import SwiftUI
import PhotosUI
import AoqClientSdk

// MARK: - Chat Message Model

struct ChatMessage: Identifiable {
    let id = UUID()
    let sender: Sender
    var content: String
    let image: UIImage?
    let time: Date
    var apiMessageId: String?

    enum Sender {
        case ai, user
    }

    init(sender: Sender, content: String, time: Date, apiMessageId: String? = nil) {
        self.sender = sender
        self.content = content
        self.image = nil
        self.time = time
        self.apiMessageId = apiMessageId
    }

    init(sender: Sender, image: UIImage, time: Date) {
        self.sender = sender
        self.content = ""
        self.image = image
        self.time = time
    }
}

// MARK: - AI Call View

struct AICallView: View {
    @StateObject private var mgr = AoqEngineManager.shared

    @State private var messages: [ChatMessage] = []
    @State private var isRecording: Bool = false
    @State private var showSidePanel: Bool = false
    @State private var selectedSetting: SettingItem?
    @State private var isVoiceMode: Bool = true
    @State private var inputText: String = ""
    @State private var showPlusMenu: Bool = false
    @FocusState private var isInputFocused: Bool

    enum SettingItem: String, CaseIterable {
        case engine = "引擎设置"
        case audioCodec = "编码设置"
        case connection = "链接设置"
        case capture = "采集设置"
        case ui = "UI 设置"
    }

    @State private var showLogOverlay: Bool = false

    @State private var workDir: String = NSTemporaryDirectory()
    @State private var enableDumpAudio: Bool = false
    @State private var extras: String = ""

    @State private var token: String = ""
    @State private var sid: String = ""
    @State private var certificate: String = ""
    /* relay 接入点列表的 JSON 表示，默认单个 127.0.0.1:8006 */
    @State private var relayEndpointsJSON: String = "[\n  {\n    \"endpoint\" : \"127.0.0.1\",\n    \"port\" : 8006\n  }\n]"
    @State private var workspaceIdHash: String = ""

    @State private var codecSampleRate: Int = 48000
    @State private var codecChannel: Int = 1
    @State private var codecFormat: String = "Opus"

    @State private var captureSampleRate: Int = 48000
    @State private var captureChannel: Int = 1
    @State private var captureIsExternal: Bool = false

    @State private var showCamera: Bool = false
    @State private var showPhotoPicker: Bool = false
    @State private var selectedPhotoItem: PhotosPickerItem?
    @State private var pendingImage: UIImage?
    @State private var showImagePreview: Bool = false

