//
//  WalletView.swift
//  suixinkan
//
//  Created by Codex on 2026/6/22.
//

import Combine
import PhotosUI
import SwiftUI

/// 钱包首页，展示钱包汇总、收益明细、提现记录和钱包二级入口。
struct WalletView: View {
    @Environment(AccountContext.self) private var accountContext
    @Environment(WalletAPI.self) private var walletAPI
    @Environment(ProfileAPI.self) private var profileAPI
    @Environment(ToastCenter.self) private var toastCenter

    @State private var viewModel = WalletViewModel()
    @State private var route: WalletRoute?

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                summaryCard
                walletActions
                ledgerControls
                ledgerList
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.pageVertical)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("我的钱包")
        .navigationBarTitleDisplayMode(.inline)
        .navigationDestination(item: $route) { route in
            switch route {
            case .withdrawApply:
                WithdrawApplyView()
            case .bankCardSettings:
                WithdrawalSettingsView()
            case .pointsRedemption:
                PointsRedemptionView()
            case .realNameAuth:
                RealNameAuthView()
            }
        }
        .task {
            await viewModel.loadInitial(api: walletAPI, staffId: staffId)
        }
        .refreshable {
            await viewModel.loadInitial(api: walletAPI, staffId: staffId)
        }
        .onChange(of: viewModel.errorMessage) { _, message in
            if let message {
                toastCenter.show(message)
            }
        }
    }

    /// 当前用户 staffId，优先使用账号快照里的 userId。
    private var staffId: Int? {
        Int(accountContext.profile?.userId ?? "")
    }

    /// 钱包汇总卡片。
    private var summaryCard: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            HStack {
                VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
                    Text("可提现金额")
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(.white.opacity(0.86))
                    Text(viewModel.withdrawableText)
                        .font(.system(size: AppMetrics.FontSize.largeTitle, weight: .bold))
                        .foregroundStyle(.white)
                }
                Spacer()
                if viewModel.isLoadingSummary {
                    ProgressView()
                        .tint(.white)
                }
            }

            HStack(spacing: AppMetrics.Spacing.medium) {
                walletSummaryItem(title: "累计金额", value: viewModel.totalAmountText)
                walletSummaryItem(title: "当前余额", value: viewModel.currentBalanceText)
                walletSummaryItem(title: "可兑换积分", value: "\(viewModel.pointsOverview?.withdrawnPoints ?? 0)")
            }
        }
        .padding(AppMetrics.Spacing.large)
        .background(AppDesign.primary, in: RoundedRectangle(cornerRadius: 8))
    }

    /// 钱包快捷操作。
    private var walletActions: some View {
        HStack(spacing: AppMetrics.Spacing.small) {
            walletActionButton(title: "提现", icon: "banknote") {
                Task {
                    let decision = await viewModel.resolveWithdrawDecision(profileAPI: profileAPI, walletAPI: walletAPI)
                    switch decision {
                    case .route(let nextRoute):
                        route = nextRoute
                    case .message(let message):
                        toastCenter.show(message)
                    }
                }
            }
            walletActionButton(title: "银行卡", icon: "creditcard") {
                route = .bankCardSettings
            }
            walletActionButton(title: "积分兑换", icon: "giftcard") {
                route = .pointsRedemption
            }
        }
    }

    /// 明细筛选控件。
    private var ledgerControls: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            Picker("明细类型", selection: Binding(
                get: { viewModel.selectedTab },
                set: { tab in Task { await viewModel.selectTab(tab, api: walletAPI) } }
            )) {
                ForEach(WalletLedgerTab.allCases) { tab in
                    Text(tab.title).tag(tab)
                }
            }
            .pickerStyle(.segmented)

            if viewModel.selectedTab == .earnings {
                HStack {
                    ForEach(WalletDateFilter.allCases) { filter in
                        Button {
                            Task { await viewModel.selectFilter(filter, api: walletAPI) }
                        } label: {
                            Text(filter.title)
                                .font(.system(size: AppMetrics.FontSize.footnote, weight: .medium))
                                .foregroundStyle(viewModel.selectedFilter == filter ? .white : AppDesign.primary)
                                .padding(.horizontal, AppMetrics.Spacing.small)
                                .padding(.vertical, AppMetrics.Spacing.xSmall)
                                .background(viewModel.selectedFilter == filter ? AppDesign.primary : AppDesign.primarySoft, in: Capsule())
                        }
                    }
                    Spacer()
                }
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: 8))
    }

    /// 钱包明细列表。
    @ViewBuilder
    private var ledgerList: some View {
        if viewModel.selectedTab == .earnings {
            LazyVStack(spacing: AppMetrics.Spacing.small) {
                ForEach(viewModel.earningsGroups) { group in
                    walletSection(title: group.date, subtitle: "¥\(group.dayAmount) / \(group.dayPoints)分") {
                        ForEach(group.items) { item in
                            ledgerRow(title: item.typeLabel.isEmpty ? "收益" : item.typeLabel, subtitle: item.createdAt, amount: "+¥\(item.amount)", extra: item.orderNumberSuffix)
                        }
                    }
                }
                loadMoreButton(enabled: viewModel.canLoadMoreEarnings)
            }
        } else {
            LazyVStack(spacing: AppMetrics.Spacing.small) {
                ForEach(viewModel.withdrawRecords) { record in
                    ledgerRow(title: record.statusLabel, subtitle: record.createdAt, amount: "-¥\(record.amount)", extra: record.expectedAt ?? "")
                        .padding(AppMetrics.Spacing.medium)
                        .background(.white, in: RoundedRectangle(cornerRadius: 8))
                }
                loadMoreButton(enabled: viewModel.canLoadMoreWithdraws)
            }
        }
    }

    /// 汇总子项。
    private func walletSummaryItem(title: String, value: String) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxxSmall) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(.white.opacity(0.75))
            Text(value)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(.white)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    /// 快捷操作按钮。
    private func walletActionButton(title: String, icon: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            VStack(spacing: AppMetrics.Spacing.xSmall) {
                Image(systemName: icon)
                    .font(.system(size: 22, weight: .semibold))
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.footnote, weight: .medium))
            }
            .foregroundStyle(AppDesign.primary)
            .frame(maxWidth: .infinity, minHeight: 76)
            .background(.white, in: RoundedRectangle(cornerRadius: 8))
        }
    }

    /// 白色分组卡片。
    private func walletSection<Content: View>(title: String, subtitle: String, @ViewBuilder content: () -> Content) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                Spacer()
                Text(subtitle)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            content()
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: 8))
    }

    /// 明细行。
    private func ledgerRow(title: String, subtitle: String, amount: String, extra: String) -> some View {
        HStack(alignment: .top) {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxxSmall) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Text([subtitle, extra].filter { !$0.isEmpty }.joined(separator: " · "))
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            Spacer()
            Text(amount)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(amount.hasPrefix("+") ? AppDesign.success : AppDesign.textPrimary)
        }
    }

    /// 加载更多按钮。
    @ViewBuilder
    private func loadMoreButton(enabled: Bool) -> some View {
        if enabled {
            Button {
                Task { await viewModel.loadMore(api: walletAPI) }
            } label: {
                Text(viewModel.isLoadingList ? "加载中..." : "加载更多")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                    .frame(maxWidth: .infinity, minHeight: 44)
            }
        }
    }
}

