// 反馈页（14E，对照 doc/frontend-design.html 第八章）：
// 多行文本 1–1000 实时计数 / PhotosPicker 选图 ≤3 张（长边压到 ≤2000px 再传，单张 ≤5MB）
// / 诊断信息 Switch（app 版本、iOS 版本、机型、device_id）/ multipart POST /v1/feedback
// / 成功态"已收到 · 谢谢你" + 继续反馈。
import PhotosUI
import SwiftUI

struct FeedbackView: View {
    @EnvironmentObject private var account: AccountStore
    @Environment(\.horizontalSizeClass) private var hSize

    private struct PickedImage: Identifiable {
        let id = UUID()
        let thumb: UIImage
        let jpeg: Data
    }

    private static let maxContentLen = 1000 // protocol.FeedbackMaxContentLen
    private static let maxImages = 3        // protocol.FeedbackMaxImages
    private static let maxImageBytes = 5 << 20 // protocol.FeedbackMaxImageBytes

    @State private var content = ""
    @State private var pickerItems: [PhotosPickerItem] = []
    @State private var images: [PickedImage] = []
    @State private var diagnosticsOn = true
    @State private var submitting = false
    @State private var done = false
    @State private var errorText: String?

    var body: some View {
        Group {
            if done {
                successView
            } else {
                form
            }
        }
        .background(DuduTheme.bgApp.ignoresSafeArea())
        .navigationTitle("反馈问题")
        .navigationBarTitleDisplayMode(.inline)
    }

    // MARK: - 表单

    private var form: some View {
        VStack(spacing: 0) {
            ScrollView {
                VStack(spacing: DuduTheme.space4) {
                    contentCard
                    imagesCard
                    diagnosticsCard
                }
                .padding(DuduTheme.space4)
                .frame(maxWidth: hSize == .regular ? 640 : .infinity) // iPad 自适应收窄
                .frame(maxWidth: .infinity)
            }
            bottomBar
        }
    }

    private var contentCard: some View {
        VStack(alignment: .trailing, spacing: DuduTheme.space1) {
            ZStack(alignment: .topLeading) {
                if content.isEmpty {
                    Text("说说遇到的问题或建议")
                        .font(.system(size: DuduTheme.textMd))
                        .foregroundStyle(DuduTheme.text3)
                        .padding(.top, 8)
                        .padding(.leading, 5)
                }
                TextEditor(text: $content)
                    .font(.system(size: DuduTheme.textMd))
                    .foregroundStyle(DuduTheme.text1)
                    .scrollContentBackground(.hidden)
                    .frame(minHeight: 140)
                    .onChange(of: content) { _, new in
                        if new.count > Self.maxContentLen {
                            content = String(new.prefix(Self.maxContentLen))
                        }
                    }
            }
            Text("\(content.count) / \(Self.maxContentLen)")
                .font(.system(size: DuduTheme.textXs).monospacedDigit())
                .foregroundStyle(DuduTheme.text3)
        }
        .padding(DuduTheme.space3)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
    }