    var body: some View {
        ZStack(alignment: .leading) {
            mainContent
            if showSidePanel {
                sidePanelOverlay
            }
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarTitleDisplayMode(.inline)
        .background(SwipeBackEnabler())
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                Button { withAnimation(.easeInOut(duration: 0.25)) { showSidePanel.toggle() } } label: {
                    Image(systemName: "line.3.horizontal")
                        .font(.title3)
                }
            }
            ToolbarItem(placement: .principal) {
                VStack(spacing: 1) {
                    Text("AI 通话")
                        .font(.headline)
                    Text("内容由 AI 生成")
                        .font(.caption2)
                        .foregroundStyle(.secondary)
                }
            }
            ToolbarItem(placement: .topBarTrailing) {
                HStack(spacing: 16) {
                    Button {} label: {
                        Image(systemName: "phone.fill")
                    }
                    Button { mgr.isSpeakerOn.toggle() } label: {
                        Image(systemName: mgr.isSpeakerOn ? "speaker.wave.2.fill" : "speaker.slash.fill")
                    }
                }
            }
        }
        .onReceive(mgr.$lastDataMsg) { data in
            guard let data = data,
                  let text = String(data: data, encoding: .utf8), !text.isEmpty else { return }
            let msg = ChatMessage(sender: .ai, content: text, time: Date())
            messages.append(msg)
        }
        .fullScreenCover(isPresented: $showCamera) {
            AoqCameraView { image, text in
                let msg = ChatMessage(sender: .user, image: image, time: Date())
                messages.append(msg)
                if !text.isEmpty {
                    let textMsg = ChatMessage(sender: .user, content: text, time: Date())
                    messages.append(textMsg)
                }
            }
        }
        .fullScreenCover(isPresented: $showImagePreview) {
            if let image = pendingImage {
                ImagePreviewView(image: image) { text in
                    let msg = ChatMessage(sender: .user, image: image, time: Date())
                    messages.append(msg)
                    if !text.isEmpty {
                        let textMsg = ChatMessage(sender: .user, content: text, time: Date())
                        messages.append(textMsg)
                    }
                    pendingImage = nil
                }
            }
        }
        .photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItem, matching: .images)
        .onChange(of: selectedPhotoItem) { newItem in
            guard let newItem = newItem else { return }
            newItem.loadTransferable(type: Data.self) { result in
                if case .success(let data) = result, let data = data, let img = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self.pendingImage = img
                        self.showImagePreview = true
                    }
                }
            }
            selectedPhotoItem = nil
        }
    }

    // MARK: - Main Content

    private var mainContent: some View {
        VStack(spacing: 0) {
            ZStack {
                chatArea
                if showLogOverlay {
                    logOverlay
                }
            }
            .clipped()
            bottomBar
        }
        .background(Color.white)
    }

    private var logOverlay: some View {
        ScrollView {
            LazyVStack(alignment: .leading, spacing: 4) {
                ForEach(mgr.events) { entry in
                    Text("[\(entry.timestamp)] \(entry.message)")
                        .font(.system(size: 11, design: .monospaced))
                        .foregroundStyle(.green)
                }
            }
            .padding(10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.7))
        .allowsHitTesting(false)
    }

    // MARK: - Side Panel

    private var sidePanelOverlay: some View {
        ZStack(alignment: .leading) {
            Color.black.opacity(0.3)
                .ignoresSafeArea()
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 0.25)) { showSidePanel = false }
                }

            sidePanelContent
                .frame(width: UIScreen.main.bounds.width * 0.78)
                .background(Color(uiColor: .systemBackground))
                .transition(.move(edge: .leading))
        }
    }

    private var sidePanelContent: some View {
        VStack(alignment: .leading, spacing: 0) {
            sidePanelHeader
            Divider()
            if let selected = selectedSetting {
                settingDetail(selected)
            } else {
                settingList
            }
        }
    }

    private var sidePanelHeader: some View {
        HStack {
            if selectedSetting != nil {
                Button {
                    withAnimation(.easeInOut(duration: 0.2)) { selectedSetting = nil }
                } label: {
                    Image(systemName: "chevron.left")
                        .font(.body.bold())
                }
            }
            Text(selectedSetting?.rawValue ?? "设置")
                .font(.title3.bold())
            Spacer()
            Button {
                withAnimation(.easeInOut(duration: 0.25)) {
                    showSidePanel = false
                    selectedSetting = nil
                }
            } label: {
                Image(systemName: "xmark.circle.fill")
                    .font(.title3)
                    .foregroundStyle(.secondary)
            }
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 14)
    }

    private var settingList: some View {
        VStack(spacing: 0) {
            ForEach(SettingItem.allCases, id: \.self) { item in
                Button {
                    withAnimation(.easeInOut(duration: 0.2)) { selectedSetting = item }
                } label: {
                    HStack {
                        Image(systemName: iconForSetting(item))
                            .frame(width: 24)
                            .foregroundStyle(.blue)
                        Text(item.rawValue)
                            .font(.body)
                            .foregroundStyle(.primary)
                        Spacer()
                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundStyle(.tertiary)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 14)
                }
                Divider().padding(.leading, 56)
            }
            Spacer()
        }
    }

    private func iconForSetting(_ item: SettingItem) -> String {
        switch item {
        case .engine: return "engine.combustion"
        case .connection: return "link"
        case .audioCodec: return "waveform"
        case .capture: return "mic"
        case .ui: return "eye"
        }
    }

    @ViewBuilder
    private func settingDetail(_ item: SettingItem) -> some View {
        ScrollView {
            VStack(spacing: 12) {
                switch item {
                case .engine: engineSettings
                case .connection: connectionSettings
                case .audioCodec: audioCodecSettings
                case .capture: captureSettings
                case .ui: uiSettings
                }
            }
            .padding(16)
        }
    }

    private var engineSettings: some View {
        VStack(alignment: .leading, spacing: 12) {
            LabeledInput(label: "WorkDir", text: $workDir, placeholder: "工作目录")
            LabeledInput(label: "Extras", text: $extras, placeholder: "扩展参数（可选）")
            Toggle("音频 Dump", isOn: $enableDumpAudio)
                .font(.subheadline)
                .tint(.blue)

            Divider()

            HStack(spacing: 6) {
                Text("状态")
                    .font(.subheadline)
                Spacer()
                Circle()
                    .fill(mgr.isEngineCreated ? Color.green : Color.gray)
                    .frame(width: 8, height: 8)
                Text(mgr.isEngineCreated ? "已创建" : "未创建")
                    .font(.subheadline)
                    .foregroundStyle(mgr.isEngineCreated ? .green : .secondary)
            }

            HStack(spacing: 12) {
                Button("创建引擎") {
                    mgr.createEngine(workDir: workDir, enableDumpAudio: enableDumpAudio, extras: extras)
                }
                .buttonStyle(.borderedProminent)
                .disabled(mgr.isEngineCreated)

                Button("销毁引擎") {
                    mgr.destroyEngine()
                }
                .buttonStyle(.bordered)
                .tint(.red)
                .disabled(!mgr.isEngineCreated)
            }
            .frame(maxWidth: .infinity)
        }
        .padding(12)
        .background(Color(uiColor: .secondarySystemGroupedBackground))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    private var connectionSettings: some View {
        VStack(alignment: .leading, spacing: 10) {
            LabeledInput(label: "Token", text: $token, placeholder: "输入 Token")
            LabeledInput(label: "SID", text: $sid, placeholder: "输入 SID")
            LabeledInput(label: "Certificate", text: $certificate, placeholder: "输入 Certificate")
            relayEndpointsEditor
            LabeledInput(label: "WsIdHash", text: $workspaceIdHash, placeholder: "工作空间哈希 ID")

            HStack(spacing: 12) {
                Button("连接") {
                    startCall()
                    withAnimation(.easeInOut(duration: 0.25)) {
                        showSidePanel = false
                        selectedSetting = nil
                    }
                }
                .buttonStyle(.borderedProminent)
                .disabled(mgr.isEngineCreated)

                Button("断开") { endCall() }
                    .buttonStyle(.bordered)
                    .tint(.red)
                    .disabled(!mgr.isEngineCreated)
            }
            .padding(.top, 4)

            HStack(spacing: 6) {
                Circle()
                    .fill(mgr.isConnected ? Color.green : (mgr.isEngineCreated ? Color.orange : Color.gray))
                    .frame(width: 8, height: 8)
                Text(mgr.isConnected ? "已连接" : (mgr.isEngineCreated ? "连接中..." : "未连接"))
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
        }
        .padding(12)
        .background(Color(uiColor: .secondarySystemGroupedBackground))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    /* relay 接入点 JSON 多行编辑器 */
    private var relayEndpointsEditor: some View {
        VStack(alignment: .leading, spacing: 4) {
            HStack(alignment: .top) {
                Text("RelayEndpoints")
                    .frame(width: 110, alignment: .leading)
                    .foregroundStyle(.secondary)
                TextEditor(text: $relayEndpointsJSON)
                    .font(.system(.caption, design: .monospaced))
                    .frame(minHeight: 80, maxHeight: 140)
                    .overlay(
                        RoundedRectangle(cornerRadius: 4)
                            .stroke(Color.secondary.opacity(0.3))
                    )
            }
            Text("格式：[{\"endpoint\":\"ip\",\"port\":8443}]，由服务器返回或手动编辑")
                .font(.caption2)
                .foregroundStyle(.secondary)
        }
    }

    private var audioCodecSettings: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("采样率")
                .font(.subheadline)
            Picker("采样率", selection: $codecSampleRate) {
                Text("8000").tag(8000)
                Text("16000").tag(16000)
                Text("48000").tag(48000)
            }
            .pickerStyle(.segmented)

            Divider()

            Text("通道数")
                .font(.subheadline)
            Picker("通道数", selection: $codecChannel) {
                Text("单声道").tag(1)
                Text("双声道").tag(2)
            }
            .pickerStyle(.segmented)

            Divider()

            Text("编码格式")
                .font(.subheadline)
            Picker("编码格式", selection: $codecFormat) {
                Text("Opus").tag("Opus")
                Text("AAC").tag("AAC")
                Text("G711").tag("G711")
            }
            .pickerStyle(.segmented)

            Divider()

            Button("设置") {
                mgr.startAudioPlayer(channel: codecChannel, isExternal: false)
            }
            .buttonStyle(.borderedProminent)
            .frame(maxWidth: .infinity)
            .disabled(!mgr.isEngineCreated)
        }
        .padding(12)
        .background(Color(uiColor: .secondarySystemGroupedBackground))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    private var captureSettings: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("采样率")
                .font(.subheadline)
            Picker("采样率", selection: $captureSampleRate) {
                Text("48000").tag(48000)
                Text("32000").tag(32000)
                Text("16000").tag(16000)
            }
            .pickerStyle(.segmented)

            Divider()

            Text("通道数")
                .font(.subheadline)
            Picker("通道数", selection: $captureChannel) {
                Text("1").tag(1)
                Text("2").tag(2)
            }
            .pickerStyle(.segmented)

            Divider()

            Toggle("外部采集", isOn: $captureIsExternal)
                .font(.subheadline)
                .tint(.blue)

            Divider()

            HStack(spacing: 12) {
                Button("开始采集") {
                    mgr.startAudioCapture(channel: captureChannel, isExternal: captureIsExternal, isVoipMode: false)
                }
                .buttonStyle(.borderedProminent)
                .disabled(!mgr.isEngineCreated)

                Button("停止采集") {
                    mgr.stopAudioCapture()
                }
                .buttonStyle(.bordered)
                .tint(.red)
                .disabled(!mgr.isEngineCreated)
            }
            .frame(maxWidth: .infinity)
        }
        .padding(12)
        .background(Color(uiColor: .secondarySystemGroupedBackground))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    private var uiSettings: some View {
        VStack(alignment: .leading, spacing: 12) {
            Toggle("显示日志", isOn: $showLogOverlay)
                .font(.subheadline)
                .tint(.blue)

            Text("开启后在聊天区域叠加显示 SDK 回调日志")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding(12)
        .background(Color(uiColor: .secondarySystemGroupedBackground))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    // MARK: - Chat Area

    private var chatArea: some View {
        ScrollViewReader { proxy in
            ScrollView {
                LazyVStack(spacing: 12) {
                    ForEach(messages) { msg in
                        chatBubble(msg)
                            .id(msg.id)
                    }
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)
            }
            .onChange(of: messages.count) { _ in
                if let last = messages.last {
                    withAnimation { proxy.scrollTo(last.id, anchor: .bottom) }
                }
            }
        }
    }

    @ViewBuilder
    private func chatBubble(_ msg: ChatMessage) -> some View {
        HStack(alignment: .top, spacing: 8) {
            if msg.sender == .ai {
                aiAvatar
                aiBubble(msg.content)
                Spacer(minLength: 48)
            } else {
                Spacer(minLength: 48)
                if let image = msg.image {
                    userImageBubble(image)
                } else {
                    userBubble(msg.content)
                }
            }
        }
    }

    private var aiAvatar: some View {
        Circle()
            .fill(Color.purple.opacity(0.15))
            .frame(width: 32, height: 32)
            .overlay {
                Image(systemName: "waveform")
                    .font(.system(size: 14))
                    .foregroundStyle(.purple)
            }
    }

    private func aiBubble(_ text: String) -> some View {
        Text(text)
            .font(.body)
            .padding(.horizontal, 14)
            .padding(.vertical, 10)
            .background(Color(uiColor: .systemGray6))
            .clipShape(RoundedRectangle(cornerRadius: 16))
    }

    private func userBubble(_ text: String) -> some View {
        Text(text)
            .font(.body)
            .foregroundStyle(.white)
            .padding(.horizontal, 14)
            .padding(.vertical, 10)
            .background(Color.blue)
            .clipShape(RoundedRectangle(cornerRadius: 16))
    }

    private func userImageBubble(_ image: UIImage) -> some View {
        Image(uiImage: image)
            .resizable()
            .scaledToFill()
            .frame(maxWidth: 200, maxHeight: 200)
            .clipShape(RoundedRectangle(cornerRadius: 12))
    }

    // MARK: - Bottom Bar

    private var bottomBar: some View {
        VStack(spacing: 8) {
            inputBar
                .padding(.horizontal, 16)
                .padding(.vertical, 14)
                .background(Color(uiColor: .systemBackground))
                .clipShape(RoundedRectangle(cornerRadius: 22))
                .shadow(color: .black.opacity(0.08), radius: 10, x: 0, y: -3)
            if showPlusMenu {
                plusMenuGrid
            }
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 10)
    }

    private var connectionStatus: some View {
        HStack(spacing: 6) {
            Circle()
                .fill(statusColor)
                .frame(width: 8, height: 8)
            Text(statusText)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
    }

    private var statusColor: Color {
        if mgr.isConnected { return .green }
        if mgr.isEngineCreated { return .orange }
        return .gray
    }

    private var statusText: String {
        if mgr.isConnected { return "已连接" }
        if mgr.isEngineCreated { return "连接中..." }
        return "未连接"
    }

    // MARK: - Input Bar

    private var inputBar: some View {
        HStack(spacing: 10) {
            Button { showCamera = true } label: {
                Image(systemName: "camera")
                    .font(.title3)
                    .foregroundStyle(.primary)
            }

            if isVoiceMode {
                pushToTalkButton
            } else {
                textInputField
            }

            Button {
                isVoiceMode.toggle()
                if !isVoiceMode {
                    isInputFocused = true
                } else {
                    isInputFocused = false
                }
            } label: {
                Image(systemName: isVoiceMode ? "keyboard" : "waveform")
                    .font(.title3)
                    .foregroundStyle(.primary)
            }

            Button {
                withAnimation(.easeInOut(duration: 0.2)) { showPlusMenu.toggle() }
            } label: {
                Image(systemName: showPlusMenu ? "xmark.circle.fill" : "plus.circle.fill")
                    .font(.title3)
                    .foregroundStyle(showPlusMenu ? .secondary : .primary)
            }
        }
    }

    private var pushToTalkButton: some View {
        Text(isRecording ? "松开 结束" : "按住说话")
            .font(.body.bold())
            .foregroundStyle(isRecording ? .red : .primary)
            .frame(maxWidth: .infinity)
            .frame(height: 36)
            .scaleEffect(isRecording ? 1.03 : 1.0)
            .animation(.easeInOut(duration: 0.15), value: isRecording)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged { _ in
                        if !isRecording { beginRecording() }
                    }
                    .onEnded { _ in
                        endRecording()
                    }
            )
    }

    private var textInputField: some View {
        HStack {
            TextField("发消息...", text: $inputText)
                .font(.subheadline)
                .focused($isInputFocused)
                .submitLabel(.send)
                .onSubmit { sendTextMessage() }
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 8)
        .background(Color(uiColor: .systemGray6))
        .clipShape(Capsule())
    }

    // MARK: - Plus Menu

    private var plusMenuGrid: some View {
        LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 4), spacing: 16) {
            plusMenuItem(icon: "camera.fill", title: "相机") { showCamera = true }
            plusMenuItem(icon: "photo.fill", title: "相册") { showPhotoPicker = true }
            plusMenuItem(icon: "doc.fill", title: "文件") {}
            plusMenuItem(icon: "phone.fill", title: "打电话") {}
        }
        .padding(.top, 8)
        .padding(.bottom, 4)
    }

    private func plusMenuItem(icon: String, title: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            VStack(spacing: 6) {
                Image(systemName: icon)
                    .font(.title3)
                    .foregroundStyle(.primary)
                    .frame(width: 50, height: 50)
                    .background(Color(uiColor: .systemGray6))
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                Text(title)
                    .font(.caption2)
                    .foregroundStyle(.secondary)
            }
        }
    }

    // MARK: - SDK Actions

    private func startCall() {
        if !mgr.isEngineCreated {
            mgr.createEngine(workDir: workDir, enableDumpAudio: enableDumpAudio, extras: extras)
        }
        let audioTrack = AoqTrackParam()
        audioTrack.trackType = .audio
        let dataTrack = AoqTrackParam()
        dataTrack.trackType = .data
        mgr.connect(token: token, sid: sid, certificate: certificate,
                    relayEndpoints: parseRelayEndpoints(json: relayEndpointsJSON),
                    workspaceIdHash: workspaceIdHash,
                    publishTracks: [audioTrack, dataTrack],
                    subscribeTracks: [audioTrack, dataTrack])
        mgr.startAudioPlayer(channel: codecChannel, isExternal: false)
    }

    private func endCall() {
        mgr.stopAudioCapture()
        mgr.stopAudioPlayer()
        mgr.disconnect()
        mgr.destroyEngine()
        isRecording = false
    }

    private func beginRecording() {
        isRecording = true
        if mgr.isConnected {
            mgr.startAudioCapture(channel: captureChannel, isExternal: captureIsExternal, isVoipMode: false)
        }
        let msg = ChatMessage(sender: .user, content: "[语音输入中...]", time: Date())
        messages.append(msg)
    }

    private func endRecording() {
        isRecording = false
        if mgr.isConnected {
            mgr.stopAudioCapture()
        }
    }

    private func sendTextMessage() {
        let text = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else { return }
        let msg = ChatMessage(sender: .user, content: text, time: Date())
        messages.append(msg)
        inputText = ""
    }
}

