//
//  DepositOrderViews.swift
//  suixinkan
//
//  Created by Codex on 2026/6/25.
//

import SwiftUI

/// 押金订单入口页，支持订单号查询、列表分页、核销和退款。
struct DepositOrderEntryView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.ordersAPI) private var ordersAPI
    @EnvironmentObject private var router: RouterPath
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = DepositOrderListViewModel()
    @State private var orderNumber = ""
    @State private var pendingWriteOff: DepositOrderListItem?
    @State private var pendingRefund: DepositOrderListItem?
    @State private var refundReason = ""

    var body: some View {
        List {
            Section("订单查询") {
                TextField("请输入押金订单号", text: $orderNumber)
                    .textInputAutocapitalization(.never)
                    .autocorrectionDisabled(true)

                Button("查看订单详情") {
                    navigateToDetail(orderNumber)
                }
                .disabled(orderNumber.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
            }

            Section {
                if viewModel.orders.isEmpty {
                    AppContentUnavailableView("暂无押金订单", systemImage: "doc.text.magnifyingglass")
                        .frame(maxWidth: .infinity, minHeight: 180)
                } else {
                    ForEach(viewModel.orders) { item in
                        DepositOrderRow(
                            item: item,
                            isOperating: viewModel.operatingOrderNumber == item.orderNumber,
                            onDetail: { navigateToDetail(item.orderNumber) },
                            onWriteOff: { pendingWriteOff = item },
                            onRefund: { pendingRefund = item }
                        )
                    }

                    if viewModel.hasMore {
                        Button(viewModel.loadingMore ? "加载中..." : "加载更多") {
                            Task { await viewModel.reload(api: ordersAPI, scenicId: accountContext.currentScenic?.id, reset: false) }
                        }
                        .frame(maxWidth: .infinity, alignment: .center)
                        .disabled(viewModel.loadingMore)
                    }
                }
            } header: {
                HStack {
                    Text("押金订单列表")
                    Spacer()
                    Text("\(viewModel.orders.count)/\(viewModel.total)")
                }
            }
        }
        .listStyle(.insetGrouped)
        .scrollContentBackground(.hidden)
        .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
        .navigationTitle("押金订单")
        .navigationBarTitleDisplayMode(.inline)
        .refreshable { await reload(showLoading: false) }
        .task { await reload(showLoading: true) }
        .confirmationDialog("确认核销该押金订单？", isPresented: writeOffBinding, titleVisibility: .visible) {
            Button("确认核销") {
                guard let pendingWriteOff else { return }
                Task { await writeOff(pendingWriteOff) }
            }
            Button("取消", role: .cancel) {}
        } message: {
            Text(pendingWriteOff?.orderNumber ?? "")
        }
        .alert("申请退款", isPresented: refundBinding) {
            TextField("请输入退款原因", text: $refundReason)
            Button("提交") {
                guard let pendingRefund else { return }
                Task { await refund(pendingRefund) }
            }
            Button("取消", role: .cancel) {
                pendingRefund = nil
                refundReason = ""
            }
        } message: {
            Text("请填写退款原因后提交。")
        }
        .alert("提示", isPresented: errorBinding) {
            Button("知道了", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "")
        }
    }

    private var writeOffBinding: Binding<Bool> {
        Binding(
            get: { pendingWriteOff != nil },
            set: { if !$0 { pendingWriteOff = nil } }
        )
    }

    private var refundBinding: Binding<Bool> {
        Binding(
            get: { pendingRefund != nil },
            set: { if !$0 { pendingRefund = nil; refundReason = "" } }
        )
    }

    private var errorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.errorMessage != nil },
            set: { if !$0 { viewModel.clearError() } }
        )
    }

    /// 跳转到押金订单详情页。
    private func navigateToDetail(_ rawOrderNumber: String) {
        let text = rawOrderNumber.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else { return }
        router.navigate(to: .orders(.depositDetail(orderNumber: text)))
    }

    /// 刷新押金订单列表。
    private func reload(showLoading: Bool) async {
        if showLoading {
            await globalLoading.withLoading {
                await viewModel.reload(api: ordersAPI, scenicId: accountContext.currentScenic?.id, reset: true)
            }
        } else {
            await viewModel.reload(api: ordersAPI, scenicId: accountContext.currentScenic?.id, reset: true)
        }
    }

    /// 核销押金订单并提示结果。
    private func writeOff(_ item: DepositOrderListItem) async {
        pendingWriteOff = nil
        let success = await viewModel.writeOff(api: ordersAPI, scenicId: accountContext.currentScenic?.id, orderNumber: item.orderNumber)
        if success {
            toastCenter.show("核销成功")
        }
    }

    /// 提交押金订单退款并提示结果。
    private func refund(_ item: DepositOrderListItem) async {
        let reason = refundReason
        pendingRefund = nil
        refundReason = ""
        let success = await viewModel.refund(api: ordersAPI, scenicId: accountContext.currentScenic?.id, orderNumber: item.orderNumber, reason: reason)
        if success {
            toastCenter.show("退款申请已提交")
        }
    }
}