/// 提现申请页，输入金额和短信验证码后提交提现。
struct WithdrawApplyView: View {
    @Environment(WalletAPI.self) private var walletAPI
    @Environment(ToastCenter.self) private var toastCenter
    @Environment(\.dismiss) private var dismiss
    @State private var viewModel = WithdrawApplyViewModel()

    var body: some View {
        Form {
            if let info = viewModel.info {
                Section("银行卡") {
                    Text("\(info.bankCard.bankName) \(info.bankCard.cardNumber)")
                    Text("可提现金额：¥\(WalletViewModel.moneyText(info.amountWithdrawable))")
                }
            }

            Section("提现金额") {
                TextField("请输入提现金额", text: $viewModel.amountText)
                    .keyboardType(.decimalPad)
                HStack {
                    TextField("短信验证码", text: $viewModel.smsCode)
                        .keyboardType(.numberPad)
                    Button(viewModel.smsCountdown > 0 ? "\(viewModel.smsCountdown)s" : "获取验证码") {
                        Task { await viewModel.sendSms(api: walletAPI) }
                    }
                    .disabled(viewModel.smsCountdown > 0)
                }
            }

            Button(viewModel.isSubmitting ? "提交中..." : "提交提现申请") {
                Task {
                    if await viewModel.submit(api: walletAPI) {
                        toastCenter.show("提现申请已提交")
                        dismiss()
                    }
                }
            }
            .disabled(viewModel.isSubmitting)
        }
        .navigationTitle("提现申请")
        .navigationBarTitleDisplayMode(.inline)
        .task { await viewModel.load(api: walletAPI) }
        .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in
            if viewModel.smsCountdown > 0 {
                viewModel.smsCountdown -= 1
            }
        }
        .onChange(of: viewModel.errorMessage) { _, message in
            if let message {
                toastCenter.show(message)
            }
        }
    }
}