// MARK: - Aoq Camera View

private struct AoqCameraView: View {
    var onSend: (UIImage, String) -> Void
    @Environment(\.dismiss) private var dismiss
    @State private var useFrontCamera: Bool = false
    @State private var captureAction: (() -> Void)?
    @State private var capturedImage: UIImage?
    @State private var inputText: String = ""
    @State private var isVoiceMode: Bool = true
    @State private var isPressing: Bool = false
    @FocusState private var isInputFocused: Bool

    var body: some View {
        VStack(spacing: 0) {
            if capturedImage != nil {
                previewHeader
            } else {
                cameraTopBar
            }

            if let image = capturedImage {
                previewContent(image)
            } else {
                CameraPreviewRepresentable(useFrontCamera: useFrontCamera, onCapture: { image in
                    capturedImage = image
                }, onCoordinatorReady: { takePicture in
                    captureAction = takePicture
                })
            }

            if capturedImage != nil {
                previewBottom
            } else {
                cameraBottomBar
            }
        }
        .background(Color.black.ignoresSafeArea())
        .gesture(
            DragGesture(minimumDistance: 40)
                .onEnded { value in
                    if value.translation.width > 80 {
                        if capturedImage != nil {
                            capturedImage = nil
                        } else {
                            dismiss()
                        }
                    }
                }
        )
    }