/// 押金订单列表行，展示订单状态和操作按钮。
private struct DepositOrderRow: View {
    let item: DepositOrderListItem
    let isOperating: Bool
    let onDetail: () -> Void
    let onWriteOff: () -> Void
    let onRefund: () -> Void

    var body: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text(item.orderNumber.isEmpty ? "--" : item.orderNumber)
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Spacer()
                Text(item.statusName.isEmpty ? "状态\(item.status)" : item.statusName)
                    .font(.system(size: AppMetrics.FontSize.caption, weight: .medium))
                    .foregroundStyle(statusColor)
                    .padding(.horizontal, AppMetrics.Spacing.small)
                    .frame(height: 24)
                    .background(statusColor.opacity(0.12), in: Capsule())
            }

            HStack {
                Text("¥\(item.amount.isEmpty ? "0.00" : item.amount)")
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.primary)
                Spacer()
                Text(item.createdAt.isEmpty ? "--" : item.createdAt)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }

            if !item.userPhone.isEmpty {
                Text("手机号：\(item.userPhone)")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }

            HStack(spacing: AppMetrics.Spacing.small) {
                rowButton("详情", tint: AppDesign.primary, action: onDetail)
                rowButton(isOperating ? "处理中..." : "核销", tint: Color(hex: 0x22C55E), disabled: isOperating, action: onWriteOff)
                rowButton(isOperating ? "处理中..." : "退款", tint: Color(hex: 0xF59E0B), disabled: isOperating, action: onRefund)
            }
        }
        .padding(.vertical, AppMetrics.Spacing.xSmall)
    }

    private var statusColor: Color {
        switch item.status {
        case 20:
            return AppDesign.primary
        case 30:
            return Color(hex: 0x22C55E)
        case 50:
            return Color(hex: 0xEF4444)
        default:
            return Color(hex: 0xF59E0B)
        }
    }

    /// 构建列表行操作按钮。
    private func rowButton(_ title: String, tint: Color, disabled: Bool = false, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                .foregroundStyle(disabled ? AppDesign.textSecondary : tint)
                .frame(maxWidth: .infinity)
                .frame(height: 34)
                .background((disabled ? Color(hex: 0xEEF2F7) : tint.opacity(0.12)), in: RoundedRectangle(cornerRadius: 8))
        }
        .buttonStyle(.plain)
        .disabled(disabled)
    }
}

/// 押金订单详情页，展示订单基础信息和拍摄点列表。
struct DepositOrderDetailView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.ordersAPI) private var ordersAPI
    @EnvironmentObject private var router: RouterPath
    @Environment(\.globalLoading) private var globalLoading

    let orderNumber: String
    @StateObject private var viewModel = DepositOrderDetailViewModel()

    var body: some View {
        List {
            if let detail = viewModel.detail {
                Section("订单信息") {
                    OrderDetailValueRow(title: "订单号", value: detail.orderNumber)
                    OrderDetailValueRow(title: "订单状态", value: detail.orderStatusName)
                    OrderDetailValueRow(title: "订单类型", value: detail.orderTypeLabel)
                    OrderDetailValueRow(title: "项目名称", value: detail.projectName)
                    OrderDetailValueRow(title: "订单金额", value: "¥\(detail.actualPayAmount.isEmpty ? "0.00" : detail.actualPayAmount)")
                    OrderDetailValueRow(title: "退款金额", value: "¥\(detail.actualRefundAmount.isEmpty ? "0" : detail.actualRefundAmount)")
                    OrderDetailValueRow(title: "手机号", value: detail.phone)
                    OrderDetailValueRow(title: "下单时间", value: detail.createdAt)
                    OrderDetailValueRow(title: "付款时间", value: detail.payTime)
                    OrderDetailValueRow(title: "完成时间", value: detail.completeTime)
                }

                if let projectInfo = detail.multiTravel?.projectInfo {
                    Section("项目配置") {
                        OrderDetailValueRow(title: "打卡点数", value: "\(projectInfo.settleSpotNum)")
                        OrderDetailValueRow(title: "单点底片", value: "\(projectInfo.singleSpotMaterialNum)")
                        OrderDetailValueRow(title: "单点精修", value: "\(projectInfo.singleSpotPhotoNum)")
                        OrderDetailValueRow(title: "单点视频", value: "\(projectInfo.singleSpotVideoNum)")
                    }
                }

                Section("拍摄详情") {
                    let shootingList = detail.multiTravel?.shootingList ?? []
                    if shootingList.isEmpty {
                        AppContentUnavailableView("暂无拍摄记录", systemImage: "photo.stack")
                    } else {
                        ForEach(shootingList) { item in
                            Button {
                                router.navigate(
                                    to: .orders(
                                        .depositShootingInfo(
                                            orderNumber: detail.orderNumber,
                                            scenicSpotId: item.scenicSpotId,
                                            photogUid: item.photogUid
                                        )
                                    )
                                )
                            } label: {
                                DepositShootingPointRow(item: item)
                            }
                        }
                    }
                }
            } else {
                Section {
                    AppContentUnavailableView("暂无订单详情", systemImage: "doc.text.magnifyingglass")
                        .frame(maxWidth: .infinity, minHeight: 220)
                }
            }
        }
        .listStyle(.insetGrouped)
        .scrollContentBackground(.hidden)
        .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
        .navigationTitle("押金订单详情")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await globalLoading.withLoading {
                await viewModel.load(api: ordersAPI, storeId: accountContext.currentStore?.id, orderNumber: orderNumber)
            }
        }
        .alert("提示", isPresented: errorBinding) {
            Button("知道了", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "")
        }
    }

    private var errorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.errorMessage != nil },
            set: { if !$0 { viewModel.clearError() } }
        )
    }
}

