// 首页（对照 doc/frontend-design.html 第七章 ① 启用引导 + ④ 我的）：
// 四步引导卡（添加键盘 / 完全访问 / 麦克风 / 试一试，自动检测完成态）
// + 账户卡（昵称脱敏 / 余额 / Badge）+ 今日试用进度卡 + 入口（购买 / 反馈 / 退出登录）。
// 设计硬规则：每屏至多一个蓝色主按钮（底部引导按钮）；无渐变；UI 无 emoji；文案"你"短句无句号。
// 步骤检测：
//   1 添加键盘 —— UITextInputMode.activeInputModes 含本键盘 bundle id（AppleKeyboards 兜底）
//   2 完全访问 —— 键盘扩展出现时回写 App Group（需用户开启后切过一次 dudu 键盘）
//   3 麦克风 —— AVAudioApplication.recordPermission
//   4 试一试 —— 键盘扩展打开过（kb.seen），"我说完了"手动兜底
import AVFoundation
import SwiftUI

struct HomeView: View {
    @EnvironmentObject private var account: AccountStore
    @EnvironmentObject private var router: AppRouter
    @Environment(\.horizontalSizeClass) private var hSize
    @Environment(\.scenePhase) private var scenePhase

    private static let keyboardBundleID = "app.dudu.ios.keyboard"

    /// 第 4 步手动兜底："我说完了"
    @AppStorage("guide.tried") private var triedManually = false

    @State private var micPermission = AVAudioApplication.shared.recordPermission
    @State private var keyboardAdded = false
    @State private var showLogoutConfirm = false
    #if DEBUG
    @State private var mockState: AccountState = .guest
    @State private var offlineMock = false
    #endif

    var body: some View {
        VStack(spacing: 0) {
            ScrollView {
                VStack(spacing: DuduTheme.space4) {
                    header
                    stepsCard
                    accountCard
                    if account.state != .guest {
                        trialCard
                    }
                    entriesCard
                    #if DEBUG
                    debugCard
                    #endif
                }
                .padding(DuduTheme.space4)
                .frame(maxWidth: hSize == .regular ? 640 : .infinity) // iPad 自适应收窄
                .frame(maxWidth: .infinity)
            }
            if activeStep < 4 {
                primaryButton
            }
        }
        .background(DuduTheme.bgApp.ignoresSafeArea())
        .toolbar(.hidden, for: .navigationBar)
        .onAppear { refresh() }
        .onChange(of: scenePhase) { _, phase in
            if phase == .active { refresh() }
        }
    }

    private func refresh() {
        account.reload()
        micPermission = AVAudioApplication.shared.recordPermission
        keyboardAdded = Self.detectKeyboardAdded()
        #if DEBUG
        mockState = account.state
        offlineMock = Api.offlineMock
        #endif
    }

    // MARK: - 引导步骤状态

    /// 各步完成态（独立检测，非顺序推进）
    private var stepDone: [Bool] {
        [keyboardAdded,
         account.keyboardFullAccess,
         micPermission == .granted,
         account.keyboardSeen || triedManually]
    }

    /// 当前活跃步 = 第一个未完成步；4 = 全部完成
    private var activeStep: Int {
        stepDone.firstIndex(of: false) ?? 4
    }

    /// 任务指定检测方式：UITextInputMode.activeInputModes 包含键盘 bundle id；
    /// identifier 是非公开 key，responds 检查兜底，再退 AppleKeyboards 列表。
    private static func detectKeyboardAdded() -> Bool {
        let sel = NSSelectorFromString("identifier")
        for mode in UITextInputMode.activeInputModes {
            guard mode.responds(to: sel),
                  let id = mode.perform(sel)?.takeUnretainedValue() as? String else { continue }
            if id.contains(keyboardBundleID) { return true }
        }
        if let kbs = UserDefaults.standard.array(forKey: "AppleKeyboards") as? [String] {
            return kbs.contains { $0.contains(keyboardBundleID) }
        }
        return false
    }

    // MARK: - 头部

    private var header: some View {
        VStack(spacing: DuduTheme.space2) {
            Text("dudu")
                .font(.system(size: 28, weight: .bold, design: .rounded))
                .foregroundStyle(DuduTheme.accent)
            Text(activeStep < 4 ? "四步开启 dudu" : "都弄好了")
                .font(.system(size: DuduTheme.textXl, weight: .semibold))
                .foregroundStyle(DuduTheme.text1)
            Text("按住说话，松开上屏")
                .font(.system(size: DuduTheme.textBase))
                .foregroundStyle(DuduTheme.text2)
        }
        .padding(.top, DuduTheme.space6)
    }

    // MARK: - 四步引导

    private var stepsCard: some View {
        VStack(spacing: DuduTheme.space3) {
            stepRow(index: 0, title: "添加键盘", desc: "设置 · 键盘里打开 dudu")
            stepRow(index: 1, title: "开启完全访问", desc: "识别需要联网，只在你说话时使用")
            stepRow(index: 2, title: "允许麦克风", desc: "键盘说话用的就是这里的授权")
            stepRow(index: 3, title: "试一试", desc: "随便找个输入框，切到 dudu 键盘说一句")
        }
    }