    // MARK: - Camera Mode

    private var cameraTopBar: some View {
        HStack {
            Button { dismiss() } label: {
                Image(systemName: "xmark")
                    .font(.title3)
                    .foregroundStyle(.white)
            }
            Spacer()
            Text("aoq相机")
                .font(.headline)
                .foregroundStyle(.white)
            Spacer()
            Button {} label: {
                Image(systemName: "bolt.slash.fill")
                    .font(.title3)
                    .foregroundStyle(.white)
            }
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 12)
    }

    private var cameraBottomBar: some View {
        VStack(spacing: 20) {
            HStack(spacing: 0) {
                Text("单页")
                    .font(.subheadline.bold())
                    .padding(.horizontal, 16)
                    .padding(.vertical, 6)
                    .background(Color.white.opacity(0.2))
                    .clipShape(Capsule())
                Text("多页")
                    .font(.subheadline)
                    .foregroundStyle(.white.opacity(0.7))
                    .padding(.horizontal, 16)
                    .padding(.vertical, 6)
            }
            .foregroundStyle(.white)

            HStack {
                Circle()
                    .fill(Color.white.opacity(0.3))
                    .frame(width: 50, height: 50)

                Spacer()

                ShutterButton {
                    captureAction?()
                }

                Spacer()

                Button { useFrontCamera.toggle() } label: {
                    Image(systemName: "arrow.triangle.2.circlepath")
                        .font(.title2)
                        .foregroundStyle(.white)
                        .frame(width: 50, height: 50)
                }
            }
            .padding(.horizontal, 40)
        }
        .padding(.bottom, 30)
    }