/// 银行卡设置页，使用图片选择和 OSS 上传提交银行卡资料。
struct WithdrawalSettingsView: View {
    @Environment(AccountContext.self) private var accountContext
    @Environment(WalletAPI.self) private var walletAPI
    @Environment(OSSUploadService.self) private var ossUploadService
    @Environment(ToastCenter.self) private var toastCenter
    @Environment(\.dismiss) private var dismiss

    @State private var viewModel = WithdrawalSettingsViewModel()
    @State private var frontItem: PhotosPickerItem?
    @State private var backItem: PhotosPickerItem?

    var body: some View {
        Form {
            if let bankCard = viewModel.bankCard {
                Section("审核状态") {
                    Text(bankCard.auditStatusLabel.isEmpty ? "待提交" : bankCard.auditStatusLabel)
                    if let reason = bankCard.rejectReason, !reason.isEmpty {
                        Text(reason).foregroundStyle(AppDesign.warning)
                    }
                }
            }

            Section("基础信息") {
                TextField("持卡人姓名", text: $viewModel.realName)
                TextField("银行卡号", text: $viewModel.cardNumber)
                    .keyboardType(.numberPad)
                Picker("开户银行", selection: $viewModel.bankName) {
                    Text("请选择").tag("")
                    ForEach(viewModel.banks, id: \.self) { bank in
                        Text(bank).tag(bank)
                    }
                }
                TextField("开户支行", text: $viewModel.branchName)
                Picker("省份", selection: $viewModel.provinceCode) {
                    Text("请选择").tag("")
                    ForEach(viewModel.areas) { area in
                        Text(area.name).tag(area.code)
                    }
                }
                Picker("城市", selection: $viewModel.cityCode) {
                    Text("请选择").tag("")
                    ForEach(selectedProvinceChildren) { city in
                        Text(city.name).tag(city.code)
                    }
                }
            }

            Section("银行卡照片") {
                bankCardImagePicker(title: "银行卡正面", item: $frontItem, data: viewModel.frontImageData, url: viewModel.frontImageURL)
                bankCardImagePicker(title: "银行卡反面", item: $backItem, data: viewModel.backImageData, url: viewModel.backImageURL)
                if viewModel.uploadProgress > 0 && viewModel.uploadProgress < 100 {
                    ProgressView(value: Double(viewModel.uploadProgress), total: 100)
                }
            }

            Section("短信验证码") {
                HStack {
                    TextField("请输入短信验证码", text: $viewModel.smsCode)
                        .keyboardType(.numberPad)
                    Button(viewModel.smsCountdown > 0 ? "\(viewModel.smsCountdown)s" : "获取验证码") {
                        Task { await viewModel.sendSms(api: walletAPI) }
                    }
                    .disabled(viewModel.smsCountdown > 0)
                }
            }

            Button(viewModel.isSubmitting ? "提交中..." : "提交银行卡资料") {
                Task {
                    if await viewModel.submit(api: walletAPI, uploader: ossUploadService, scenicId: accountContext.currentScenic?.id) {
                        toastCenter.show("银行卡资料已提交")
                        dismiss()
                    }
                }
            }
            .disabled(viewModel.isSubmitting)
        }
        .navigationTitle("银行卡设置")
        .navigationBarTitleDisplayMode(.inline)
        .task { await viewModel.load(api: walletAPI) }
        .onChange(of: frontItem) { _, item in
            Task { viewModel.frontImageData = try? await item?.loadTransferable(type: Data.self) }
        }
        .onChange(of: backItem) { _, item in
            Task { viewModel.backImageData = try? await item?.loadTransferable(type: Data.self) }
        }
        .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in
            if viewModel.smsCountdown > 0 {
                viewModel.smsCountdown -= 1
            }
        }
        .onChange(of: viewModel.errorMessage) { _, message in
            if let message {
                toastCenter.show(message)
            }
        }
    }

    /// 当前所选省份下的城市列表。
    private var selectedProvinceChildren: [AreaNode] {
        viewModel.areas.first { $0.code == viewModel.provinceCode }?.children ?? []
    }

    /// 银行卡图片选择行。
    private func bankCardImagePicker(title: String, item: Binding<PhotosPickerItem?>, data: Data?, url: String) -> some View {
        PhotosPicker(selection: item, matching: .images) {
            HStack(spacing: AppMetrics.Spacing.small) {
                bankCardPreview(data: data, url: url)
                    .frame(width: 88, height: 56)
                    .clipShape(RoundedRectangle(cornerRadius: 8))
                Text(title)
                Spacer()
                Image(systemName: "chevron.right")
                    .foregroundStyle(AppDesign.placeholder)
            }
        }
    }

    /// 银行卡图片预览。
    @ViewBuilder
    private func bankCardPreview(data: Data?, url: String) -> some View {
        if let data, let image = UIImage(data: data) {
            Image(uiImage: image)
                .resizable()
                .scaledToFill()
        } else {
            RemoteImage(urlString: url) {
                Rectangle()
                    .fill(AppDesign.primarySoft)
                    .overlay {
                        Image(systemName: "creditcard")
                            .foregroundStyle(AppDesign.primary)
                    }
            }
        }
    }
}