    private func stepRow(index: Int, title: String, desc: String) -> some View {
        let done = stepDone[index]
        let active = activeStep == index
        return HStack(spacing: DuduTheme.space3) {
            ZStack {
                Circle()
                    .fill(done ? DuduTheme.positiveSoft : DuduTheme.accentSoft)
                    .frame(width: 32, height: 32)
                if done {
                    Image(systemName: "checkmark")
                        .font(.system(size: 13, weight: .semibold))
                        .foregroundStyle(DuduTheme.positive)
                } else {
                    Text("\(index + 1)")
                        .font(.system(size: 14, weight: .semibold))
                        .foregroundStyle(DuduTheme.accentText)
                }
            }
            VStack(alignment: .leading, spacing: 2) {
                Text(title)
                    .font(.system(size: DuduTheme.textMd, weight: .medium))
                    .foregroundStyle(DuduTheme.text1)
                Text(desc)
                    .font(.system(size: DuduTheme.textXs))
                    .foregroundStyle(DuduTheme.text3)
            }
            Spacer()
        }
        .padding(DuduTheme.space4)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(
            RoundedRectangle(cornerRadius: DuduTheme.radiusLg)
                .strokeBorder(active ? DuduTheme.accent : DuduTheme.border1,
                              lineWidth: active ? 1.5 : 1)
        )
        .opacity(done || active ? 1 : 0.62)
    }

    // MARK: - 账户卡

    private var accountCard: some View {
        Button {
            if account.state == .guest { router.showLogin = true }
        } label: {
            HStack(spacing: DuduTheme.space3) {
                ZStack {
                    Circle().fill(DuduTheme.accentSoft).frame(width: 40, height: 40)
                    Image(systemName: "person.fill")
                        .font(.system(size: 17))
                        .foregroundStyle(DuduTheme.accentText)
                }
                VStack(alignment: .leading, spacing: 2) {
                    Text(account.state == .guest ? "未登录" : (account.nicknameMasked ?? "已登录"))
                        .font(.system(size: DuduTheme.textMd, weight: .medium))
                        .foregroundStyle(DuduTheme.text1)
                    Text(accountSubtitle)
                        .font(.system(size: DuduTheme.textXs))
                        .foregroundStyle(DuduTheme.text3)
                }
                Spacer()
                badge
                if account.state == .guest {
                    Image(systemName: "chevron.right")
                        .font(.system(size: 12, weight: .semibold))
                        .foregroundStyle(DuduTheme.text3)
                }
            }
            .padding(DuduTheme.space4)
            .background(DuduTheme.surfaceCard)
            .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
            .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
        }
        .buttonStyle(.plain)
    }

    private var accountSubtitle: String {
        switch account.state {
        case .ok: return "时长余额 \(account.balanceSeconds / 60) 分钟 · 不过期"
        case .trial: return "今日试用剩 \(account.trialRemainingSeconds) 秒"
        case .guest: return "登录后开始用"
        case .quota: return "时长用完了"
        }
    }

    private var badge: some View {
        let (text, fg, bg): (String, Color, Color) = {
            switch account.state {
            case .ok: return ("余额充足", DuduTheme.positive, DuduTheme.positiveSoft)
            case .trial: return ("试用中", DuduTheme.accentText, DuduTheme.accentSoft)
            case .guest: return ("未登录", DuduTheme.text2, DuduTheme.surface3)
            case .quota: return ("余额不足", DuduTheme.warning, DuduTheme.warningSoft)
            }
        }()
        return Text(text)
            .font(.system(size: DuduTheme.textXs, weight: .medium))
            .foregroundStyle(fg)
            .padding(.horizontal, 10)
            .padding(.vertical, 4)
            .background(Capsule().fill(bg))
    }

    // MARK: - 今日试用进度卡

    private var trialCard: some View {
        let limit = max(1, account.trialDailyLimitSeconds)
        let used = min(account.trialUsedSeconds, limit)
        return VStack(alignment: .leading, spacing: DuduTheme.space2) {
            HStack {
                Text("今日免费试用")
                    .font(.system(size: DuduTheme.textMd, weight: .medium))
                    .foregroundStyle(DuduTheme.text1)
                Spacer()
                Text("\(used / 60) / \(limit / 60) 分钟")
                    .font(.system(size: DuduTheme.textSm).monospacedDigit())
                    .foregroundStyle(DuduTheme.text2)
            }
            ProgressView(value: Double(used), total: Double(limit))
                .tint(DuduTheme.accent)
        }
        .padding(DuduTheme.space4)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
    }

    // MARK: - 入口列表（购买 / 反馈 / 退出登录）