    // MARK: - Preview Mode

    private var previewHeader: some View {
        HStack {
            Button { capturedImage = nil } label: {
                Image(systemName: "chevron.left")
                    .font(.title3.bold())
                    .foregroundStyle(.white)
            }
            Spacer()
            HStack(spacing: 20) {
                Button {} label: {
                    Image(systemName: "crop")
                        .font(.title3)
                        .foregroundStyle(.white)
                }
                Button {} label: {
                    Image(systemName: "square.and.arrow.up")
                        .font(.title3)
                        .foregroundStyle(.white)
                }
            }
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 12)
    }

    private func previewContent(_ image: UIImage) -> some View {
        Image(uiImage: image)
            .resizable()
            .scaledToFit()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color.black)
            .contentShape(Rectangle())
            .onTapGesture {
                isInputFocused = false
            }
    }

    private var previewBottom: some View {
        VStack(spacing: 12) {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 10) {
                    suggestionPill("这是什么")
                    suggestionPill("提取图中所有文字")
                }
                .padding(.horizontal, 16)
            }

            HStack(spacing: 10) {
                Button {
                    isVoiceMode.toggle()
                    if !isVoiceMode {
                        isInputFocused = true
                    } else {
                        isInputFocused = false
                    }
                } label: {
                    Image(systemName: isVoiceMode ? "waveform" : "keyboard")
                        .font(.body)
                        .foregroundStyle(.white)
                        .frame(width: 38, height: 38)
                        .background(Color.purple)
                        .clipShape(Circle())
                }

                if isVoiceMode {
                    Text(isPressing ? "松开 结束" : "按住说话")
                        .font(.subheadline.bold())
                        .foregroundStyle(isPressing ? .red : .white.opacity(0.8))
                        .frame(maxWidth: .infinity)
                        .frame(height: 36)
                        .scaleEffect(isPressing ? 1.03 : 1.0)
                        .animation(.easeInOut(duration: 0.15), value: isPressing)
                        .gesture(
                            DragGesture(minimumDistance: 0)
                                .onChanged { _ in
                                    if !isPressing { isPressing = true }
                                }
                                .onEnded { _ in
                                    isPressing = false
                                }
                        )
                } else {
                    TextField("发消息...", text: $inputText)
                        .font(.subheadline)
                        .foregroundStyle(.white)
                        .focused($isInputFocused)
                        .padding(.horizontal, 12)
                        .padding(.vertical, 10)
                        .submitLabel(.send)
                        .onSubmit { sendImage() }
                }

                Button { sendImage() } label: {
                    Image(systemName: "arrow.right")
                        .font(.body.bold())
                        .foregroundStyle(.white)
                        .frame(width: 38, height: 38)
                        .background(Color.blue)
                        .clipShape(Circle())
                }
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 10)
            .background(Color.white.opacity(0.15))
            .clipShape(Capsule())
            .padding(.horizontal, 16)
        }
        .padding(.vertical, 12)
        .background(Color.black)
    }

    private func suggestionPill(_ text: String) -> some View {
        Button {
            inputText = text
            sendImage()
        } label: {
            HStack(spacing: 4) {
                Text(text)
                    .font(.subheadline)
                Image(systemName: "arrow.right")
                    .font(.caption)
            }
            .foregroundStyle(.white.opacity(0.9))
            .padding(.horizontal, 14)
            .padding(.vertical, 8)
            .background(Color.white.opacity(0.15))
            .clipShape(Capsule())
        }
    }

    private func sendImage() {
        guard let image = capturedImage else { return }
        onSend(image, inputText)
        dismiss()
    }
}

