import SwiftUI
import Speech
import AVFoundation
import Combine
#if canImport(Translation)
import Translation
#endif

class SpeechRecognizer: ObservableObject {
    static let shared = SpeechRecognizer()
    
    @Published var transcript = ""
    @Published var isRecording = false
    @Published var error: String?
    
    private var audioEngine = AVAudioEngine()
    private var request: SFSpeechAudioBufferRecognitionRequest?
    private var task: SFSpeechRecognitionTask?
    private var recognizer: SFSpeechRecognizer?
    private var currentLocale = Locale(identifier: "en-US")
    
    // To handle appending new sessions to existing text
    private var sessionStartTranscript = ""
    
    private init() {
        // Load saved transcript
        if let saved = UserDefaults.standard.string(forKey: "voiceNoteTranscript") {
            self.transcript = saved
        }
        // Initialize default recognizer
        self.recognizer = SFSpeechRecognizer(locale: currentLocale)
        requestPermissions()
    }
    
    private func requestPermissions() {
        SFSpeechRecognizer.requestAuthorization { authStatus in
            DispatchQueue.main.async {
                switch authStatus {
                case .authorized:
                    break
                case .denied:
                    self.error = "Speech recognition authorization denied"
                case .restricted:
                    self.error = "Speech recognition restricted on this device"
                case .notDetermined:
                    self.error = "Speech recognition not yet authorized"
                @unknown default:
                    self.error = "Unknown authorization status"
                }
            }
        }
    }
    
    func setLanguage(locale: Locale) {
        currentLocale = locale
        // If we are already recording, we'd need to stop and restart, 
        // but for now we just update the recognizer for the next session
        if recognizer?.locale != locale {
            recognizer = SFSpeechRecognizer(locale: locale)
        }
    }
    
    func startTranscribing(allowOnline: Bool = true, locale: Locale? = nil) {
        // Determine locale
        if let locale = locale {
            self.currentLocale = locale
        }
        let localeToUse = self.currentLocale

        // Safety net: Reload from UserDefaults if empty
        if transcript.isEmpty {
            if let saved = UserDefaults.standard.string(forKey: "voiceNoteTranscript") {
                self.transcript = saved
            }
        }
        
        guard !isRecording else { return }
        
        // Update recognizer if needed
        if recognizer?.locale != localeToUse {
             recognizer = SFSpeechRecognizer(locale: localeToUse)
        }
        
        guard let recognizer = recognizer, recognizer.isAvailable else {
            self.error = "Speech recognizer is not available for \(localeToUse.identifier)"
            return
        }
        
        // Save current transcript as the starting point for this session
        sessionStartTranscript = transcript
        
            do {
            let audioSession = AVAudioSession.sharedInstance()
            try audioSession.setCategory(.playAndRecord, mode: .measurement, options: [.duckOthers, .defaultToSpeaker, .allowBluetoothHFP])
            try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
            
            request = SFSpeechAudioBufferRecognitionRequest()
            guard let request = request else { return }
            request.shouldReportPartialResults = true
            request.requiresOnDeviceRecognition = !allowOnline
            
            // Enable automatic punctuation (iOS 16+)
            if #available(iOS 16, *) {
                request.addsPunctuation = true
            }
            
            let inputNode = audioEngine.inputNode
            
            task = recognizer.recognitionTask(with: request) { [weak self] result, error in
                guard let self = self else { return }
                
                if let error = error {
                    // Check if we should fallback (if we were trying online and it failed)
                    if allowOnline {
                        print("Online transcription failed: \(error.localizedDescription). Retrying offline.")
                        // We must stop the current engine/request before retrying
                        self.stopTranscribing()
                        
                        // Retry with on-device only
                        // Add a small delay to ensure cleanup completes
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                            self.startTranscribing(allowOnline: false, locale: localeToUse)
                        }
                        return
                    } else {
                        // We were already offline (or forced offline), just report error
                        DispatchQueue.main.async {
                            self.error = "Transcription error: \(error.localizedDescription)"
                        }
                    }
                }
                
                if let result = result {
                    DispatchQueue.main.async {
                        // Only update if we're still recording (prevents race condition with clear)
                        guard self.isRecording else { return }
                        
                        // Append new text to the session start text
                        let newText = result.bestTranscription.formattedString
                        
                        // Ignore empty results to prevent overwriting persistence
                        guard !newText.isEmpty else { return }
                        
                        if self.sessionStartTranscript.isEmpty {
                            self.transcript = newText
                        } else {
                            self.transcript = self.sessionStartTranscript + " " + newText
                        }
                        
                        // Save to UserDefaults
                        UserDefaults.standard.set(self.transcript, forKey: "voiceNoteTranscript")
                    }
                }
                
                if error != nil || (result?.isFinal ?? false) {
                    self.stopTranscribing()
                }
            }
            
