//
//  ProfileView.swift
//  suixinkan
//
//  Created by Codex on 2026/6/20.
//

import PhotosUI
import SwiftUI
import UIKit

/// 个人信息页视图，展示用户资料、账号状态、实名认证状态和退出登录入口。
struct ProfileView: View {
    @Environment(AppSession.self) private var appSession
    @Environment(AccountContext.self) private var accountContext
    @Environment(PermissionContext.self) private var permissionContext
    @Environment(ScenicSpotContext.self) private var scenicSpotContext
    @Environment(AppRouter.self) private var appRouter
    @Environment(RouterPath.self) private var router
    @Environment(ProfileAPI.self) private var profileAPI
    @Environment(OSSUploadService.self) private var ossUploadService
    @Environment(ToastCenter.self) private var toastCenter
    @Environment(AuthSessionCoordinator.self) private var authSessionCoordinator
    @Environment(\.globalLoading) private var globalLoading
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass

    @State private var viewModel = ProfileViewModel()
    @State private var showsPasswordSheet = false
    @State private var showsLogoutConfirm = false
    @State private var pickedAvatarItem: PhotosPickerItem?
    @FocusState private var nicknameFocused: Bool

    private var contentMaxWidth: CGFloat {
        horizontalSizeClass == .regular ? 720 : .infinity
    }

