import SwiftUI
import SwiftData

// MARK: - ActiveRecordingView
/// The live recording screen showing real-time waveform, elapsed time,
/// and quick-action buttons for adding photos and notes during a session.
/// Fully redesigned to use a minimalist business-focused line-drawn UI.
struct ActiveRecordingView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) private var dismiss

    let session: CelestiaSession
    var initialDuration: TimeInterval = 0
    let recordingSource: RecordingSourceChoice
    var onFinishRecording: (() -> Void)? = nil

    @State private var recordingVM: RecordingViewModel
    @State private var showNoteSheet = false
    @State private var showCamera = false
    @State private var noteText = ""
    @State private var pendingNoteTimeMs: Double = 0
    @State private var latestEvent: CelestiaTimelineEvent?
    @State private var latestEventVisible = false
    @State private var isEndingRecording = false
    @State private var stopErrorMessage: String?
    @State private var recordName: String
    @State private var showRecordNameEditor = false
    @State private var hasStartedLiveActivity = false
    @State private var hasAddedContinuationMarker = false

    init(
        session: CelestiaSession,
        initialDuration: TimeInterval = 0,
        recordingSource: RecordingSourceChoice = .iPhone,
        onFinishRecording: (() -> Void)? = nil
    ) {
        self.session = session
        self.initialDuration = initialDuration
        self.recordingSource = recordingSource
        self.onFinishRecording = onFinishRecording
        _recordingVM = State(initialValue: RecordingViewModel(source: recordingSource))
        _recordName = State(initialValue: session.title)
    }

    var body: some View {
        ZStack(alignment: .top) {
            // Dynamic clean background
            Color.spaceBlack
                .ignoresSafeArea()
                .contentShape(Rectangle())
                .onTapGesture(count: 2) {
                    endRecording()
                }

            VStack(spacing: 0) {
                recordNameSection
                    .padding(.horizontal, 24)
                    .padding(.top, 16)
                    .padding(.bottom, 14)

                // Top Header Block (Timecode + Indicator)
                VStack(spacing: 16) {
                    timecodeSection
                    recordingIndicator
                }
                .padding(.bottom, 24)

                // Live Waveform
                waveformSection
                    .padding(.horizontal, 24)
                    .padding(.bottom, 20)

                // Latest Event Card
                latestEventCard
                    .padding(.horizontal, 24)
                    .padding(.bottom, 20)

                Spacer()

                // Action Buttons
                actionButtons
                    .padding(.horizontal, 48)
                    .padding(.bottom, 32)

                // Recording Controls
                recordingControlButtons
                    .padding(.bottom, 24)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
            .ignoresSafeArea(.keyboard, edges: .bottom)
        }
        .ignoresSafeArea(.keyboard, edges: .bottom)
        .toolbar(.hidden, for: .tabBar)
        .toolbar(.hidden, for: .navigationBar)
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true)
        .sheet(isPresented: $showRecordNameEditor) {
            recordNameEditorSheet
        }
        .sheet(isPresented: $showNoteSheet) {
            noteInputSheet
        }
        .fullScreenCover(isPresented: $showCamera) {
            ImagePicker(sourceType: UIImagePickerController.isSourceTypeAvailable(.camera) ? .camera : .photoLibrary) { image in
                saveImageAndAddEvent(image)
            }
        }
        .onAppear {
            UIApplication.shared.isIdleTimerDisabled = true
            recordingVM.startRecording(initialDuration: initialDuration)
        }
        .onChange(of: recordingVM.isRecording) { _, isRecording in
            if isRecording {
                addContinuationMarkerIfNeeded()
            }
            guard isRecording, !hasStartedLiveActivity else { return }
            hasStartedLiveActivity = true
            RecordingLiveActivityManager.shared.start(
                sessionID: session.id,
                title: session.title,
                sourceName: recordingVM.sourceDisplayName,
                elapsedSeconds: recordingVM.elapsedTime
            )
        }
        .onChange(of: recordingVM.isPaused) { _, isPaused in
            guard hasStartedLiveActivity else { return }
            RecordingLiveActivityManager.shared.update(
                elapsedSeconds: recordingVM.elapsedTime,
                isPaused: isPaused
            )
        }
        .onOpenURL { url in
            handleRecordingURL(url)
        }
        .onDisappear {
            UIApplication.shared.isIdleTimerDisabled = false
            commitRecordName()
            if recordingVM.isRecording {
                recordingVM.stopRecording()
            }
            if hasStartedLiveActivity {
                RecordingLiveActivityManager.shared.end(elapsedSeconds: recordingVM.elapsedTime)
                hasStartedLiveActivity = false
            }
        }
        .alert("无法结束设备录音", isPresented: Binding(
            get: { stopErrorMessage != nil },
            set: { if !$0 { stopErrorMessage = nil } }
        )) {
            Button("重试") { endRecording() }
            Button("继续录音", role: .cancel) { stopErrorMessage = nil }
        } message: {
            Text(stopErrorMessage ?? "请确认微光仍在附近并保持连接。")
        }
    }

    // MARK: - Record Name

    private var recordNameSection: some View {
        Button {
            recordName = session.title
            showRecordNameEditor = true
        } label: {
            VStack(alignment: .leading, spacing: 8) {
                HStack(spacing: 6) {
                    Text("记录名称")
                        .font(.system(size: 10, weight: .semibold, design: .monospaced))
                        .tracking(1.4)

                    Spacer()

                    Image(systemName: "pencil")
                        .font(.system(size: 11, weight: .semibold))
                }
                .foregroundStyle(Color.secondary)

                Text(session.title)
                    .font(.system(size: 19, weight: .semibold))
                    .foregroundStyle(Color.primary)
                    .lineLimit(1)
                    .frame(maxWidth: .infinity, alignment: .leading)

                Rectangle()
                    .fill(Color.primary.opacity(0.16))
                    .frame(height: 1)
            }
            .padding(.horizontal, 14)
            .padding(.vertical, 12)
            .background(Color.cardBackground.opacity(0.45))
            .businessBorder(cornerRadius: 8)
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }

    private var recordNameEditorSheet: some View {
        RecordNameEditorSheet(recordName: $recordName) {
            saveRecordNameAndCloseEditor()
        } onCancel: {
            recordName = session.title
            showRecordNameEditor = false
        }
    }

    // MARK: - Timecode

    private var timecodeSection: some View {
        Text(recordingVM.elapsedTimeFormatted)
            .font(.system(size: 52, weight: .light))
            .monospacedDigit()
            .foregroundStyle(Color.primary)
            .contentTransition(.numericText(countsDown: false))
            .frame(height: 64)
    }

    // MARK: - Recording Indicator

    private var recordingIndicator: some View {
        VStack(spacing: 8) {
            HStack(spacing: 8) {
                TimelineView(.periodic(from: .now, by: 1.0)) { context in
                    let isEven = Int(context.date.timeIntervalSince1970) % 2 == 0
                    Circle()
                        .fill(recordingVM.isRecording && !recordingVM.isPaused ? Color.recordingRed : Color.secondary)
                        .frame(width: 8, height: 8)
                        .opacity(recordingVM.isRecording && !recordingVM.isPaused ? (isEven ? 1.0 : 0.3) : 0.6)
                        .animation(.easeInOut(duration: 0.5), value: isEven)
                }
                .frame(width: 10, height: 10)

                Text(recordingVM.isPaused ? "已暂停" : recordingVM.statusMessage)
                    .font(.system(size: 11, weight: .semibold, design: .monospaced))
                    .foregroundStyle(recordingVM.isRecording && !recordingVM.isPaused ? Color.recordingRed : Color.secondary)
                    .tracking(1.2)
            }

            HStack(spacing: 6) {
                Image(systemName: recordingSource.systemImage)
                    .font(.system(size: 11, weight: .medium))
                Text("设备：\(recordingVM.sourceDisplayName)")
                    .font(.system(size: 11, weight: .medium))
            }
            .foregroundStyle(Color.primary.opacity(0.85))

            if let error = recordingVM.errorMessage {
                Text(error)
                    .font(.system(size: 10))
                    .foregroundStyle(Color.recordingRed)
                    .multilineTextAlignment(.center)
                    .lineLimit(2)
            }
        }
        .padding(.horizontal, 10)
        .padding(.vertical, 8)
        .businessBorder(cornerRadius: 6)
    }

    // MARK: - Waveform

    private var waveformSection: some View {
        VStack(spacing: 0) {
            LiveWaveformView(samples: recordingVM.waveformSamples)
                .frame(height: 90)

            // Graphical VU Meter + Numeric Display
            HStack(spacing: 10) {
                AmplitudeLevelMeterView(amplitude: recordingVM.currentAmplitude)

                Spacer(minLength: 0)

                Text(String(format: "%02.0f%%", recordingVM.currentAmplitude * 100))
                    .font(.system(size: 9, weight: .medium, design: .monospaced))
                    .foregroundStyle(recordingVM.currentAmplitude > 0.85 ? Color.recordingRed : Color.secondary)
            }
            .padding(.horizontal, 4)
            .padding(.top, 10)
        }
        .frame(height: 114)
    }

    // MARK: - Latest Event Card

    private var latestEventCard: some View {
        ZStack { // Fix: Use ZStack instead of Group to enforce the fixed frame even when empty
            if let event = latestEvent, latestEventVisible {
                HStack(spacing: 12) {
                    Image(systemName: event.eventIcon)
                        .font(.system(size: 12))
                        .foregroundStyle(Color.primary)
                        .frame(width: 28, height: 28)
                        .businessBorder(cornerRadius: 14)

                    VStack(alignment: .leading, spacing: 2) {
                        Text(eventLabel(for: event.eventType))
                            .font(.system(size: 11, weight: .semibold))
                            .foregroundStyle(Color.primary)

                        if let text = event.textContent {
                            Text(text)
                               .font(.system(size: 12))
                               .foregroundStyle(Color.secondary)
                               .lineLimit(1)
                        }
                    }

                    Spacer()

                    Text(event.relativeTimeFormatted)
                        .font(.system(size: 11, weight: .regular, design: .monospaced))
                        .foregroundStyle(Color.secondary)
                }
                .padding(12)
                .background(Color.cardBackground.opacity(0.4))
                .businessBorder(cornerRadius: 8)
                .transition(.asymmetric(
                    insertion: .move(edge: .bottom).combined(with: .opacity),
                    removal: .opacity
                ))
            }
        }
        .frame(height: 56)
        .animation(.spring(response: 0.35, dampingFraction: 0.8), value: latestEvent?.id)
    }

    // MARK: - Action Buttons

    private var actionButtons: some View {
        HStack(spacing: 40) {
            // Camera button
            actionButton(
                icon: "camera",
                label: "拍照打点"
            ) {
                capturePhoto()
            }

            // Note button
            actionButton(
                icon: "doc.text",
                label: "文字笔记"
            ) {
                presentNoteSheet()
            }
        }
    }

    private func actionButton(
        icon: String,
        label: String,
        action: @escaping () -> Void
    ) -> some View {
        Button(action: action) {
            VStack(spacing: 10) {
                ZStack {
                    Circle()
                        .fill(Color.primary.opacity(0.02))
                        .frame(width: 60, height: 60)
                        .businessBorder(cornerRadius: 30)

                    Image(systemName: icon)
                        .font(.system(size: 20, weight: .light))
                        .foregroundStyle(Color.primary)
                }

                Text(label)
                    .font(.system(size: 11, weight: .regular))
                    .foregroundStyle(Color.secondary)
            }
        }
        .buttonStyle(.plain)
    }

    // MARK: - Recording Controls

    private var recordingControlButtons: some View {
        HStack(spacing: 52) {
            recordingControlButton(
                icon: recordingVM.isPaused ? "play.fill" : "pause.fill",
                label: recordingVM.isPaused ? "继续记录" : "暂停",
                tint: .primary
            ) {
                toggleRecordingPause()
            }

            recordingControlButton(
                icon: "stop.fill",
                label: isEndingRecording ? "正在结束" : "结束记录",
                tint: .recordingRed,
                isProminent: true
            ) {
                endRecording()
            }
        }
    }

    private func recordingControlButton(
        icon: String,
        label: String,
        tint: Color,
        isProminent: Bool = false,
        action: @escaping () -> Void
    ) -> some View {
        Button(action: action) {
            VStack(spacing: 9) {
                ZStack {
                    Circle()
                        .fill(isProminent ? tint : Color.primary.opacity(0.02))
                        .frame(width: 64, height: 64)

                    if !isProminent {
                        Circle()
                            .stroke(Color.primary.opacity(0.18), lineWidth: 1)
                            .frame(width: 64, height: 64)
                    }

                    Image(systemName: icon)
                        .font(.system(size: 21, weight: .semibold))
                        .foregroundStyle(isProminent ? Color.white : tint)
                }

                Text(label)
                    .font(.system(size: 11, weight: .medium))
                    .foregroundStyle(tint)
            }
            .frame(width: 88)
        }
        .buttonStyle(.plain)
        .disabled(isEndingRecording)
        .opacity(isEndingRecording && !isProminent ? 0.4 : 1)
        .accessibilityLabel(label)
    }

    // MARK: - Note Input Sheet

    private var noteInputSheet: some View {
        NavigationStack {
            ZStack {
                Color.spaceBlack.ignoresSafeArea()

                VStack(alignment: .leading, spacing: 16) {
                    Label(
                        "添加到 \(formattedNoteTime(pendingNoteTimeMs))",
                        systemImage: "clock"
                    )
                    .font(.system(size: 12, weight: .medium))
                    .foregroundStyle(Color.secondary)

                    ZStack(alignment: .topLeading) {
                        if noteText.isEmpty {
                            Text("输入笔记内容…")
                                .font(.system(size: 15))
                                .foregroundStyle(Color.secondary.opacity(0.6))
                                .padding(.horizontal, 18)
                                .padding(.vertical, 16)
                                .allowsHitTesting(false)
                        }

                        TextEditor(text: $noteText)
                            .font(.system(size: 15))
                            .foregroundStyle(Color.primary)
                            .scrollContentBackground(.hidden)
                            .padding(10)
                            .frame(minHeight: 160)
                            .background(Color.cardBackground.opacity(0.5))
                            .businessBorder(cornerRadius: 8)
                    }

                    Spacer()
                }
                .padding(20)
            }
            .navigationTitle("添加笔记")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("取消") {
                        showNoteSheet = false
                        noteText = ""
                    }
                }

                ToolbarItem(placement: .confirmationAction) {
                    Button("保存") {
                        addNote()
                    }
                    .disabled(noteText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
                }
            }
        }
        .presentationDetents([.medium])
        .presentationDragIndicator(.visible)
        .presentationBackground(Color.spaceBlack)
    }

    // MARK: - Actions

    private func capturePhoto() {
        showCamera = true
    }

    private func saveImageAndAddEvent(_ image: UIImage) {
        guard let data = image.jpegData(compressionQuality: 0.8) else { return }
        let filename = "photo_\(UUID().uuidString).jpg"
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let fileURL = documentsURL.appendingPathComponent(filename)
        do {
            try data.write(to: fileURL)
            let event = recordingVM.addPhotoEvent(to: session, localFilePath: filename)
            HapticManager.trigger(.photoCapture)
            showLatestEvent(event)
        } catch {
            print("[ActiveRecordingView] Failed to save captured photo: \(error.localizedDescription)")
        }
    }

    private func addNote() {
        let text = noteText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else { return }

        let event = recordingVM.addNoteEvent(to: session, text: text)
        event.relativeTimeMs = Int64(pendingNoteTimeMs.rounded())

        HapticManager.trigger(.noteAdded)
        showLatestEvent(event)

        noteText = ""
        showNoteSheet = false
    }

    private func addContinuationMarkerIfNeeded() {
        guard initialDuration > 0, !hasAddedContinuationMarker else { return }
        hasAddedContinuationMarker = true

        let event = CelestiaTimelineEvent(
            relativeTimeMs: Int64((initialDuration * 1_000).rounded()),
            eventType: "MARKER"
        )
        event.textContent = "续录时间：\(Self.continuationDateFormatter.string(from: Date()))"
        session.events.append(event)
        session.isSynced = false
        session.syncState = .pending
        try? modelContext.save()
    }

    private func presentNoteSheet() {
        pendingNoteTimeMs = max(0, recordingVM.elapsedTime * 1_000)
        noteText = ""
        showNoteSheet = true
    }

    private func formattedNoteTime(_ timeMs: Double) -> String {
        let totalSeconds = max(0, Int(timeMs / 1_000))
        let hours = totalSeconds / 3_600
        let minutes = (totalSeconds % 3_600) / 60
        let seconds = totalSeconds % 60

        if hours > 0 {
            return String(format: "%d:%02d:%02d", hours, minutes, seconds)
        }
        return String(format: "%02d:%02d", minutes, seconds)
    }

    private static let continuationDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.dateFormat = "yyyy年M月d日 HH:mm:ss"
        return formatter
    }()

    private func toggleRecordingPause() {
        guard !isEndingRecording else { return }
        HapticManager.trigger(.tapFeedback)

        if recordingVM.isPaused {
            recordingVM.resumeRecording()
        } else {
            recordingVM.pauseRecording()
        }
    }

    private func endRecording() {
        guard !isEndingRecording else { return }
        commitRecordName()
        isEndingRecording = true

        recordingVM.stopRecording { result in
            switch result {
            case .success(let confirmedURL):
                finalizeRecording(newRecordedURL: confirmedURL ?? recordingVM.outputFileURL)
            case .failure(let error):
                isEndingRecording = false
                stopErrorMessage = error.localizedDescription
            }
        }
    }

    private func finalizeRecording(newRecordedURL: URL?) {
        let existingPath = session.localAudioPath
        let existingURL = AudioPathHelper.resolveURL(for: existingPath)
        let totalRecordedSeconds = recordingVM.elapsedTime
        RecordingLiveActivityManager.shared.end(elapsedSeconds: totalRecordedSeconds)
        hasStartedLiveActivity = false
        
        if let newRecordedURL = newRecordedURL {
            Task { @MainActor in
                let mergedURL = await AudioMerger.mergeAudioFiles(firstURL: existingURL, secondURL: newRecordedURL)
                session.localAudioPath = AudioPathHelper.relativePath(from: mergedURL.path)
                session.endTime = session.startTime.addingTimeInterval(totalRecordedSeconds)
                session.isSynced = false
                session.syncState = .pending
                try? modelContext.save()
                
                HapticManager.trigger(.recordStop)
                isEndingRecording = false
                dismiss()
                onFinishRecording?()
            }
        } else {
            if existingURL != nil {
                session.endTime = session.startTime.addingTimeInterval(totalRecordedSeconds)
                session.isSynced = false
                session.syncState = .pending
                try? modelContext.save()
            } else {
                session.endTime = Date()
                session.isSynced = false
                session.syncState = .pending
                try? modelContext.save()
            }
            HapticManager.trigger(.recordStop)
            isEndingRecording = false
            dismiss()
            onFinishRecording?()
        }
    }

    private func showLatestEvent(_ event: CelestiaTimelineEvent) {
        withAnimation {
            latestEvent = event
            latestEventVisible = true
        }
        // Auto-dismiss after a few seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
            withAnimation {
                latestEventVisible = false
            }
        }
    }

    // MARK: - Helpers

    private func eventLabel(for type: String) -> String {
        switch type {
        case "PHOTO": return "已捕获照片"
        case "NOTE": return "已保存笔记"
        case "MARKER": return "标记点"
        case "VOICE": return "音轨事件"
        default: return "事件"
        }
    }

    private func commitRecordName() {
        let trimmedName = recordName.trimmingCharacters(in: .whitespacesAndNewlines)
        if trimmedName.isEmpty {
            recordName = session.title
            return
        }

        guard session.title != trimmedName else {
            if recordName != trimmedName {
                recordName = trimmedName
            }
            return
        }

        recordName = trimmedName
        session.title = trimmedName
        session.isSynced = false
        session.syncState = .pending
        try? modelContext.save()
    }

    private func saveRecordNameAndCloseEditor() {
        commitRecordName()
        guard !recordName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return }
        showRecordNameEditor = false
    }

    private func handleRecordingURL(_ url: URL) {
        guard url.scheme == "celestiatrace",
              url.host == "recording" else { return }

        let components = url.pathComponents.filter { $0 != "/" }
        guard let sessionID = components.first,
              sessionID.caseInsensitiveCompare(session.id.uuidString) == .orderedSame else { return }

        switch components.dropFirst().first {
        case "photo":
            capturePhoto()
        case "note":
            presentNoteSheet()
        default:
            break
        }
    }
}