private struct ShutterButton: View {
    var action: () -> Void
    @State private var isPressed = false

    var body: some View {
        Circle()
            .fill(Color.white)
            .frame(width: 70, height: 70)
            .overlay(
                Circle()
                    .stroke(Color.white, lineWidth: 4)
                    .frame(width: 80, height: 80)
            )
            .scaleEffect(isPressed ? 0.9 : 1.0)
            .animation(.easeInOut(duration: 0.1), value: isPressed)
            .onTapGesture {
                isPressed = true
                action()
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
                    isPressed = false
                }
            }
    }
}

private struct CameraPreviewRepresentable: UIViewControllerRepresentable {
    var useFrontCamera: Bool
    var onCapture: (UIImage) -> Void
    var onCoordinatorReady: (@escaping () -> Void) -> Void

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.sourceType = .camera
        picker.cameraDevice = useFrontCamera ? .front : .rear
        picker.showsCameraControls = false
        picker.delegate = context.coordinator
        context.coordinator.picker = picker

        DispatchQueue.main.async {
            onCoordinatorReady { [weak picker] in
                picker?.takePicture()
            }
        }
        return picker
    }

    func updateUIViewController(_ picker: UIImagePickerController, context: Context) {
        let device: UIImagePickerController.CameraDevice = useFrontCamera ? .front : .rear
        if picker.cameraDevice != device {
            picker.cameraDevice = device
        }
    }

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

    class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        var onCapture: (UIImage) -> Void
        weak var picker: UIImagePickerController?

        init(onCapture: @escaping (UIImage) -> Void) {
            self.onCapture = onCapture
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let image = info[.originalImage] as? UIImage {
                onCapture(image)
            }
        }
    }
}