/// 押金订单拍摄点行。
private struct DepositShootingPointRow: View {
    let item: StoreOrderShootingListItem

    var body: some View {
        HStack {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Text(item.photogName.isEmpty ? "摄影师未分配" : item.photogName)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            Spacer()
            VStack(alignment: .trailing, spacing: AppMetrics.Spacing.xSmall) {
                Text(item.status == 2 ? "已拍摄" : "待拍摄")
                    .font(.system(size: AppMetrics.FontSize.caption, weight: .medium))
                    .foregroundStyle(item.status == 2 ? Color(hex: 0x22C55E) : AppDesign.primary)
                Text(String(format: "评分 %.1f", max(item.startAvg, item.start)))
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            Image(systemName: "chevron.right")
                .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                .foregroundStyle(AppDesign.textSecondary)
        }
    }

    private var title: String {
        let text = item.scenicSpotName.isEmpty ? item.staffName : item.scenicSpotName
        return text.isEmpty ? "未命名打卡点" : text
    }
}

/// 押金拍摄信息页，展示评价、底片和成片。
struct DepositOrderShootingInfoView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.ordersAPI) private var ordersAPI
    @Environment(\.globalLoading) private var globalLoading

    let orderNumber: String
    let scenicSpotId: Int
    let photogUid: Int

    @StateObject private var viewModel = DepositOrderShootingInfoViewModel()
    @State private var selectedTab: DepositShootingMediaTab = .negative

    var body: some View {
        List {
            if let detail = viewModel.detail {
                Section("拍摄点") {
                    OrderDetailValueRow(title: "名称", value: detail.scenicSpotName)
                    OrderDetailValueRow(title: "订单类型", value: detail.orderTypeName)
                }

                Section("评分与评价") {
                    if let comment = detail.orderComment {
                        RatingRow(title: "拍摄满意度", score: comment.starShooting)
                        RatingRow(title: "修图满意度", score: comment.starRetouching)
                        RatingRow(title: "景区满意度", score: comment.starScenery)
                        RatingRow(title: "服务满意度", score: comment.starService)
                        RatingRow(title: "相机满意度", score: comment.starCamera)
                        Text(comment.content.isEmpty ? "暂无评价内容" : comment.content)
                            .font(.system(size: AppMetrics.FontSize.subheadline))
                            .foregroundStyle(AppDesign.textSecondary)
                    } else {
                        AppContentUnavailableView("暂无评价信息", systemImage: "star")
                    }
                }

                Section {
                    Picker("媒体类型", selection: $selectedTab) {
                        Text("底片").tag(DepositShootingMediaTab.negative)
                        Text("成片").tag(DepositShootingMediaTab.complete)
                    }
                    .pickerStyle(.segmented)

                    OrderMediaGrid(files: selectedTab == .negative ? detail.materialList : detail.completeList)
                } header: {
                    Text("媒体文件")
                }
            } else {
                Section {
                    AppContentUnavailableView("暂无拍摄信息", systemImage: "photo.stack")
                        .frame(maxWidth: .infinity, minHeight: 220)
                }
            }
        }
        .listStyle(.insetGrouped)
        .scrollContentBackground(.hidden)
        .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
        .navigationTitle("拍摄信息")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await globalLoading.withLoading {
                await viewModel.load(
                    api: ordersAPI,
                    storeId: accountContext.currentStore?.id,
                    orderNumber: orderNumber,
                    scenicSpotId: scenicSpotId,
                    photogUid: photogUid
                )
            }
        }
        .alert("提示", isPresented: errorBinding) {
            Button("知道了", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "")
        }
    }

    private var errorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.errorMessage != nil },
            set: { if !$0 { viewModel.clearError() } }
        )
    }
}