/// 积分兑换页，展示积分概览、提交兑换申请和兑换记录。
struct PointsRedemptionView: View {
    @Environment(AccountContext.self) private var accountContext
    @Environment(WalletAPI.self) private var walletAPI
    @Environment(ToastCenter.self) private var toastCenter
    @State private var viewModel = PointsRedemptionViewModel()

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                    Text("可兑换积分")
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(AppDesign.textSecondary)
                    Text("\(viewModel.overview.withdrawnPoints)")
                        .font(.system(size: AppMetrics.FontSize.largeTitle, weight: .bold))
                        .foregroundStyle(AppDesign.textPrimary)
                    HStack {
                        TextField("请输入兑换积分", text: $viewModel.pointsText)
                            .keyboardType(.numberPad)
                        Button("全部") {
                            viewModel.fillAllPoints()
                        }
                    }
                    .appInputFieldStyle(cornerRadius: 8, minHeight: AppMetrics.ControlSize.inputHeight)
                    Button(viewModel.isSubmitting ? "提交中..." : "提交兑换") {
                        Task {
                            if await viewModel.submit(api: walletAPI, staffId: staffId) {
                                toastCenter.show("积分兑换申请已提交")
                            }
                        }
                    }
                    .frame(maxWidth: .infinity, minHeight: AppMetrics.ControlSize.primaryButtonHeight)
                    .foregroundStyle(.white)
                    .background(AppDesign.primary, in: RoundedRectangle(cornerRadius: 8))
                }
                .padding(AppMetrics.Spacing.medium)
                .background(.white, in: RoundedRectangle(cornerRadius: 8))

                LazyVStack(spacing: AppMetrics.Spacing.small) {
                    ForEach(viewModel.records) { item in
                        HStack {
                            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxxSmall) {
                                Text("\(item.points) 积分")
                                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                                Text(item.createdAt)
                                    .font(.system(size: AppMetrics.FontSize.caption))
                                    .foregroundStyle(AppDesign.textSecondary)
                            }
                            Spacer()
                            Text("¥\(item.amount, specifier: "%.2f")")
                                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                        }
                        .padding(AppMetrics.Spacing.medium)
                        .background(.white, in: RoundedRectangle(cornerRadius: 8))
                    }
                    if viewModel.canLoadMore {
                        Button("加载更多") {
                            Task { await viewModel.loadMore(api: walletAPI) }
                        }
                    }
                }
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.pageVertical)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("积分兑换")
        .navigationBarTitleDisplayMode(.inline)
        .task { await viewModel.load(api: walletAPI, staffId: staffId) }
        .onChange(of: viewModel.errorMessage) { _, message in
            if let message {
                toastCenter.show(message)
            }
        }
    }

    /// 当前用户 staffId。
    private var staffId: Int? {
        Int(accountContext.profile?.userId ?? "")
    }
}