// MARK: - Image Preview View

private struct ImagePreviewView: View {
    let image: UIImage
    var onSend: (String) -> Void
    @Environment(\.dismiss) private var dismiss
    @State private var inputText: String = ""
    @FocusState private var isFocused: Bool

    var body: some View {
        VStack(spacing: 0) {
            previewTopBar
            imageArea
            previewBottomBar
        }
        .background(Color.black.ignoresSafeArea())
    }

    private var previewTopBar: some View {
        HStack {
            Button { dismiss() } label: {
                Image(systemName: "chevron.left")
                    .font(.title3.bold())
                    .foregroundStyle(.white)
            }
            Spacer()
            HStack(spacing: 20) {
                Button {} label: {
                    Image(systemName: "crop")
                        .font(.title3)
                        .foregroundStyle(.white)
                }
                Button {} label: {
                    Image(systemName: "square.and.arrow.up")
                        .font(.title3)
                        .foregroundStyle(.white)
                }
            }
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 12)
    }

    private var imageArea: some View {
        Image(uiImage: image)
            .resizable()
            .scaledToFit()
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color.black)
    }

    private var previewBottomBar: some View {
        VStack(spacing: 12) {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 10) {
                    suggestionPill("这是什么")
                    suggestionPill("提取图中所有文字")
                }
                .padding(.horizontal, 16)
            }

            HStack(spacing: 10) {
                Button {} label: {
                    Image(systemName: "waveform")
                        .font(.body)
                        .foregroundStyle(.white)
                        .frame(width: 38, height: 38)
                        .background(Color.purple)
                        .clipShape(Circle())
                }

                TextField("发消息或按住说话...", text: $inputText)
                    .font(.subheadline)
                    .focused($isFocused)
                    .padding(.horizontal, 12)
                    .padding(.vertical, 10)
                    .submitLabel(.send)
                    .onSubmit { sendMessage() }

                Button { sendMessage() } label: {
                    Image(systemName: "arrow.right")
                        .font(.body.bold())
                        .foregroundStyle(.white)
                        .frame(width: 38, height: 38)
                        .background(Color.blue)
                        .clipShape(Circle())
                }
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 10)
            .background(Color(uiColor: .systemGray6))
            .clipShape(Capsule())
            .padding(.horizontal, 16)
        }
        .padding(.vertical, 12)
        .background(Color(uiColor: .systemBackground))
    }

    private func suggestionPill(_ text: String) -> some View {
        Button {
            inputText = text
            sendMessage()
        } label: {
            HStack(spacing: 4) {
                Text(text)
                    .font(.subheadline)
                Image(systemName: "arrow.right")
                    .font(.caption)
            }
            .foregroundStyle(.primary)
            .padding(.horizontal, 14)
            .padding(.vertical, 8)
            .background(Color(uiColor: .systemGray6))
            .clipShape(Capsule())
        }
    }

    private func sendMessage() {
        onSend(inputText)
        dismiss()
    }
}

// MARK: - Swipe Back Gesture Enabler

private struct SwipeBackEnabler: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        SwipeBackController()
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}

    private class SwipeBackController: UIViewController {
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            navigationController?.interactivePopGestureRecognizer?.isEnabled = true
            navigationController?.interactivePopGestureRecognizer?.delegate = nil
        }
    }
}

#Preview {
    NavigationStack {
        AICallView()
    }
}
