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

import PhotosUI
import SwiftUI
import UIKit

/// 实名认证页面，展示审核状态并允许提交基础实名资料。
struct RealNameAuthView: View {
    @Environment(AccountContext.self) private var accountContext
    @Environment(ProfileAPI.self) private var profileAPI
    @Environment(OSSUploadService.self) private var ossUploadService
    @Environment(ToastCenter.self) private var toastCenter
    @Environment(\.globalLoading) private var globalLoading
    @State private var viewModel = RealNameAuthViewModel()
    @State private var pickedFrontItem: PhotosPickerItem?
    @State private var pickedBackItem: PhotosPickerItem?

    var body: some View {
        ScrollView {
            VStack(spacing: 14) {
                auditStatusPanel
                identityCard
                privilegeCard
                tipsCard
            }
            .padding(.horizontal, 16)
            .padding(.top, 16)
            .padding(.bottom, 34)
        }
        .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
        .navigationTitle("实名认证")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await loadInfo()
        }
        .onChange(of: pickedFrontItem) { _, item in
            Task { await prepareIdentityImage(from: item, side: .front) }
        }
        .onChange(of: pickedBackItem) { _, item in
            Task { await prepareIdentityImage(from: item, side: .back) }
        }
    }

    private var auditStatusPanel: some View {
        VStack(spacing: 14) {
            auditRow("审核状态", value: viewModel.info?.auditStatusText?.nonEmpty ?? viewModel.auditStatusText(viewModel.info?.auditStatus ?? 0))
            auditRow("审核人：", value: viewModel.info?.auditor?.name.nonEmpty ?? "--")
            auditRow("审核时间：", value: viewModel.info?.auditAt?.nonEmpty ?? "--")
            auditRow("审核备注：", value: viewModel.info?.rejectReason?.nonEmpty ?? "--")
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 22)
        .background(Color(hex: 0xEAF4FF), in: RoundedRectangle(cornerRadius: 14))
    }

    /// 构造审核信息行。
    private func auditRow(_ title: String, value: String) -> some View {
        HStack(alignment: .top) {
            Text(title)
                .font(.system(size: 16, weight: .semibold))
                .foregroundStyle(Color(hex: 0x1687D9))
            Spacer(minLength: 20)
            Text(value)
                .font(.system(size: 16, weight: .medium))
                .foregroundStyle(Color(hex: 0x1687D9))
                .multilineTextAlignment(.trailing)
        }
    }

    private var identityCard: some View {
        VStack(alignment: .leading, spacing: 14) {
            identityImageSection(
                title: "身份证国徽面",
                side: .back,
                pickedItem: $pickedBackItem,
                pendingData: viewModel.pendingBackImageData,
                remoteURL: viewModel.backUrl,
                progress: viewModel.backUploadProgress
            )
            identityImageSection(
                title: "身份证人像面",
                side: .front,
                pickedItem: $pickedFrontItem,
                pendingData: viewModel.pendingFrontImageData,
                remoteURL: viewModel.frontUrl,
                progress: viewModel.frontUploadProgress
            )
            formField("姓名", text: realNameBinding, placeholder: "请输入姓名")
            formField("身份证号码", text: idCardNoBinding, placeholder: "请输入身份证号码")
            validitySection
            if shouldShowSmsSection {
                smsSection
            }
            submitButton
            statusBanner
        }
        .padding(.horizontal, 18)
        .padding(.vertical, 20)
        .background(.white, in: RoundedRectangle(cornerRadius: 14))
    }

    /// 构造证件图片预览区域。
    private func identityImageSection(
        title: String,
        side: RealNameImageSide,
        pickedItem: Binding<PhotosPickerItem?>,
        pendingData: Data?,
        remoteURL: String,
        progress: Int?
    ) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            Text(title)
                .font(.system(size: 17, weight: .semibold))
                .foregroundStyle(Color(hex: 0x222222))
            PhotosPicker(selection: pickedItem, matching: .images) {
                imagePreview(side: side, pendingData: pendingData, remoteURL: remoteURL, progress: progress)
            }
            .buttonStyle(.plain)
            .disabled(viewModel.submitting || viewModel.info?.verified == true)
        }
    }

    private var validitySection: some View {
        VStack(alignment: .leading, spacing: 10) {
            HStack(spacing: 10) {
                Text("有效期")
                    .font(.system(size: 17, weight: .semibold))
                    .foregroundStyle(Color(hex: 0x222222))
                Spacer()
                Button {
                    viewModel.isLongValid.toggle()
                } label: {
                    HStack(spacing: 6) {
                        Image(systemName: viewModel.isLongValid ? "checkmark.circle.fill" : "circle")
                            .font(.system(size: 18, weight: .semibold))
                        Text("长期有效")
                            .font(.system(size: 15))
                    }
                    .foregroundStyle(viewModel.isLongValid ? AppDesign.primary : Color(hex: 0x8EA0AF))
                }
                .buttonStyle(.plain)
            }
            HStack(spacing: 12) {
                dateField(selection: startDateBinding)
                dateField(selection: endDateBinding)
                    .disabled(viewModel.isLongValid)
                    .opacity(viewModel.isLongValid ? 0.45 : 1)
            }
        }
    }

    private var smsSection: some View {
        HStack(spacing: 10) {
            TextField("", text: smsCodeBinding, prompt: Text("请输入短信验证码").foregroundColor(AppDesign.placeholder))
                .keyboardType(.numberPad)
                .font(.system(size: 16))
                .appInputFieldStyle(cornerRadius: 8, minHeight: 48)
            Button {
                Task { await sendCode() }
            } label: {
                Text(viewModel.sendingCode ? "发送中" : "获取验证码")
                    .font(.system(size: 14, weight: .medium))
                    .foregroundStyle(viewModel.sendingCode ? Color(hex: 0x9CA3AF) : .white)
                    .frame(width: 104, height: 48)
                    .background(viewModel.sendingCode ? Color(hex: 0xEEF2F7) : AppDesign.primary, in: RoundedRectangle(cornerRadius: 8))
            }
            .buttonStyle(.plain)
            .disabled(viewModel.sendingCode)
        }
    }

    private var submitButton: some View {
        Button {
            Task { await submit() }
        } label: {
            Text(viewModel.submitting ? "提交中..." : "下一步")
                .font(.system(size: 18, weight: .semibold))
                .foregroundStyle(.white)
                .frame(maxWidth: .infinity)
                .frame(height: 52)
                .background(canSubmit ? AppDesign.primary : Color(hex: 0xC9CED6), in: RoundedRectangle(cornerRadius: 10))
        }
        .buttonStyle(.plain)
        .disabled(!canSubmit || viewModel.submitting)
    }

    @ViewBuilder
    private var statusBanner: some View {
        if let statusMessage = viewModel.statusMessage {
            HStack(spacing: 6) {
                Image(systemName: statusMessageIsSuccess ? "checkmark.circle.fill" : "exclamationmark.triangle.fill")
                    .font(.system(size: 12))
                Text(statusMessage)
                    .font(.system(size: 13))
            }
            .foregroundStyle(statusMessageIsSuccess ? AppDesign.success : AppDesign.warning)
            .padding(.horizontal, 10)
            .frame(minHeight: 34, alignment: .leading)
            .background((statusMessageIsSuccess ? AppDesign.success : AppDesign.warning).opacity(0.12), in: RoundedRectangle(cornerRadius: 8))
        }
    }

    private var privilegeCard: some View {
        VStack(alignment: .leading, spacing: 22) {
            Text("实名认证特权")
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(Color(hex: 0x222222))
            privilegeRow(icon: "checkmark.circle.fill", title: "开启接单权限", message: "完成实名认证后可立即接单，实名状态对游客可见")
            privilegeRow(icon: "person.3.fill", title: "加入营销群", message: "专业摄影师交流群，获取更多流量与技术支持")
            privilegeRow(icon: "map.fill", title: "景区选择权限", message: "可自主选择运营景区，获得独家运营资源")
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 22)
        .background(.white, in: RoundedRectangle(cornerRadius: 14))
    }

    /// 构造认证特权行。
    private func privilegeRow(icon: String, title: String, message: String) -> some View {
        HStack(alignment: .top, spacing: 14) {
            Image(systemName: icon)
                .font(.system(size: 18, weight: .semibold))
                .foregroundStyle(.white)
                .frame(width: 30, height: 30)
                .background(AppDesign.primary, in: Circle())
            VStack(alignment: .leading, spacing: 4) {
                Text(title)
                    .font(.system(size: 17, weight: .semibold))
                    .foregroundStyle(Color(hex: 0x333333))
                Text(message)
                    .font(.system(size: 14))
                    .foregroundStyle(Color(hex: 0x777777))
                    .fixedSize(horizontal: false, vertical: true)
            }
        }
    }

    private var tipsCard: some View {
        VStack(alignment: .leading, spacing: 14) {
            Text("温馨提示:")
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(Color(hex: 0x333333))
            tipText("请确保填写的信息真实有效")
            tipText("身份信息仅用于实名认证，我们将严格保护您的隐私")
            tipText("如有疑问请联系客服")
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 22)
        .background(.white, in: RoundedRectangle(cornerRadius: 14))
    }

    /// 构造温馨提示行。
    private func tipText(_ text: String) -> some View {
        HStack(alignment: .top, spacing: 8) {
            Text("-")
            Text(text)
                .fixedSize(horizontal: false, vertical: true)
        }
        .font(.system(size: 15))
        .foregroundStyle(Color(hex: 0x666666))
    }

    /// 构造证件图片预览。
    private func imagePreview(side: RealNameImageSide, pendingData: Data?, remoteURL: String, progress: Int?) -> some View {
        ZStack {
            if let pendingData, let image = UIImage(data: pendingData) {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                RemoteImage(urlString: remoteURL, contentMode: .fit) {
                    placeholderImageContent(side: side)
                }
            }

            if let progress {
                ZStack {
                    RoundedRectangle(cornerRadius: 8)
                        .fill(.black.opacity(0.32))
                    Text("\(progress)%")
                        .font(.system(size: 17, weight: .semibold))
                        .foregroundStyle(.white)
                }
            }
        }
        .frame(maxWidth: .infinity)
        .frame(height: 166)
        .background(Color(hex: 0xFAFAFA))
        .clipShape(RoundedRectangle(cornerRadius: 8))
        .overlay(
            RoundedRectangle(cornerRadius: 8)
                .stroke(Color(hex: 0xE0E0E0), style: StrokeStyle(lineWidth: 1, dash: [5, 4]))
        )
    }

    /// 构造证件图片空状态内容。
    private func placeholderImageContent(side: RealNameImageSide) -> some View {
        ZStack {
            Color(hex: 0xF3F6FA)
            VStack(spacing: 8) {
                Image(systemName: "photo.badge.plus")
                    .font(.system(size: 26, weight: .semibold))
                    .foregroundStyle(Color(hex: 0x8A94A6))
                Text(side == .front ? "选择身份证人像面" : "选择身份证国徽面")
                    .font(.system(size: 14, weight: .medium))
                    .foregroundStyle(Color(hex: 0x8A94A6))
            }
        }
    }

    /// 构造文本输入行。
    private func formField(_ title: String, text: Binding<String>, placeholder: String) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(title)
                .font(.system(size: 17, weight: .semibold))
                .foregroundStyle(Color(hex: 0x222222))
            TextField("", text: text, prompt: Text(placeholder).foregroundColor(AppDesign.placeholder))
                .font(.system(size: 16))
                .foregroundStyle(Color(hex: 0x333333))
                .appInputFieldStyle(cornerRadius: 8, minHeight: 54)
        }
    }

    /// 构造日期选择器。
    private func dateField(selection: Binding<Date>) -> some View {
        DatePicker("", selection: selection, displayedComponents: .date)
            .labelsHidden()
            .datePickerStyle(.compact)
            .font(.system(size: 16))
            .frame(maxWidth: .infinity)
            .frame(height: 54)
            .background(Color(hex: 0xF1F1F1), in: RoundedRectangle(cornerRadius: 6))
    }

    private var canSubmit: Bool {
        viewModel.validationMessage == nil && !viewModel.submitting
    }

    private var shouldShowSmsSection: Bool {
        !viewModel.smsCode.isEmpty || viewModel.info?.verified != true
    }

    private var statusMessageIsSuccess: Bool {
        guard let statusMessage = viewModel.statusMessage else { return false }
        return statusMessage.contains("成功") || statusMessage.contains("已发送") || statusMessage.contains("已提交")
    }

    private var realNameBinding: Binding<String> {
        Binding(get: { viewModel.realName }, set: { viewModel.realName = $0 })
    }

    private var idCardNoBinding: Binding<String> {
        Binding(get: { viewModel.idCardNo }, set: { viewModel.idCardNo = $0 })
    }

    private var smsCodeBinding: Binding<String> {
        Binding(get: { viewModel.smsCode }, set: { viewModel.smsCode = $0 })
    }

    private var startDateBinding: Binding<Date> {
        Binding(get: { viewModel.startDate }, set: { viewModel.startDate = $0 })
    }

    private var endDateBinding: Binding<Date> {
        Binding(get: { viewModel.endDate }, set: { viewModel.endDate = $0 })
    }

    /// 拉取实名认证信息。
    private func loadInfo() async {
        do {
            try await globalLoading.withOptionalLoading(viewModel.info == nil, message: "加载中...") {
                try await viewModel.load(api: profileAPI)
            }
        } catch is CancellationError {
            return
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 发送验证码。
    private func sendCode() async {
        do {
            try await viewModel.sendCode(api: profileAPI)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 提交实名资料。
    private func submit() async {
        do {
            try await globalLoading.withLoading(message: "提交中...") {
                try await viewModel.submit(
                    api: profileAPI,
                    uploader: ossUploadService,
                    scenicId: accountContext.currentScenic?.id ?? 0
                )
            }
        } catch {
            viewModel.statusMessage = error.localizedDescription
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 处理用户选择的证件图片，并生成待上传数据。
    private func prepareIdentityImage(from item: PhotosPickerItem?, side: RealNameImageSide) async {
        guard let item else { return }
        defer {
            switch side {
            case .front:
                pickedFrontItem = nil
            case .back:
                pickedBackItem = nil
            }
        }
        do {
            guard let data = try await item.loadTransferable(type: Data.self) else {
                toastCenter.show("请选择有效的证件图片")
                return
            }
            try viewModel.prepareIdentityImage(data: data, side: side)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }
}

private extension String {
    /// 去除空白后返回非空字符串。
    var nonEmpty: String? {
        let text = trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? nil : text
    }
}