    private var imagesCard: some View {
        VStack(alignment: .leading, spacing: DuduTheme.space2) {
            Text("截图（选填，最多 \(Self.maxImages) 张）")
                .font(.system(size: DuduTheme.textXs))
                .foregroundStyle(DuduTheme.text3)
            HStack(spacing: DuduTheme.space3) {
                ForEach(images) { img in
                    ZStack(alignment: .topTrailing) {
                        Image(uiImage: img.thumb)
                            .resizable()
                            .scaledToFill()
                            .frame(width: 64, height: 64)
                            .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusSm))
                        Button {
                            images.removeAll { $0.id == img.id }
                        } label: {
                            Image(systemName: "xmark")
                                .font(.system(size: 9, weight: .semibold))
                                .foregroundStyle(DuduTheme.overlayText)
                                .frame(width: 20, height: 20)
                                .background(Circle().fill(DuduTheme.overlayBg))
                        }
                        .offset(x: 6, y: -6)
                    }
                }
                if images.count < Self.maxImages {
                    PhotosPicker(selection: $pickerItems,
                                 maxSelectionCount: Self.maxImages - images.count,
                                 matching: .images) {
                        RoundedRectangle(cornerRadius: DuduTheme.radiusSm)
                            .strokeBorder(DuduTheme.border2,
                                          style: StrokeStyle(lineWidth: 1, dash: [4]))
                            .frame(width: 64, height: 64)
                            .overlay(
                                Image(systemName: "photo.badge.plus")
                                    .font(.system(size: 18))
                                    .foregroundStyle(DuduTheme.text3)
                            )
                    }
                }
                Spacer()
            }
        }
        .padding(DuduTheme.space4)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
        .onChange(of: pickerItems) { _, items in
            guard !items.isEmpty else { return }
            Task { await loadPicked(items) }
        }
    }

    private var diagnosticsCard: some View {
        HStack(spacing: DuduTheme.space3) {
            VStack(alignment: .leading, spacing: 2) {
                Text("附带诊断信息")
                    .font(.system(size: DuduTheme.textMd, weight: .medium))
                    .foregroundStyle(DuduTheme.text1)
                Text("App 版本、系统版本、机型、设备标识")
                    .font(.system(size: DuduTheme.textXs))
                    .foregroundStyle(DuduTheme.text3)
            }
            Spacer()
            Toggle("", isOn: $diagnosticsOn)
                .labelsHidden()
                .tint(DuduTheme.accent)
        }
        .padding(DuduTheme.space4)
        .background(DuduTheme.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusLg))
        .overlay(RoundedRectangle(cornerRadius: DuduTheme.radiusLg).strokeBorder(DuduTheme.border1))
    }

    private var bottomBar: some View {
        VStack(spacing: DuduTheme.space2) {
            if let errorText {
                Text(errorText)
                    .font(.system(size: DuduTheme.textSm))
                    .foregroundStyle(DuduTheme.danger)
            }
            Button(action: submit) {
                HStack(spacing: DuduTheme.space2) {
                    if submitting {
                        ProgressView().tint(DuduTheme.textOnAccent)
                    }
                    Text(submitting ? "正在提交" : "提交")
                        .font(.system(size: DuduTheme.textLg, weight: .medium))
                }
                .foregroundStyle(DuduTheme.textOnAccent)
                .frame(maxWidth: .infinity)
                .frame(height: DuduTheme.controlLg)
                .background(DuduTheme.accent.opacity(canSubmit ? 1 : 0.5))
                .clipShape(RoundedRectangle(cornerRadius: DuduTheme.radiusSm))
            }
            .disabled(!canSubmit)
        }
        .padding(.horizontal, DuduTheme.space4)
        .padding(.vertical, DuduTheme.space3)
        .frame(maxWidth: hSize == .regular ? 640 : .infinity)
        .frame(maxWidth: .infinity)
        .background(DuduTheme.bgApp)
    }

    private var canSubmit: Bool {
        !submitting && !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }

    // MARK: - 成功态

    private var successView: some View {
        VStack(spacing: DuduTheme.space4) {
            Spacer()
            ZStack {
                Circle().fill(DuduTheme.positiveSoft).frame(width: 56, height: 56)
                Image(systemName: "checkmark")
                    .font(.system(size: 24, weight: .semibold))
                    .foregroundStyle(DuduTheme.positive)
            }
            Text("已收到 · 谢谢你")
                .font(.system(size: DuduTheme.textLg, weight: .semibold))
                .foregroundStyle(DuduTheme.text1)
            Button("继续反馈") {
                content = ""
                images = []
                errorText = nil
                done = false
            }
            .font(.system(size: DuduTheme.textMd, weight: .medium))
            .foregroundStyle(DuduTheme.accentText)
            Spacer()
        }
        .frame(maxWidth: .infinity)
    }

    // MARK: - 图片处理（长边压到 ≤2000px，JPEG 重编码，超 5MB 跳过）

    private func loadPicked(_ items: [PhotosPickerItem]) async {
        var skipped = false
        for item in items {
            guard images.count < Self.maxImages else { break }
            guard let data = try? await item.loadTransferable(type: Data.self),
                  let processed = Self.processImage(data) else {
                skipped = true
                continue
            }
            images.append(PickedImage(thumb: processed.thumb, jpeg: processed.jpeg))
        }
        pickerItems = []
        errorText = skipped ? "有图片超过 5MB 或无法读取，已跳过" : nil
    }

    private static func processImage(_ data: Data) -> (thumb: UIImage, jpeg: Data)? {
        guard var image = UIImage(data: data) else { return nil }
        let maxSide: CGFloat = 2000
        let longest = max(image.size.width, image.size.height)
        if longest > maxSide {
            let scale = maxSide / longest
            let size = CGSize(width: image.size.width * scale, height: image.size.height * scale)
            let renderer = UIGraphicsImageRenderer(size: size)
            image = renderer.image { _ in image.draw(in: CGRect(origin: .zero, size: size)) }
        }
        guard let jpeg = image.jpegData(compressionQuality: 0.85),
              jpeg.count <= maxImageBytes else { return nil }
        return (image, jpeg)
    }

    // MARK: - 提交

    private func submit() {
        guard let token = account.token else {
            errorText = "请先登录"
            return
        }
        submitting = true
        errorText = nil
        let diagnostics: String? = diagnosticsOn ? Self.diagnosticsJSON() : nil
        let trimmed = content.trimmingCharacters(in: .whitespacesAndNewlines)
        let jpegs = images.map(\.jpeg)
        Task {
            do {
                _ = try await Api.client.submitFeedback(token: token, content: trimmed,
                                                        jpegImages: jpegs,
                                                        diagnosticsJSON: diagnostics)
                done = true
            } catch let apiErr as ApiError where apiErr.code == ApiError.feedbackRateLimited {
                errorText = "今天反馈次数已达上限"
            } catch {
                errorText = "提交失败，稍后再试" // 保留已填内容
            }
            submitting = false
        }
    }

    /// 诊断信息（对齐 backend 3.5：app_version / os_version / platform / device_id；不含识别文本）
    private static func diagnosticsJSON() -> String? {
        let payload: [String: String] = [
            "app_version": DeviceInfo.appVersion,
            "os_version": DeviceInfo.osVersion,
            "platform": DeviceInfo.platform,
            "model": DeviceInfo.model,
            "device_id": MetricsQueue.shared.deviceID,
        ]
        guard let data = try? JSONSerialization.data(withJSONObject: payload, options: [.sortedKeys]) else {
            return nil
        }
        return String(data: data, encoding: .utf8)
    }
}

#Preview {
    NavigationStack { FeedbackView().environmentObject(AccountStore()) }
}