            let recordingFormat = inputNode.outputFormat(forBus: 0)
            inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
                request.append(buffer)
            }
            
            try audioEngine.start()
            isRecording = true
            error = nil
            
        } catch {
            self.error = "Error starting recording: \(error.localizedDescription)"
            stopTranscribing()
        }
    }
    
    func stopTranscribing() {
        // Ensure we only stop if we are actually recording/have resources allocated
        guard isRecording else { return }
        
        audioEngine.stop()
        audioEngine.inputNode.removeTap(onBus: 0)
        request?.endAudio()
        task?.cancel()
        
        task = nil
        request = nil
        isRecording = false
    }
    
    func clear() {
        // Stop recording first to prevent it from saving again
        stopTranscribing()
        
        // Then clear everything
        transcript = ""
        sessionStartTranscript = ""
        UserDefaults.standard.removeObject(forKey: "voiceNoteTranscript")
        
        // Restart transcribing after a brief delay to allow audio engine to fully stop
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.startTranscribing()
        }
    }
}

struct VoiceNoteView: View {
    @EnvironmentObject var themeManager: ThemeManager
    @ObservedObject var speechRecognizer = SpeechRecognizer.shared
    var onFlipBack: () -> Void
    
    @State private var fontSize: CGFloat = 40
    @AppStorage("isSpanishMode") private var isSpanishMode = false
    @State private var translatedText = ""
    @State private var triggerTranslation = false
    @State private var translationError: String?
    @State private var manualTranslationConfig: TranslationSession.Configuration?
    @State private var showTranslation = false
    @State private var translationTaskID = UUID()
    @State private var longPressTriggered = false
    @State private var showingSettingsAlert = false
    
    // New Dynamic Language State
    @ObservedObject private var languageManager = LanguageManager.shared
    @AppStorage("targetLanguageIdentifier") private var targetLanguageIdentifier: String = ""
    @State private var showSettings = false
    
