import SwiftUI
import KeyboardShortcuts

struct ConfigurationView: View {
    let mode: ConfigurationMode
    let powerModeManager: PowerModeManager
    @EnvironmentObject var enhancementService: AIEnhancementService
    @EnvironmentObject var aiService: AIService
    @Environment(\.presentationMode) private var presentationMode
    @FocusState private var isNameFieldFocused: Bool
    
    // State for configuration
    @State private var configName: String = "New Power Mode"
    @State private var selectedEmoji: String = "💼"
    @State private var isShowingEmojiPicker = false
    @State private var isShowingAppPicker = false
    @State private var isAIEnhancementEnabled: Bool
    @State private var selectedPromptId: UUID?
    @State private var selectedTranscriptionModelName: String?
    @State private var selectedLanguage: String?
    @State private var installedApps: [(url: URL, name: String, bundleId: String, icon: NSImage)] = []
    @State private var searchText = ""
    
    // Validation state
    @State private var validationErrors: [PowerModeValidationError] = []
    @State private var showValidationAlert = false
    
    // New state for AI provider and model
    @State private var selectedAIProvider: String?
    @State private var selectedAIModel: String?
    
    // App and Website configurations
    @State private var selectedAppConfigs: [AppConfig] = []
    @State private var websiteConfigs: [URLConfig] = []
    @State private var newWebsiteURL: String = ""
    
    // New state for screen capture toggle
    @State private var useScreenCapture = false
    @State private var isAutoSendEnabled = false
    @State private var isDefault = false
    
    @State private var isShowingDeleteConfirmation = false

    // PowerMode hotkey configuration
    @State private var powerModeConfigId: UUID = UUID()

    private func languageSelectionDisabled() -> Bool {
        guard let selectedModelName = effectiveModelName,
              let model = whisperState.allAvailableModels.first(where: { $0.name == selectedModelName })
        else {
            return false
        }
        return model.provider == .parakeet || model.provider == .gemini
    }
    
    // Whisper state for model selection
    @EnvironmentObject private var whisperState: WhisperState
    
    // Computed property to check if current config is the default
    private var isCurrentConfigDefault: Bool {
        if case .edit(let config) = mode {
            return config.isDefault
        }
        return false
    }
    
    private var filteredApps: [(url: URL, name: String, bundleId: String, icon: NSImage)] {
        if searchText.isEmpty {
            return installedApps
        }
        return installedApps.filter { app in
            app.name.localizedCaseInsensitiveContains(searchText) ||
            app.bundleId.localizedCaseInsensitiveContains(searchText)
        }
    }
    
    // Simplified computed property for effective model name
    private var effectiveModelName: String? {
        if let model = selectedTranscriptionModelName {
            return model
        }
        return whisperState.currentTranscriptionModel?.name
    }
    
    init(mode: ConfigurationMode, powerModeManager: PowerModeManager) {
        self.mode = mode
        self.powerModeManager = powerModeManager

        // Always fetch the most current configuration data
        switch mode {
        case .add:
            let newId = UUID()
            _powerModeConfigId = State(initialValue: newId)
            _isAIEnhancementEnabled = State(initialValue: true)
            _selectedPromptId = State(initialValue: nil)
            _selectedTranscriptionModelName = State(initialValue: nil)
            _selectedLanguage = State(initialValue: nil)
            _configName = State(initialValue: "")
            _selectedEmoji = State(initialValue: "✏️")
            _useScreenCapture = State(initialValue: false)
            _isAutoSendEnabled = State(initialValue: false)
            _isDefault = State(initialValue: false)
            // Default to current global AI provider/model for new configurations - use UserDefaults only
            _selectedAIProvider = State(initialValue: UserDefaults.standard.string(forKey: "selectedAIProvider"))
            _selectedAIModel = State(initialValue: nil) // Initialize to nil and set it after view appears
        case .edit(let config):
            // Get the latest version of this config from PowerModeManager
            let latestConfig = powerModeManager.getConfiguration(with: config.id) ?? config
            _powerModeConfigId = State(initialValue: latestConfig.id)
            _isAIEnhancementEnabled = State(initialValue: latestConfig.isAIEnhancementEnabled)
            _selectedPromptId = State(initialValue: latestConfig.selectedPrompt.flatMap { UUID(uuidString: $0) })
            _selectedTranscriptionModelName = State(initialValue: latestConfig.selectedTranscriptionModelName)
            _selectedLanguage = State(initialValue: latestConfig.selectedLanguage)
            _configName = State(initialValue: latestConfig.name)
            _selectedEmoji = State(initialValue: latestConfig.emoji)
            _selectedAppConfigs = State(initialValue: latestConfig.appConfigs ?? [])
            _websiteConfigs = State(initialValue: latestConfig.urlConfigs ?? [])
            _useScreenCapture = State(initialValue: latestConfig.useScreenCapture)
            _isAutoSendEnabled = State(initialValue: latestConfig.isAutoSendEnabled)
            _isDefault = State(initialValue: latestConfig.isDefault)
            _selectedAIProvider = State(initialValue: latestConfig.selectedAIProvider)
            _selectedAIModel = State(initialValue: latestConfig.selectedAIModel)
        }
    }
    