    var body: some View {
        ScrollView {
            VStack(spacing: 22) {
                header
                infoCard
                logoutButton
            }
            .padding(.horizontal, 19)
            .padding(.top, 24)
            .padding(.bottom, 24)
            .frame(maxWidth: contentMaxWidth)
            .frame(maxWidth: .infinity)
        }
        .background(profileBackground.ignoresSafeArea())
        .navigationTitle("个人信息")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await reloadProfile(showToast: false)
        }
        .refreshable {
            await reloadProfile(showToast: true)
        }
        .sheet(isPresented: $showsPasswordSheet) {
            PasswordUpdateSheet { password in
                await updatePassword(password)
            }
        }
        .confirmationDialog("确认退出当前账号？", isPresented: $showsLogoutConfirm, titleVisibility: .visible) {
            Button("退出登录", role: .destructive) {
                authSessionCoordinator.logout(
                    appSession: appSession,
                    accountContext: accountContext,
                    permissionContext: permissionContext,
                    scenicSpotContext: scenicSpotContext,
                    appRouter: appRouter,
                    toastCenter: toastCenter
                )
            }
            Button("取消", role: .cancel) {}
        }
        .onChange(of: viewModel.isEditingProfile) { _, isEditing in
            guard isEditing else { return }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
                nicknameFocused = true
            }
        }
        .onChange(of: pickedAvatarItem) { _, item in
            Task { await prepareAvatarImage(from: item) }
        }
    }

    private var profileBackground: some View {
        LinearGradient(
            colors: [
                Color(hex: 0xF7FAFF),
                Color(hex: 0xF3F7FD),
                Color.white
            ],
            startPoint: .top,
            endPoint: .bottom
        )
    }

    private var header: some View {
        HStack(alignment: .center, spacing: 14) {
            avatarImage

            VStack(alignment: .leading, spacing: 8) {
                if viewModel.isEditingProfile {
                    TextField("请输入昵称", text: nicknameBinding)
                        .font(.system(size: 24, weight: .semibold))
                        .foregroundStyle(Color(hex: 0x252525))
                        .tint(AppDesign.primary)
                        .textFieldStyle(.plain)
                        .focused($nicknameFocused)
                        .submitLabel(.done)
                        .padding(.horizontal, 10)
                        .frame(height: 42)
                        .background(.white, in: RoundedRectangle(cornerRadius: 8))
                        .overlay {
                            RoundedRectangle(cornerRadius: 8)
                                .stroke(AppDesign.primary, lineWidth: 1)
                        }
                        .onSubmit {
                            Task { await saveProfileEdits() }
                        }
                } else {
                    Text(viewModel.displayNickname)
                        .font(.system(size: 24, weight: .semibold))
                        .foregroundStyle(Color(hex: 0x252525))
                        .lineLimit(nil)
                        .fixedSize(horizontal: false, vertical: true)
                }

                Text("UID:  \(accountContext.profile?.userId.isEmpty == false ? accountContext.profile?.userId ?? "--" : "--")")
                    .font(.system(size: 18, weight: .semibold))
                    .foregroundStyle(Color(hex: 0x606A7A))
                    .lineLimit(1)
            }
            .layoutPriority(1)

            Spacer(minLength: 0)

            Button {
                if viewModel.isEditingProfile {
                    Task { await saveProfileEdits() }
                } else {
                    viewModel.beginEditing()
                }
            } label: {
                ZStack {
                    if viewModel.isSaving && viewModel.isEditingProfile {
                        ProgressView()
                            .tint(.white)
                            .scaleEffect(0.82)
                    } else {
                        Image(systemName: viewModel.isEditingProfile ? "checkmark" : "pencil")
                            .font(.system(size: 18, weight: .semibold))
                    }
                }
                .foregroundStyle(.white)
                .frame(width: 44, height: 44)
                .background(
                    LinearGradient(
                        colors: [Color(hex: 0x238BFF), Color(hex: 0x006BFF)],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ),
                    in: Circle()
                )
                .shadow(color: Color(hex: 0x0073FF, alpha: 0.24), radius: 10, x: 0, y: 5)
            }
            .buttonStyle(.plain)
            .disabled(viewModel.isSaving)
            .opacity(viewModel.isSaving ? 0.6 : 1)
            .accessibilityLabel(viewModel.isEditingProfile ? "完成编辑" : "编辑个人信息")
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.horizontal, 18)
        .padding(.vertical, 21)
        .frame(minHeight: 132)
        .background {
            RoundedRectangle(cornerRadius: 17, style: .continuous)
                .fill(.white)
            ProfileHeaderWaveShape()
                .fill(
                    LinearGradient(
                        colors: [
                            Color(hex: 0xBFDFFF, alpha: 0.18),
                            Color(hex: 0x8EC4FF, alpha: 0.28)
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
            ProfileHeaderWaveShape(phase: 0.35)
                .fill(Color(hex: 0xE4F1FF, alpha: 0.62))
        }
        .clipShape(RoundedRectangle(cornerRadius: 17, style: .continuous))
        .overlay {
            RoundedRectangle(cornerRadius: 17, style: .continuous)
                .stroke(Color(hex: 0xE4ECF7), lineWidth: 1)
        }
        .shadow(color: Color(hex: 0xC8D7EA, alpha: 0.32), radius: 16, x: 0, y: 8)
    }

    private var avatarImage: some View {
        PhotosPicker(selection: $pickedAvatarItem, matching: .images) {
            avatarPreview
                .frame(width: 86, height: 86)
                .clipShape(Circle())
                .overlay {
                    Circle()
                        .stroke(.white, lineWidth: 3)
                }
                .overlay(alignment: .bottomTrailing) {
                    Image(systemName: "camera.fill")
                        .font(.system(size: 12, weight: .bold))
                        .foregroundStyle(.white)
                        .frame(width: 26, height: 26)
                        .background(AppDesign.primary, in: Circle())
                        .overlay {
                            Circle().stroke(.white, lineWidth: 2)
                        }
                }
                .overlay {
                    if let progress = viewModel.avatarUploadProgress {
                        ZStack {
                            Circle()
                                .fill(.black.opacity(0.34))
                            Text("\(progress)%")
                                .font(.system(size: 14, weight: .semibold))
                                .foregroundStyle(.white)
                        }
                    }
                }
        }
        .buttonStyle(.plain)
        .disabled(viewModel.isSaving)
        .accessibilityLabel("头像")
    }

    @ViewBuilder
    private var avatarPreview: some View {
        if let data = viewModel.pendingAvatarData, let image = UIImage(data: data) {
            Image(uiImage: image)
                .resizable()
                .scaledToFill()
        } else {
            RemoteAvatarImage(urlString: viewModel.displayAvatarURL)
        }
    }

    private var infoCard: some View {
        VStack(spacing: 0) {
            infoRow(title: "姓名") {
                plainInfoValue(viewModel.displayRealName)
            }

            divider

            Button {
                router.navigate(to: .profile(.accountSwitch))
            } label: {
                infoRow(title: "当前账号") {
                    VStack(alignment: .trailing, spacing: 3) {
                        rowValueText(currentAccountDisplayName)
                        Text(currentAccountTypeText)
                            .font(.system(size: 12, weight: .medium))
                            .foregroundStyle(AppDesign.textSecondary)
                            .lineLimit(1)
                    }
                    rowChevron
                }
            }
            .buttonStyle(.plain)

            divider

            infoRow(title: "手机号") {
                plainInfoValue(viewModel.displayPhone)
            }

            divider

            Button {
                showsPasswordSheet = true
            } label: {
                infoRow(title: "修改密码") {
                    rowChevron
                }
            }
            .buttonStyle(.plain)

            divider

            Button {
                router.navigate(to: .profile(.realNameAuth))
            } label: {
                infoRow(title: "认证状态") {
                    realNameStatusView
                    rowChevron
                }
            }
            .buttonStyle(.plain)

            divider

            infoRow(title: "账号状态") {
                accountStatusView
            }

            divider

            infoRow(title: "当前景区") {
                scenicStatusView
            }

            divider

            Button {
                router.navigate(to: .profile(.settings))
            } label: {
                infoRow(title: "系统设置") {
                    rowChevron
                }
            }
            .buttonStyle(.plain)
        }
        .padding(.horizontal, 24)
        .padding(.vertical, 4)
        .background(.white, in: RoundedRectangle(cornerRadius: 17, style: .continuous))
        .overlay {
            RoundedRectangle(cornerRadius: 17, style: .continuous)
                .stroke(Color(hex: 0xEEF3FA), lineWidth: 1)
        }
        .shadow(color: Color(hex: 0xC8D7EA, alpha: 0.30), radius: 16, x: 0, y: 8)
    }

    private var divider: some View {
        Rectangle()
            .fill(Color(hex: 0xE8EDF4))
            .frame(height: 1)
    }

    private var logoutButton: some View {
        Button {
            showsLogoutConfirm = true
        } label: {
            Text("退出登录")
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(Color(hex: 0xFF3B3B))
                .frame(maxWidth: .infinity)
                .frame(height: 58)
                .background(.white, in: RoundedRectangle(cornerRadius: 17, style: .continuous))
                .overlay {
                    RoundedRectangle(cornerRadius: 17, style: .continuous)
                        .stroke(Color(hex: 0xEEF3FA), lineWidth: 1)
                }
                .shadow(color: Color(hex: 0xC8D7EA, alpha: 0.24), radius: 14, x: 0, y: 7)
        }
        .buttonStyle(.plain)
    }

    /// 构造资料信息行，统一左右布局和点击区域。
    private func infoRow<Content: View>(title: String, @ViewBuilder content: () -> Content) -> some View {
        HStack(spacing: 8) {
            Text(title)
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(Color(hex: 0x101827))
                .frame(width: 104, alignment: .leading)
            Spacer(minLength: 4)
            content()
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .frame(height: 69)
        .contentShape(Rectangle())
    }

    @ViewBuilder
    /// 根据文本是否为空占位，选择普通文本或状态徽标展示。
    private func plainInfoValue(_ text: String) -> some View {
        if text == "--" {
            statusBadge(text: text, foreground: Color(hex: 0x606A7A), background: Color(hex: 0xF0F2F6))
        } else {
            rowValueText(text)
        }
    }

    /// 构造资料行右侧的普通值文本。
    private func rowValueText(_ text: String) -> some View {
        Text(text)
            .font(.system(size: 18, weight: .medium))
            .foregroundStyle(Color(hex: 0x333333))
            .lineLimit(1)
            .fixedSize(horizontal: false, vertical: true)
    }

    private var rowChevron: some View {
        Image(systemName: "chevron.right")
            .font(.system(size: 22, weight: .medium))
            .foregroundStyle(Color(hex: 0x9AA1AA))
    }

    @ViewBuilder
    private var realNameStatusView: some View {
        if viewModel.realNameInfo == nil {
            Text(viewModel.realNameStatusText)
                .font(.system(size: 17, weight: .medium))
                .foregroundStyle(Color(hex: 0xFF7B00))
                .lineLimit(1)
        } else {
            statusBadge(
                text: viewModel.realNameStatusText,
                icon: viewModel.realNameInfo?.auditStatus == 2 ? "checkmark.shield.fill" : nil,
                foreground: realNameStatusColor,
                background: realNameStatusBackground
            )
        }
    }

    private var accountStatusView: some View {
        let text = viewModel.accountStatusText
        return Group {
            if text == "--" {
                statusBadge(text: text, foreground: Color(hex: 0x606A7A), background: Color(hex: 0xF0F2F6))
            } else {
                statusBadge(text: text, icon: "checkmark.circle.fill", foreground: Color(hex: 0x14964A), background: Color(hex: 0xDDF8E9))
            }
        }
    }

    private var scenicStatusView: some View {
        let text = nonEmpty(accountContext.currentScenic?.name) ?? "--"
        return Group {
            if text == "--" {
                statusBadge(text: text, foreground: Color(hex: 0x606A7A), background: Color(hex: 0xF0F2F6))
            } else {
                statusBadge(text: text, icon: "mappin.circle.fill", foreground: AppDesign.primary, background: Color(hex: 0xE7F1FF))
            }
        }
    }

    /// 构造状态徽标，支持可选图标、前景色和背景色。
    private func statusBadge(text: String, icon: String? = nil, foreground: Color, background: Color) -> some View {
        HStack(spacing: 7) {
            if let icon {
                Image(systemName: icon)
                    .font(.system(size: 17, weight: .semibold))
            }
            Text(text)
                .lineLimit(1)
        }
        .font(.system(size: 17, weight: .semibold))
        .foregroundStyle(foreground)
        .padding(.horizontal, icon == nil ? 14 : 12)
        .frame(height: 34)
        .background(background, in: Capsule())
    }

    private var realNameStatusColor: Color {
        guard let realNameInfo = viewModel.realNameInfo else { return Color(hex: 0xFF7B00) }
        switch realNameInfo.auditStatus {
        case 2:
            return Color(hex: 0x14964A)
        case 3:
            return Color(hex: 0xEF4444)
        default:
            return Color(hex: 0xFF7B00)
        }
    }

    private var realNameStatusBackground: Color {
        guard let realNameInfo = viewModel.realNameInfo else { return Color(hex: 0xF4F4F4) }
        switch realNameInfo.auditStatus {
        case 2:
            return Color(hex: 0xDDF8E9)
        case 3:
            return Color(hex: 0xFFE7E7)
        default:
            return Color(hex: 0xFFF0E2)
        }
    }

    private var currentAccountDisplayName: String {
        nonEmpty(accountContext.currentStore?.name)
            ?? nonEmpty(accountContext.currentScenic?.name)
            ?? accountContext.profile?.displayName
            ?? viewModel.displayNickname
    }

    private var currentAccountTypeText: String {
        if accountContext.currentStore != nil {
            return "门店账号"
        }
        if accountContext.currentScenic != nil {
            return "景区账号"
        }
        return nonEmpty(viewModel.userInfo?.roleName) ?? "账号"
    }

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

    /// 重新拉取个人资料，并同步更新全局账号资料。
    private func reloadProfile(showToast: Bool) async {
        do {
            try await globalLoading.withOptionalLoading(!showToast && viewModel.userInfo == nil, message: "加载中...") {
                try await viewModel.reload(api: profileAPI)
            }
            if let userInfo = viewModel.userInfo {
                authSessionCoordinator.refreshCachedProfile(from: userInfo, accountContext: accountContext)
            } else {
                accountContext.replaceProfile(viewModel.accountProfileFallback(accountContext.profile))
            }
            if showToast {
                toastCenter.show("个人信息已刷新")
            }
        } catch is CancellationError {
            return
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 保存昵称编辑内容，并在成功后刷新全局账号展示。
    private func saveProfileEdits() async {
        do {
            try await globalLoading.withLoading(message: "保存中...") {
                try await viewModel.saveProfile(
                    api: profileAPI,
                    uploader: ossUploadService,
                    scenicId: accountContext.currentScenic?.id ?? 0
                )
            }
            if let userInfo = viewModel.userInfo {
                authSessionCoordinator.refreshCachedProfile(from: userInfo, accountContext: accountContext)
            } else {
                accountContext.replaceProfile(viewModel.accountProfileFallback(accountContext.profile))
            }
            toastCenter.show("个人信息已保存")
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 处理用户选择的头像图片，并生成待上传数据。
    private func prepareAvatarImage(from item: PhotosPickerItem?) async {
        guard let item else { return }
        defer { pickedAvatarItem = nil }
        do {
            guard let data = try await item.loadTransferable(type: Data.self) else {
                toastCenter.show("请选择有效的头像图片")
                return
            }
            try viewModel.prepareAvatarImage(data: data)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    /// 提交新密码，并在成功后关闭密码弹窗。
    private func updatePassword(_ password: String) async {
        do {
            try await viewModel.updatePassword(password, api: profileAPI)
            showsPasswordSheet = false
            toastCenter.show("密码修改成功")
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

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

/// 个人信息头部背景波浪形状，用于还原旧版蓝白卡片视觉。
private struct ProfileHeaderWaveShape: Shape {
    var phase: CGFloat = 0

    /// 根据当前矩形尺寸生成波浪路径。
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let startY = rect.height * (0.94 - phase * 0.16)
        path.move(to: CGPoint(x: rect.width * (0.26 + phase * 0.16), y: rect.height))
        path.addCurve(
            to: CGPoint(x: rect.width, y: rect.height * (0.26 + phase * 0.08)),
            control1: CGPoint(x: rect.width * (0.55 + phase * 0.06), y: startY),
            control2: CGPoint(x: rect.width * (0.70 + phase * 0.08), y: rect.height * (0.40 + phase * 0.14))
        )
        path.addLine(to: CGPoint(x: rect.width, y: rect.height))
        path.closeSubpath()
        return path
    }
}

/// 修改密码弹窗，负责采集新密码并提交给外部动作。
private struct PasswordUpdateSheet: View {
    @Environment(\.dismiss) private var dismiss
    @State private var password = ""
    let onSubmit: (String) async -> Void

    var body: some View {
        NavigationStack {
            VStack(alignment: .leading, spacing: 16) {
                SecureField("请输入新密码", text: $password)
                    .textContentType(.newPassword)
                    .textInputAutocapitalization(.never)
                    .autocorrectionDisabled(true)
                    .padding(.horizontal, 12)
                    .frame(height: 48)
                    .background(Color(hex: 0xF5F7FA), in: RoundedRectangle(cornerRadius: 8))
                    .overlay {
                        RoundedRectangle(cornerRadius: 8)
                            .stroke(Color(hex: 0xE2E8F0), lineWidth: 1)
                    }

                Text("密码至少 6 位。")
                    .font(.system(size: 13))
                    .foregroundStyle(AppDesign.textSecondary)

                Spacer()
            }
            .padding(16)
            .navigationTitle("修改密码")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("取消") {
                        dismiss()
                    }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("完成") {
                        Task { await onSubmit(password) }
                    }
                    .disabled(password.trimmingCharacters(in: .whitespacesAndNewlines).count < 6)
                }
            }
        }
        .presentationDetents([.height(220)])
    }
}

#Preview {
    NavigationStack {
        ProfileView()
            .environment(AppSession())
            .environment(AccountContext())
            .environment(PermissionContext())
            .environment(ScenicSpotContext())
            .environment(AppRouter())
            .environment(ToastCenter())
            .environment(ProfileAPI(client: APIClient()))
            .environment(OSSUploadService(configService: UploadAPI(client: APIClient())))
            .environment(AuthSessionCoordinator())
    }
}