struct RecordNameEditorSheet: View {
    @Binding var recordName: String
    let onSave: () -> Void
    let onCancel: () -> Void

    @FocusState private var isRecordNameFocused: Bool

    var body: some View {
        NavigationStack {
            ZStack {
                Color.spaceBlack.ignoresSafeArea()

                VStack(alignment: .leading, spacing: 10) {
                    Text("记录名称")
                        .font(.system(size: 10, weight: .semibold, design: .monospaced))
                        .foregroundStyle(Color.secondary)
                        .tracking(1.4)

                    TextField("输入记录名称", text: $recordName)
                        .focused($isRecordNameFocused)
                        .font(.system(size: 18, weight: .semibold))
                        .foregroundStyle(Color.primary)
                        .textInputAutocapitalization(.never)
                        .autocorrectionDisabled()
                        .submitLabel(.done)
                        .padding(.horizontal, 14)
                        .padding(.vertical, 12)
                        .background(Color.cardBackground.opacity(0.5))
                        .businessBorder(cornerRadius: 8)
                        .onSubmit {
                            onSave()
                        }

                    Spacer()
                }
                .padding(20)
            }
            .navigationTitle("修改记录名称")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("取消", action: onCancel)
                        .foregroundStyle(Color.secondary)
                }

                ToolbarItem(placement: .confirmationAction) {
                    Button("保存", action: onSave)
                        .disabled(recordName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
                }
            }
        }
        .presentationDetents([.height(190)])
        .presentationDragIndicator(.visible)
        .presentationBackground(Color.spaceBlack)
        .onAppear {
            DispatchQueue.main.async {
                isRecordNameFocused = true
            }
        }
    }
}

// MARK: - Amplitude Level Meter View

/// A minimalist graphical VU meter bar visualizing real-time audio amplitude.
private struct AmplitudeLevelMeterView: View {
    let amplitude: Float // 0.0 to 1.0

    private let totalSegments: Int = 16

    var body: some View {
        HStack(spacing: 3) {
            ForEach(0..<totalSegments, id: \.self) { index in
                let threshold = Float(index) / Float(totalSegments)
                let isFilled = amplitude > threshold
                let isPeak = index >= totalSegments - 2

                RoundedRectangle(cornerRadius: 1)
                    .fill(
                        isFilled
                            ? (isPeak ? Color.recordingRed : Color.primary.opacity(0.85))
                            : Color.primary.opacity(0.12)
                    )
                    .frame(height: isFilled ? (isPeak ? 7 : 5) : 3)
                    .animation(.spring(response: 0.15, dampingFraction: 0.75), value: amplitude)
            }
        }
    }
}

// MARK: - Preview

#Preview {
    let session = CelestiaSession(title: "Preview Session")
    ActiveRecordingView(session: session)
        .modelContainer(for: CelestiaSession.self, inMemory: true)
}