    private var entriesCard: some View {
        VStack(spacing: 0) {
            entryRow(title: "购买时长", icon: "creditcard") {
                if account.state == .guest {
                    router.showLogin = true
                } else {
                    router.path.append(AppRouter.Route.purchase)
                }
            }
            Divider().overlay(DuduTheme.border1).padding(.leading, DuduTheme.space4 + 28)
            entryRow(title: "反馈问题", icon: "ellipsis.message") {
                if account.state == .guest {
                    router.showLogin = true // 反馈需登录（backend 3.5）
                } else {
                    router.path.append(AppRouter.Route.feedback)
                }
            }
            if account.state != .guest {
                Divider().overlay(DuduTheme.border1).padding(.leading, DuduTheme.space4 + 28)
                Button {
                    showLogoutConfirm = true
                } label: {
                    HStack(spacing: DuduTheme.space3) {
                        Image(systemName: "rectangle.portrait.and.arrow.right")
                            .font(.system(size: 15))
                            .foregroundStyle(DuduTheme.danger)
                            .frame(width: 20)
                        Text("退出登录")
                            .font(.system(size: DuduTheme.textMd))
                            .foregroundStyle(DuduTheme.danger)
                        Spacer()
                    }
                    .padding(DuduTheme.space4)
                }
                .buttonStyle(.plain)
                .confirmationDialog("退出后键盘只能看不能说", isPresented: $showLogoutConfirm,
                                    titleVisibility: .visible) {
                    Button("退出登录", role: .destructive) { logout() }
                    Button("再想想", role: .cancel) {}
                }
            }
        }
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
    }

    private func entryRow(title: String, icon: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            HStack(spacing: DuduTheme.space3) {
                Image(systemName: icon)
                    .font(.system(size: 15))
                    .foregroundStyle(DuduTheme.accentText)
                    .frame(width: 20)
                Text(title)
                    .font(.system(size: DuduTheme.textMd))
                    .foregroundStyle(DuduTheme.text1)
                Spacer()
                Image(systemName: "chevron.right")
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(DuduTheme.text3)
            }
            .padding(DuduTheme.space4)
        }
        .buttonStyle(.plain)
    }

    private func logout() {
        if let token = account.token {
            // 服务端拉黑 token，失败不阻断本地退出
            Task { try? await Api.client.logout(token: token) }
        }
        account.logout()
    }

    #if DEBUG
    // MARK: - 调试卡（仅 DEBUG 构建）：账户四态切换 + 离线 mock 开关

    private var debugCard: some View {
        VStack(alignment: .leading, spacing: DuduTheme.space2) {
            Text("调试 · 仅开发构建可见")
                .font(.system(size: DuduTheme.textXs, weight: .medium))
                .foregroundStyle(DuduTheme.text3)
            Picker("账户态", selection: $mockState) {
                Text("ok").tag(AccountState.ok)
                Text("trial").tag(AccountState.trial)
                Text("guest").tag(AccountState.guest)
                Text("quota").tag(AccountState.quota)
            }
            .pickerStyle(.segmented)
            .onChange(of: mockState) { _, s in account.setMock(state: s) }
            Toggle("离线 mock（不连后端）", isOn: $offlineMock)
                .font(.system(size: DuduTheme.textSm))
                .foregroundStyle(DuduTheme.text2)
                .tint(DuduTheme.accent)
                .onChange(of: offlineMock) { _, on in Api.offlineMock = on }
        }
        .padding(DuduTheme.space4)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
    }
    #endif

    // MARK: - 底部主按钮（本屏唯一蓝色主按钮，全部完成后隐藏）

    private var primaryButton: some View {
        Button(action: advanceGuide) {
            Text(["去设置", "去设置", micPermission == .denied ? "去设置" : "去授权", "我说完了"][min(activeStep, 3)])
                .font(.system(size: DuduTheme.textLg, weight: .medium))
                .foregroundStyle(DuduTheme.textOnAccent)
                .frame(maxWidth: .infinity)
                .frame(height: DuduTheme.controlLg)
                .background(DuduTheme.accent)
                .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusSm))
        }
        .padding(.horizontal, DuduTheme.space4)
        .padding(.vertical, DuduTheme.space3)
        .frame(maxWidth: hSize == .regular ? 640 : .infinity)
        .frame(maxWidth: .infinity)
        .background(DuduTheme.bgApp)
    }

    private func advanceGuide() {
        MetricsQueue.shared.track(.onboardingStep, props: ["step": .number(Double(activeStep + 1))])
        switch activeStep {
        case 0, 1:
            // 系统只允许打开本 App 的设置页（app-settings:），添加键盘 / 完全访问都从这里进
            openAppSettings()
        case 2:
            if micPermission == .denied {
                openAppSettings() // 已拒绝只能去系统设置改
            } else {
                requestMic()
            }
        default:
            triedManually = true
        }
    }

    private func requestMic() {
        AVAudioApplication.requestRecordPermission { _ in
            DispatchQueue.main.async {
                micPermission = AVAudioApplication.shared.recordPermission
            }
        }
    }

    private func openAppSettings() {
        if let url = URL(string: UIApplication.openSettingsURLString) {
            UIApplication.shared.open(url)
        }
    }
}

#Preview {
    NavigationStack { HomeView() }
        .environmentObject(AccountStore())
        .environmentObject(AppRouter())
}