/// 历史拍摄信息页，展示多点位拍摄媒体。
struct HistoricalShootingInfoView: View {
    @Environment(\.ordersAPI) private var ordersAPI
    @Environment(\.globalLoading) private var globalLoading

    let orderNumber: String
    @StateObject private var viewModel = HistoricalShootingInfoViewModel()

    var body: some View {
        List {
            Section("订单") {
                OrderDetailValueRow(title: "订单号", value: orderNumber)
                OrderDetailValueRow(title: "项目名称", value: viewModel.projectName)
                OrderDetailValueRow(title: "项目类型", value: viewModel.projectTypeName)
            }

            Section("历史拍摄") {
                if viewModel.spots.isEmpty {
                    AppContentUnavailableView("暂无历史拍摄信息", systemImage: "photo.on.rectangle")
                        .frame(maxWidth: .infinity, minHeight: 220)
                } else {
                    ForEach(viewModel.spots) { spot in
                        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                            HStack {
                                Label(spot.scenicSpotName.isEmpty ? "未命名打卡点" : spot.scenicSpotName, systemImage: "mappin.and.ellipse")
                                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                                    .foregroundStyle(AppDesign.primary)
                                Spacer()
                                Text("摄影师：\(spot.photographerDisplayName)")
                                    .font(.system(size: AppMetrics.FontSize.caption))
                                    .foregroundStyle(AppDesign.textSecondary)
                            }
                            OrderMediaGrid(files: spot.files)
                        }
                        .padding(.vertical, AppMetrics.Spacing.xSmall)
                    }
                }
            }
        }
        .listStyle(.insetGrouped)
        .scrollContentBackground(.hidden)
        .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
        .navigationTitle("历史拍摄")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await globalLoading.withLoading {
                await viewModel.load(api: ordersAPI, orderNumber: orderNumber)
            }
        }
        .alert("提示", isPresented: errorBinding) {
            Button("知道了", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "")
        }
    }

    private var errorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.errorMessage != nil },
            set: { if !$0 { viewModel.clearError() } }
        )
    }
}

/// 拍摄媒体类型。
private enum DepositShootingMediaTab: Hashable {
    case negative
    case complete
}

/// 通用订单详情键值行。
private struct OrderDetailValueRow: View {
    let title: String
    let value: String

    var body: some View {
        HStack(alignment: .top) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
            Spacer(minLength: AppMetrics.Spacing.medium)
            Text(value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "--" : value)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                .foregroundStyle(AppDesign.textPrimary)
                .multilineTextAlignment(.trailing)
        }
    }
}

/// 评分展示行。
private struct RatingRow: View {
    let title: String
    let score: Int

    var body: some View {
        HStack {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
            Spacer()
            Text(String(repeating: "★", count: max(score, 0)))
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(Color(hex: 0xF59E0B))
        }
    }
}

/// 订单媒体网格，统一展示图片和视频缩略图。
private struct OrderMediaGrid: View {
    let files: [OrderMediaFile]

    private let columns = [
        GridItem(.flexible(), spacing: AppMetrics.Spacing.small),
        GridItem(.flexible(), spacing: AppMetrics.Spacing.small),
        GridItem(.flexible(), spacing: AppMetrics.Spacing.small)
    ]

    var body: some View {
        if files.isEmpty {
            AppContentUnavailableView("暂无媒体文件", systemImage: "photo")
                .frame(maxWidth: .infinity, minHeight: 140)
        } else {
            LazyVGrid(columns: columns, spacing: AppMetrics.Spacing.small) {
                ForEach(files) { file in
                    Link(destination: URL(string: file.fileUrl) ?? APIEnvironment.production.baseURL) {
                        ZStack(alignment: .bottomTrailing) {
                            RemoteImage(urlString: file.previewURLString) {
                                RoundedRectangle(cornerRadius: 8)
                                    .fill(AppDesign.primarySoft)
                            }
                            .frame(height: 88)
                            .clipShape(RoundedRectangle(cornerRadius: 8))

                            if file.isVideo {
                                Image(systemName: "play.circle.fill")
                                    .font(.system(size: 18, weight: .semibold))
                                    .foregroundStyle(.white)
                                    .shadow(radius: 2)
                                    .padding(AppMetrics.Spacing.xSmall)
                            }
                        }
                    }
                    .buttonStyle(.plain)
                }
            }
        }
    }
}