    // Configuration for iOS 18+ Translation
    #if canImport(Translation)
    @State private var translationConfig: TranslationSession.Configuration?
    #endif
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                // Main Text Area
                if isSpanishMode {
                    // Target Language Mode (Single View)
                    ScrollView {
                        VStack(alignment: .leading) {
                            if showTranslation {
                                // Show English Translation
                                if let error = translationError {
                                    Text("Error: \(error)")
                                        .foregroundColor(.red)
                                        .font(.caption)
                                        .padding(.bottom)
                                }
                                Text(translatedText.isEmpty ? "Translation will appear here..." : translatedText)
                                    .font(.system(size: fontSize, weight: .bold)) // Use dynamic fontSize
                                    .foregroundColor(translatedText.isEmpty ? .gray : themeManager.textColor)
                                    .multilineTextAlignment(.leading)
                            } else {
                                // Show Target Transcript
                                Text(speechRecognizer.transcript.isEmpty ? languageManager.getStartSpeakingText(for: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier) : speechRecognizer.transcript)
                                    .font(.system(size: fontSize, weight: .bold)) // Use dynamic fontSize
                                    .foregroundColor(themeManager.textColor)
                                    .multilineTextAlignment(.leading)
                            }
                        }
                        .padding(.horizontal)
                        .padding(.top, 80) // Clear top bar
                        .padding(.bottom, 120) // Clear bottom controls
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .onChange(of: speechRecognizer.transcript) {
                            adjustFontSize(containerSize: geometry.size)
                        }
                        .onChange(of: translatedText) {
                            adjustFontSize(containerSize: geometry.size)
                        }
                        .onChange(of: showTranslation) {
                            adjustFontSize(containerSize: geometry.size)
                        }
                        .onChange(of: targetLanguageIdentifier) {
                             print("VoiceNoteView: Language changed to \(targetLanguageIdentifier)")
                             // Force state update if needed, though AppStorage should trigger redraw.
                             // Might need to update speechRecognizer language if in Spanish mode?
                             if isSpanishMode {
                                 let locale = Locale(identifier: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier)
                                 speechRecognizer.setLanguage(locale: locale)
                                 speechRecognizer.clear()
                             }
                        }
                    }
                    .scrollDisabled(true)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(themeManager.backgroundColor)
                } else {
                    // Normal English Full Screen
                    ScrollView {
                        Text(speechRecognizer.transcript.isEmpty ? "Start speaking..." : speechRecognizer.transcript)
                            .font(.system(size: fontSize, weight: .bold))
                            .foregroundColor(themeManager.textColor)
                            .multilineTextAlignment(.leading)
                            .padding(.horizontal)
                            .padding(.top, 80) // Clear top bar
                            .padding(.bottom, 120) // Clear bottom controls
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .textSelection(.enabled)
                            .onChange(of: speechRecognizer.transcript) {
                                adjustFontSize(containerSize: geometry.size)
                            }
                    }
                    .scrollDisabled(true)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                }
                
                // Top Bar with Clear All Button
                VStack {
                    HStack {
                        // Language Toggle
                        Button(action: {
                            toggleLanguage()
                        }) {
                            HStack(spacing: 6) {
                                // Dynamic Flag and Name
                                if isSpanishMode {
                                    if let lang = languageManager.supportedLanguages.first(where: { $0.id == targetLanguageIdentifier }) {
                                        Text(lang.flag)
                                            .font(.title2)
                                        Text(lang.name)
                                            .fontWeight(.semibold)
                                            .font(.system(size: 14))
                                    } else {
                                        // Fallback if not found or empty (e.g. legacy state)
                                        Text("🏳️")
                                            .font(.title2)
                                        Text("Select Language")
                                            .fontWeight(.semibold)
                                            .font(.system(size: 14))
                                    }
                                } else {
                                    Text("🇺🇸")
                                        .font(.title2)
                                    Text("English")
                                        .fontWeight(.semibold)
                                        .font(.system(size: 14))
                                }
                            }
                            .padding(.horizontal, 12)
                            .padding(.vertical, 8)
                            .background(Color.black.opacity(0.1))
                            .cornerRadius(20)
                        }
                        .padding(.leading)
                        
                        Spacer()
                        Button(action: {
                            // Ensure the recognizer stays in the correct mode
                            let localeID = isSpanishMode ? (targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier) : "en-US"
                            speechRecognizer.setLanguage(locale: Locale(identifier: localeID))
                            
                            speechRecognizer.clear()
                            translatedText = ""
                            translationError = nil
                            showTranslation = false
                            
                            // Reset translation config so it can be re-triggered
                            manualTranslationConfig?.invalidate()
                            manualTranslationConfig = nil
                        }) {
                            Text("Clear all")
                                .foregroundColor(.red)
                                .padding()
                        }
                    }
                    Spacer()
                }
                