    var body: some View {
        Form {
            Section("General") {
                HStack(spacing: 12) {
                    Button {
                        isShowingEmojiPicker.toggle()
                    } label: {
                        Text(selectedEmoji)
                            .font(.system(size: 22))
                            .frame(width: 32, height: 32)
                            .background(
                                RoundedRectangle(cornerRadius: 8)
                                    .fill(Color(NSColor.controlBackgroundColor))
                            )
                    }
                    .buttonStyle(.plain)
                    .popover(isPresented: $isShowingEmojiPicker, arrowEdge: .bottom) {
                        EmojiPickerView(
                            selectedEmoji: $selectedEmoji,
                            isPresented: $isShowingEmojiPicker
                        )
                    }

                    TextField("Name", text: $configName)
                        .textFieldStyle(.roundedBorder)
                        .focused($isNameFieldFocused)
                }
            }

            Section("Trigger Scenarios") {
                VStack(alignment: .leading, spacing: 10) {
                    HStack {
                        Text("Applications")
                        Spacer()
                        AddIconButton(helpText: "Add application") {
                            loadInstalledApps()
                            isShowingAppPicker = true
                        }
                    }

                    if selectedAppConfigs.isEmpty {
                        Text("No applications added")
                            .foregroundColor(.secondary)
                            .font(.subheadline)
                    } else {
                        LazyVGrid(columns: [GridItem(.adaptive(minimum: 44, maximum: 50), spacing: 10)], spacing: 10) {
                            ForEach(selectedAppConfigs) { appConfig in
                                ZStack(alignment: .topTrailing) {
                                    if let appURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: appConfig.bundleIdentifier) {
                                        Image(nsImage: NSWorkspace.shared.icon(forFile: appURL.path))
                                            .resizable()
                                            .aspectRatio(contentMode: .fill)
                                            .frame(width: 44, height: 44)
                                            .clipShape(RoundedRectangle(cornerRadius: 10))
                                    } else {
                                        Image(systemName: "app.fill")
                                            .resizable()
                                            .aspectRatio(contentMode: .fit)
                                            .frame(width: 26, height: 26)
                                            .frame(width: 44, height: 44)
                                            .background(
                                                RoundedRectangle(cornerRadius: 10)
                                                    .fill(Color(NSColor.controlBackgroundColor))
                                            )
                                    }

                                    Button {
                                        selectedAppConfigs.removeAll(where: { $0.id == appConfig.id })
                                    } label: {
                                        Image(systemName: "xmark.circle.fill")
                                            .font(.system(size: 14))
                                            .foregroundColor(.secondary)
                                    }
                                    .buttonStyle(.plain)
                                    .offset(x: 6, y: -6)
                                }
                            }
                        }
                        .padding(.vertical, 2)
                    }
                }
                .padding(.vertical, 2)

                VStack(alignment: .leading, spacing: 10) {
                    Text("Websites")

                    HStack {
                        TextField("Enter website URL (e.g., google.com)", text: $newWebsiteURL)
                            .textFieldStyle(.roundedBorder)
                            .onSubmit { addWebsite() }

                        AddIconButton(helpText: "Add website", isDisabled: newWebsiteURL.isEmpty) {
                            addWebsite()
                        }
                    }

                    if websiteConfigs.isEmpty {
                        Text("No websites added")
                            .foregroundColor(.secondary)
                            .font(.subheadline)
                    } else {
                        LazyVGrid(columns: [GridItem(.adaptive(minimum: 140, maximum: 220), spacing: 10)], spacing: 10) {
                            ForEach(websiteConfigs) { urlConfig in
                                HStack(spacing: 6) {
                                    Image(systemName: "globe")
                                        .foregroundColor(.secondary)
                                    Text(urlConfig.url)
                                        .lineLimit(1)
                                    Spacer(minLength: 0)
                                    Button {
                                        websiteConfigs.removeAll(where: { $0.id == urlConfig.id })
                                    } label: {
                                        Image(systemName: "xmark.circle.fill")
                                            .foregroundColor(.secondary)
                                    }
                                    .buttonStyle(.plain)
                                }
                                .padding(.horizontal, 8)
                                .padding(.vertical, 6)
                                .background(
                                    RoundedRectangle(cornerRadius: 8)
                                        .fill(Color(NSColor.controlBackgroundColor))
                                )
                            }
                        }
                        .padding(.vertical, 2)
                    }
                }
                .padding(.vertical, 2)
            }

            Section("Transcription") {
                if whisperState.usableModels.isEmpty {
                    Text("No transcription models available. Please connect to a cloud service or download a local model in the AI Models tab.")
                        .foregroundColor(.secondary)
                } else {
                    let modelBinding = Binding<String?>(
                        get: { selectedTranscriptionModelName ?? whisperState.usableModels.first?.name },
                        set: { selectedTranscriptionModelName = $0 }
                    )

                    Picker("Model", selection: modelBinding) {
                        ForEach(whisperState.usableModels, id: \.name) { model in
                            Text(model.displayName).tag(model.name as String?)
                        }
                    }
                    .onChange(of: selectedTranscriptionModelName) { _, newModelName in
                        // Auto-set language to "auto" for models that only support auto-detection
                        if let modelName = newModelName ?? whisperState.usableModels.first?.name,
                           let model = whisperState.allAvailableModels.first(where: { $0.name == modelName }),
                           model.provider == .parakeet || model.provider == .gemini {
                            selectedLanguage = "auto"
                        }
                    }
                }

                if languageSelectionDisabled() {
                    LabeledContent("Language") {
                        Text("Autodetected")
                            .foregroundColor(.secondary)
                    }
                    .onAppear {
                        selectedLanguage = "auto"
                    }
                } else if let selectedModel = effectiveModelName,
                          let modelInfo = whisperState.allAvailableModels.first(where: { $0.name == selectedModel }),
                          modelInfo.isMultilingualModel {
                    let languageBinding = Binding<String?>(
                        get: { selectedLanguage ?? UserDefaults.standard.string(forKey: "SelectedLanguage") ?? "auto" },
                        set: { selectedLanguage = $0 }
                    )

                    Picker("Language", selection: languageBinding) {
                        ForEach(modelInfo.supportedLanguages.sorted(by: {
                            if $0.key == "auto" { return true }
                            if $1.key == "auto" { return false }
                            return $0.value < $1.value
                        }), id: \.key) { key, value in
                            Text(value).tag(key as String?)
                        }
                    }
                } else if let selectedModel = effectiveModelName,
                          let modelInfo = whisperState.allAvailableModels.first(where: { $0.name == selectedModel }),
                          !modelInfo.isMultilingualModel {
                    EmptyView()
                        .onAppear {
                            if selectedLanguage == nil {
                                selectedLanguage = "en"
                            }
                        }
                }
            }

            Section("AI Enhancement") {
                Toggle("Enable AI Enhancement", isOn: $isAIEnhancementEnabled)
                    .onChange(of: isAIEnhancementEnabled) { _, newValue in
                        if newValue {
                            if selectedAIProvider == nil {
                                selectedAIProvider = aiService.selectedProvider.rawValue
                            }
                            if selectedAIModel == nil {
                                selectedAIModel = aiService.currentModel
                            }
                            if selectedPromptId == nil {
                                selectedPromptId = enhancementService.allPrompts.first?.id
                            }
                        }
                    }

                let providerBinding = Binding<AIProvider>(
                    get: {
                        if let providerName = selectedAIProvider,
                           let provider = AIProvider(rawValue: providerName) {
                            return provider
                        }
                        return aiService.selectedProvider
                    },
                    set: { newValue in
                        selectedAIProvider = newValue.rawValue
                        aiService.selectedProvider = newValue
                        selectedAIModel = nil
                    }
                )

                if isAIEnhancementEnabled {
                    if aiService.connectedProviders.isEmpty {
                        LabeledContent("AI Provider") {
                            Text("No providers connected")
                                .foregroundColor(.secondary)
                                .italic()
                        }
                    } else {
                        Picker("AI Provider", selection: providerBinding) {
                            ForEach(aiService.connectedProviders.filter { $0 != .elevenLabs && $0 != .deepgram }, id: \.self) { provider in
                                Text(provider.rawValue).tag(provider)
                            }
                        }
                        .onChange(of: selectedAIProvider) { _, newValue in
                            if let provider = newValue.flatMap({ AIProvider(rawValue: $0) }) {
                                selectedAIModel = provider.defaultModel
                            }
                        }
                    }

                    let providerName = selectedAIProvider ?? aiService.selectedProvider.rawValue
                    if let provider = AIProvider(rawValue: providerName),
                       provider != .custom {
                        if aiService.availableModels.isEmpty {
                            LabeledContent("AI Model") {
                                Text(provider == .openRouter ? "No models loaded" : "No models available")
                                    .foregroundColor(.secondary)
                                    .italic()
                            }
                        } else {
                            let modelBinding = Binding<String>(
                                get: {
                                    if let model = selectedAIModel, !model.isEmpty { return model }
                                    return aiService.currentModel
                                },
                                set: { newModelValue in
                                    selectedAIModel = newModelValue
                                    aiService.selectModel(newModelValue)
                                }
                            )

                            let models = provider == .openRouter ? aiService.availableModels : (provider == .ollama ? aiService.availableModels : provider.availableModels)

                            Picker("AI Model", selection: modelBinding) {
                                ForEach(models, id: \.self) { model in
                                    Text(model).tag(model)
                                }
                            }

                            if provider == .openRouter {
                                Button("Refresh Models") {
                                    Task { await aiService.fetchOpenRouterModels() }
                                }
                                .help("Refresh models")
                            }
                        }
                    }

                    if enhancementService.allPrompts.isEmpty {
                        LabeledContent("Enhancement Prompt") {
                            Text("No prompts available")
                                .foregroundColor(.secondary)
                        }
                    } else {
                        Picker("Enhancement Prompt", selection: $selectedPromptId) {
                            ForEach(enhancementService.allPrompts) { prompt in
                                Text(prompt.title).tag(prompt.id as UUID?)
                            }
                        }
                    }

                    Toggle("Context Awareness", isOn: $useScreenCapture)
                }
            }

            Section("Advanced") {
                Toggle(isOn: $isDefault) {
                    HStack(spacing: 6) {
                        Text("Set as default")
                        InfoTip(
                            title: "Default Power Mode",
                            message: "Default power mode is used when no specific app or website matches are found"
                        )
                    }
                }

                Toggle(isOn: $isAutoSendEnabled) {
                    HStack(spacing: 6) {
                        Text("Auto Send")
                        InfoTip(
                            title: "Auto Send",
                            message: "Automatically presses the Return/Enter key after pasting text. This is useful for chat applications or forms where its not necessary to to make changes to the transcribed text"
                        )
                    }
                }

                HStack {
                    Text("Keyboard Shortcut")
                    InfoTip(
                        title: "Power Mode Hotkey",
                        message: "Assign a unique keyboard shortcut to instantly activate this Power Mode and start recording"
                    )

                    Spacer()

                    KeyboardShortcuts.Recorder(for: .powerMode(id: powerModeConfigId))
                        .controlSize(.regular)
                        .frame(minHeight: 28)
                }
            }
        }
        .formStyle(.grouped)
        .scrollContentBackground(.hidden)
        .background(Color(NSColor.controlBackgroundColor))
        .navigationTitle(mode.title)
        .toolbar {
            ToolbarItem(placement: .primaryAction) {
                Button("Save") {
                    saveConfiguration()
                }
                .keyboardShortcut(.defaultAction)
                .disabled(!canSave)
                .buttonStyle(.bordered)
                .controlSize(.regular)
                .padding(.horizontal, 4)
            }

            if case .edit = mode {
                ToolbarItem {
                    Button("Delete", role: .destructive) {
                        isShowingDeleteConfirmation = true
                    }
                    .buttonStyle(.bordered)
                    .controlSize(.regular)
                    .padding(.horizontal, 4)
                }
            }
        }
        .confirmationDialog(
            "Delete Power Mode?",
            isPresented: $isShowingDeleteConfirmation,
            titleVisibility: .visible
        ) {
            if case .edit(let config) = mode {
                Button("Delete", role: .destructive) {
                    powerModeManager.removeConfiguration(with: config.id)
                    presentationMode.wrappedValue.dismiss()
                }
            }
            Button("Cancel", role: .cancel) { }
        } message: {
            if case .edit(let config) = mode {
                Text("Are you sure you want to delete the '\(config.name)' power mode? This action cannot be undone.")
            }
        }
        .sheet(isPresented: $isShowingAppPicker) {
            AppPickerSheet(
                installedApps: filteredApps,
                selectedAppConfigs: $selectedAppConfigs,
                searchText: $searchText,
                onDismiss: { isShowingAppPicker = false }
            )
        }
        .powerModeValidationAlert(errors: validationErrors, isPresented: $showValidationAlert)
        .onAppear {
            // Set AI provider and model for new power modes after environment objects are available
            if case .add = mode {
                if selectedAIProvider == nil {
                    selectedAIProvider = aiService.selectedProvider.rawValue
                }
                if selectedAIModel == nil || selectedAIModel?.isEmpty == true {
                    selectedAIModel = aiService.currentModel
                }
            }
            
            // Select first prompt if AI enhancement is enabled and no prompt is selected
            if isAIEnhancementEnabled && selectedPromptId == nil {
                selectedPromptId = enhancementService.allPrompts.first?.id
            }

            // Focus the name field for faster keyboard-driven setup
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                isNameFieldFocused = true
            }
        }
    }
    
    private var canSave: Bool {
        return !configName.isEmpty
    }
    
    private func addWebsite() {
        guard !newWebsiteURL.isEmpty else { return }
        
        let cleanedURL = powerModeManager.cleanURL(newWebsiteURL)
        let urlConfig = URLConfig(url: cleanedURL)
        websiteConfigs.append(urlConfig)
        newWebsiteURL = ""
    }
    
    private func toggleAppSelection(_ app: (url: URL, name: String, bundleId: String, icon: NSImage)) {
        if let index = selectedAppConfigs.firstIndex(where: { $0.bundleIdentifier == app.bundleId }) {
            selectedAppConfigs.remove(at: index)
        } else {
            let appConfig = AppConfig(bundleIdentifier: app.bundleId, appName: app.name)
            selectedAppConfigs.append(appConfig)
        }
    }
    
    private func getConfigForForm() -> PowerModeConfig {
        let shortcut = KeyboardShortcuts.getShortcut(for: .powerMode(id: powerModeConfigId))
        let hotkeyString = shortcut != nil ? "configured" : nil

        switch mode {
        case .add:
                return PowerModeConfig(
                id: powerModeConfigId,
                name: configName,
                emoji: selectedEmoji,
                appConfigs: selectedAppConfigs.isEmpty ? nil : selectedAppConfigs,
                urlConfigs: websiteConfigs.isEmpty ? nil : websiteConfigs,
                    isAIEnhancementEnabled: isAIEnhancementEnabled,
                    selectedPrompt: selectedPromptId?.uuidString,
                    selectedTranscriptionModelName: selectedTranscriptionModelName,
                    selectedLanguage: selectedLanguage,
                    useScreenCapture: useScreenCapture,
                    selectedAIProvider: selectedAIProvider,
                    selectedAIModel: selectedAIModel,
                    isAutoSendEnabled: isAutoSendEnabled,
                    isDefault: isDefault,
                    hotkeyShortcut: hotkeyString
                )
        case .edit(let config):
            var updatedConfig = config
            updatedConfig.name = configName
            updatedConfig.emoji = selectedEmoji
            updatedConfig.isAIEnhancementEnabled = isAIEnhancementEnabled
            updatedConfig.selectedPrompt = selectedPromptId?.uuidString
            updatedConfig.selectedTranscriptionModelName = selectedTranscriptionModelName
            updatedConfig.selectedLanguage = selectedLanguage
            updatedConfig.appConfigs = selectedAppConfigs.isEmpty ? nil : selectedAppConfigs
            updatedConfig.urlConfigs = websiteConfigs.isEmpty ? nil : websiteConfigs
            updatedConfig.useScreenCapture = useScreenCapture
            updatedConfig.isAutoSendEnabled = isAutoSendEnabled
            updatedConfig.selectedAIProvider = selectedAIProvider
            updatedConfig.selectedAIModel = selectedAIModel
            updatedConfig.isDefault = isDefault
            updatedConfig.hotkeyShortcut = hotkeyString
            return updatedConfig
        }
    }
    
    private func loadInstalledApps() {
        // Get both user-installed and system applications
        let userAppURLs = FileManager.default.urls(for: .applicationDirectory, in: .userDomainMask)
        let localAppURLs = FileManager.default.urls(for: .applicationDirectory, in: .localDomainMask)
        let systemAppURLs = FileManager.default.urls(for: .applicationDirectory, in: .systemDomainMask)
        let allAppURLs = userAppURLs + localAppURLs + systemAppURLs
        
        var allApps: [URL] = []
        
        func scanDirectory(_ baseURL: URL, depth: Int = 0) {
            // Prevent infinite recursion in case of circular symlinks
            guard depth < 5 else { return }
            
            guard let enumerator = FileManager.default.enumerator(
                at: baseURL,
                includingPropertiesForKeys: [.isApplicationKey, .isDirectoryKey, .isSymbolicLinkKey],
                options: [.skipsHiddenFiles]
            ) else { return }
            
            for item in enumerator {
                guard let url = item as? URL else { continue }
                
                let resolvedURL = url.resolvingSymlinksInPath()
                
                // If it's an app, add it and skip descending into it
                if resolvedURL.pathExtension == "app" {
                    allApps.append(resolvedURL)
                    enumerator.skipDescendants()
                    continue
                }
                
                // Check if this is a symlinked directory we should traverse manually
                var isDirectory: ObjCBool = false
                if url != resolvedURL && 
                   FileManager.default.fileExists(atPath: resolvedURL.path, isDirectory: &isDirectory) && 
                   isDirectory.boolValue {
                    // This is a symlinked directory - traverse it manually
                    enumerator.skipDescendants()
                    scanDirectory(resolvedURL, depth: depth + 1)
                }
            }
        }
        
        // Scan all app directories
        for baseURL in allAppURLs {
            scanDirectory(baseURL)
        }
        
        installedApps = allApps.compactMap { url in
            guard let bundle = Bundle(url: url),
                  let bundleId = bundle.bundleIdentifier,
                  let name = (bundle.infoDictionary?["CFBundleName"] as? String) ??
                            (bundle.infoDictionary?["CFBundleDisplayName"] as? String) else {
                return nil
            }
            
            let icon = NSWorkspace.shared.icon(forFile: url.path)
            return (url: url, name: name, bundleId: bundleId, icon: icon)
        }
        .sorted { $0.name.localizedCaseInsensitiveCompare($1.name) == .orderedAscending }
    }
    
    private func saveConfiguration() {
        
        
        let config = getConfigForForm()
        
        // Only validate when the user explicitly tries to save
        let validator = PowerModeValidator(powerModeManager: powerModeManager)
        validationErrors = validator.validateForSave(config: config, mode: mode)
        
        if !validationErrors.isEmpty {
            showValidationAlert = true
            return
        }
        
        if isDefault {
            powerModeManager.setAsDefault(configId: config.id, skipSave: true)
        }

        switch mode {
        case .add:
            powerModeManager.addConfiguration(config)
        case .edit:
            powerModeManager.updateConfiguration(config)
        }

        presentationMode.wrappedValue.dismiss()
    }
}
