import AVFoundation
import SwiftUI
import VisionKit

// 扫码登录他端（#8）：本机已登录，用相机扫另一台设备显示的登录二维码（/link?r=&c=），解析校验后把
// requestId / code 交引擎走批准流程。用 VisionKit 的 DataScannerViewController（系统级扫码 UI，免手搓
// AVFoundation 会话）。模拟器无相机 → isSupported 为假，回落「相机不可用」提示。
struct ScanSheet: View
{
    // 扫到合法登录二维码时回调 (requestId, code)，随后自动关闭扫码页。
    let onScanned: (String, String) -> Void
    @Environment(\.dismiss) private var dismiss
    // nil＝权限询问中；true/false＝已授权 / 被拒。
    @State private var authorized: Bool?
    @State private var invalid = false

    var body: some View
    {
        NavigationStack
        {
            content
                .navigationTitle(t("ios.scan.title"))
                .navigationBarTitleDisplayMode(.inline)
                .toolbar
                {
                    ToolbarItem(placement: .topBarLeading)
                    {
                        Button(t("common.cancel")) { dismiss() }
                    }
                }
        }
        .task { await requestCamera() }
    }

    @ViewBuilder
    private var content: some View
    {
        if authorized == nil
        {
            ProgressView()
        }
        else if authorized == true, DataScannerViewController.isSupported
        {
            scanner
        }
        else
        {
            ContentUnavailableView(t("ios.scan.cameraDenied"), systemImage: "camera.fill")
        }
    }

    private var scanner: some View
    {
        ZStack(alignment: .bottom)
        {
            LoginScannerView(onScan: handleScan)
            VStack(spacing: 8)
            {
                if invalid
                {
                    Text(t("ios.scan.invalid"))
                        .font(.callout)
                        .padding(.vertical, 8)
                        .padding(.horizontal, 14)
                        .background(.red.opacity(0.85), in: Capsule())
                        .foregroundStyle(.white)
                }
                Text(t("ios.scan.hint"))
                    .font(.footnote)
                    .multilineTextAlignment(.center)
                    .padding(.vertical, 8)
                    .padding(.horizontal, 14)
                    .background(.black.opacity(0.5), in: Capsule())
                    .foregroundStyle(.white)
            }
            .padding(.bottom, 40)
        }
        .ignoresSafeArea(edges: .bottom)
    }

    private func requestCamera() async
    {
        switch AVCaptureDevice.authorizationStatus(for: .video)
        {
        case .authorized:
            authorized = true
        case .notDetermined:
            authorized = await AVCaptureDevice.requestAccess(for: .video)
        default:
            authorized = false
        }
    }

    // 扫到一个码：解析校验；合法即回调并关闭，非法则提示「无法识别」并继续扫描。
    private func handleScan(_ raw: String)
    {
        guard let parsed = parseLinkApprovalUrl(raw) else
        {
            invalid = true
            return
        }
        onScanned(parsed.requestId, parsed.code)
        dismiss()
    }
}

// 解析扫到的登录二维码（/link?r=&c=）：仅校验路径为 /link 且 r/c 非空。origin 不强校验——r/c 一律
// 发往本端自己的后端，外站码只会 404（无开放重定向风险），对齐 web 桌面侧的放宽逻辑（见 net/qr.ts）。
private func parseLinkApprovalUrl(_ raw: String) -> (requestId: String, code: String)?
{
    guard let comp = URLComponents(string: raw), comp.path == "/link" else { return nil }
    let items = comp.queryItems ?? []
    guard let r = items.first(where: { $0.name == "r" })?.value, !r.isEmpty,
          let c = items.first(where: { $0.name == "c" })?.value, !c.isEmpty
    else { return nil }
    return (r, c)
}

// DataScannerViewController 的 SwiftUI 封装：识别 QR 码，首个命中即回调（done 闸门避免重复触发）。
private struct LoginScannerView: UIViewControllerRepresentable
{
    let onScan: (String) -> Void

    func makeUIViewController(context: Context) -> DataScannerViewController
    {
        let scanner = DataScannerViewController(
            recognizedDataTypes: [ .barcode(symbologies: [ .qr ]) ],
            qualityLevel: .balanced,
            isHighFrameRateTrackingEnabled: false,
            isHighlightingEnabled: true)
        scanner.delegate = context.coordinator
        return scanner
    }

    func updateUIViewController(_ vc: DataScannerViewController, context: Context)
    {
        try? vc.startScanning()
    }

    func makeCoordinator() -> Coordinator { Coordinator(onScan: onScan) }

    final class Coordinator: NSObject, DataScannerViewControllerDelegate
    {
        private let onScan: (String) -> Void
        private var done = false

        init(onScan: @escaping (String) -> Void) { self.onScan = onScan }

        func dataScanner(_ scanner: DataScannerViewController,
                         didAdd addedItems: [RecognizedItem],
                         allItems: [RecognizedItem])
        {
            guard !done else { return }
            for item in addedItems
            {
                if case let .barcode(barcode) = item, let str = barcode.payloadStringValue
                {
                    done = true
                    onScan(str)
                    return
                }
            }
        }
    }
}