                // Bottom Area (Status & Flip Button)
                VStack {
                    Spacer()
                    
                    ZStack {
                        // Left & Right Controls
                        HStack {
                            // Left: Status
                            VStack(alignment: .leading, spacing: 4) {
                                if speechRecognizer.isRecording {
                                    Text("Listening...")
                                        .font(.caption)
                                        .foregroundColor(.red)
                                }
                                if let error = speechRecognizer.error {
                                    Text(error)
                                        .font(.caption)
                                        .foregroundColor(.red)
                                }
                            }
                            .padding(.leading, 20)
                            
                            Spacer()
                            
                            // Right: Flip Button
                            Button(action: {
                                onFlipBack()
                            }) {
                                Text("Flip")
                                    .font(.system(size: 16, weight: .medium))
                                    .foregroundColor(.white)
                                    .padding(.horizontal, 20)
                                    .padding(.vertical, 12)
                                    .background(Color.blue)
                                    .cornerRadius(25)
                            }
                            .padding(.trailing, 20)
                        }
                        
                            // Simple Translate Button
                            if isSpanishMode {
                                Button(action: {
                                    if targetLanguageIdentifier.isEmpty {
                                        // No language selected. Prompt user to open settings.
                                        showingSettingsAlert = true
                                    } else {
                                        if showTranslation {
                                            showTranslation = false
                                        } else {
                                            performTranslation()
                                        }
                                    }
                                }) {
                                    Group {
                                        if targetLanguageIdentifier.isEmpty {
                                            Text("Translate")
                                        } else {
                                            if let lang = languageManager.supportedLanguages.first(where: { $0.id == targetLanguageIdentifier }) {
                                                if showTranslation {
                                                    Text("Original \(lang.flag)")
                                                } else {
                                                    Text("Translate to 🇺🇸")
                                                }
                                            } else {
                                                Text("Translate")
                                            }
                                        }
                                    }
                                    .fontWeight(.semibold)
                                    .padding(.horizontal, 20)
                                    .padding(.vertical, 12)
                                    .background(Color.blue)
                                    .foregroundColor(.white)
                                    .cornerRadius(25)
                                    .shadow(radius: 3)
                                }
                                .alert("Select Language", isPresented: $showingSettingsAlert) {
                                    Button("Open Settings") {
                                        showSettings = true
                                    }
                                    Button("Cancel", role: .cancel) { }
                                } message: {
                                    Text("Please select a translation language in Settings.")
                                }
                            }
                    }
                    .padding(.bottom, 20)
                    .background(
                        LinearGradient(
                            gradient: Gradient(colors: [themeManager.backgroundColor.opacity(0), themeManager.backgroundColor]),
                            startPoint: .top,
                            endPoint: .bottom
                        )
                        .frame(height: 100)
                    )
                }
                }
            .background(themeManager.backgroundColor)
            .onAppear {
                if #available(iOS 18.0, *) {
                    Task {
                        await languageManager.checkAvailability()
                    }
                }
                
                // Recalculate font size immediately in case there is existing text
                adjustFontSize(containerSize: geometry.size)
            }
            .onChange(of: targetLanguageIdentifier) {
                 if isSpanishMode {
                     let locale = Locale(identifier: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier)
                     speechRecognizer.setLanguage(locale: locale)
                     speechRecognizer.clear()
                 }
            }
            .sheet(isPresented: $showSettings, onDismiss: {
                if isSpanishMode {
                     let locale = Locale(identifier: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier)
                     speechRecognizer.setLanguage(locale: locale)
                     speechRecognizer.clear()
                }
            }) {
                SettingsView()
                    .environmentObject(themeManager)
            }

            .onDisappear {
                // speechRecognizer.stopTranscribing() - Removed to keep recording in background
            }
            // Batch Translation Task
            #if canImport(Translation)
            .translationTask(manualTranslationConfig) { session in
                do {
                    // Perform single batch translation
                    let response = try await session.translate(speechRecognizer.transcript)
                    translatedText = response.targetText
                    translationError = nil
                    // showTranslation is already true
                } catch {
                    // Suppress specific "empty" errors or generic noise
                    let errorMsg = error.localizedDescription
                    if !errorMsg.localizedCaseInsensitiveContains("empty") {
                         print("Translation error: \(error)")
                         translationError = errorMsg
                    } else {
                        translationError = nil
                        // If silently failed, revert view so user can try again or see transcript
                        showTranslation = false
                    }
                }
            }
            #else
            // Fallback or empty logic for older iOS versions handled by UI checks
            #endif
            .id(translationTaskID) // Force recreation of the task on every request
            .gesture(
                DragGesture()
                    .onEnded { value in
                        if value.translation.width > 50 {
                            // Swipe Right -> Flip Back
                            onFlipBack()
                        } else if value.translation.width < -50 {
                            // Swipe Left -> Clear & Reset
                            if showTranslation {
                                showTranslation = false
                            }
                            speechRecognizer.clear()
                        }
                    }
            )



    }
}
    
    // Toggle Logic
    private func toggleLanguage() {
        isSpanishMode.toggle()
        showTranslation = false
        
        // Stop current recording
        speechRecognizer.stopTranscribing()
        
        // Update the locale in SpeechRecognizer immediately
        // Update the locale in SpeechRecognizer immediately
        let localeID = isSpanishMode ? (targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier) : "en-US"
        speechRecognizer.setLanguage(locale: Locale(identifier: localeID))
        
        // Clear old text and restart (clear() automatically restarts transcription using the current locale)
        speechRecognizer.clear()
        
        // Configure translation session if needed
        if #available(iOS 18.0, *), isSpanishMode {
            #if canImport(Translation)
            // Invalidating and recreating config triggers the task
            manualTranslationConfig = TranslationSession.Configuration(
                source: Locale.Language(identifier: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier),
                target: Locale.Language(identifier: "en-US")
            )
            #endif
        } else {
            #if canImport(Translation)
            manualTranslationConfig?.invalidate()
            manualTranslationConfig = nil
            #endif
        }
    }
    
    // Trigger translation
    private func performTranslation() {
        guard !speechRecognizer.transcript.isEmpty else { return }
        translatedText = "Translating..."
        translationError = nil
        showTranslation = true // Show loading state immediately
        
        if #available(iOS 18.0, *) {
            #if canImport(Translation)
            // Force a reset of the configuration
            if manualTranslationConfig != nil {
                manualTranslationConfig?.invalidate()
                manualTranslationConfig = nil
            }
            
            let langId = targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier
            
            // All languages use .translationTask modifier
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                translationTaskID = UUID()
                manualTranslationConfig = TranslationSession.Configuration(
                    source: Locale.Language(identifier: langId),
                    target: Locale.Language(identifier: "en-US")
                )
            }
            #endif
        } else {
            translationError = "Translation requires iOS 18"
        }
    }
    
    private func startWithCurrentLanguage() {
        let localeID = isSpanishMode ? (targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier) : "en-US"
        speechRecognizer.startTranscribing(locale: Locale(identifier: localeID))
    }
    
    private func adjustFontSize(containerSize: CGSize) {
        
        let maxFontSize: CGFloat = 40
        let minFontSize: CGFloat = 12
        // Use the displayed text for sizing
        let text: String
         if isSpanishMode {
             if showTranslation {
                 text = translatedText.isEmpty ? "Translation will appear here..." : translatedText
             } else {
                 text = speechRecognizer.transcript.isEmpty ? languageManager.getStartSpeakingText(for: targetLanguageIdentifier.isEmpty ? "es-MX" : targetLanguageIdentifier) : speechRecognizer.transcript
             }
         } else {
              text = speechRecognizer.transcript.isEmpty ? "Start speaking..." : speechRecognizer.transcript
         }
        // Account for padding
        let horizontalPadding: CGFloat = 32 // 16 * 2
        let width = containerSize.width - horizontalPadding
        let height = containerSize.height - 180 // Increased buffer for bottom controls
        
        var bestSize = minFontSize
        
        for size in stride(from: maxFontSize, through: minFontSize, by: -2) {
            let font = UIFont.systemFont(ofSize: size, weight: .bold)
            let attributes = [NSAttributedString.Key.font: font]
            let boundingRect = NSString(string: text).boundingRect(
                with: CGSize(width: width, height: .greatestFiniteMagnitude),
                options: [.usesLineFragmentOrigin, .usesFontLeading],
                attributes: attributes,
                context: nil
            )
            
            if boundingRect.height <= height {
                bestSize = size
                break
            }
        }
        
        if fontSize != bestSize {
            withAnimation {
                fontSize = bestSize
            }
        }
    }
}



