import SwiftUI
import SwiftData
import SharedModels

enum IrregularityCategory: String, CaseIterable, Identifiable {
    case anyIrregular = "Any Irregular"
    case spelling = "Spelling Change"
    case stemChange = "Stem Change"
    case uniqueIrregular = "Unique Irregular"

    var id: String { rawValue }

    var systemImage: String {
        switch self {
        case .anyIrregular: "asterisk"
        case .spelling: "character.cursor.ibeam"
        case .stemChange: "arrow.triangle.2.circlepath"
        case .uniqueIrregular: "star"
        }
    }
}

struct VerbListView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(\.cloudModelContextProvider) private var cloudModelContextProvider
    @Environment(ReflexiveVerbStore.self) private var reflexiveStore
    @State private var verbs: [Verb] = []
    @State private var irregularityByVerbId: [Int: Set<IrregularityCategory>] = [:]
    @State private var searchText = ""
    @State private var progress: UserProgress?
    @State private var selectedIrregularity: IrregularityCategory?
    @State private var reflexiveOnly: Bool = false
    @State private var selectedVerb: Verb?

    private var cloudContext: ModelContext { cloudModelContextProvider() }

    /// Levels currently enabled in `UserProgress` — the same set that drives
    /// what Practice picks from. The Verbs tab reads and writes the same
    /// state so changes here propagate to Practice and vice versa.
    private var selectedLevels: Set<VerbLevel> {
        progress?.selectedVerbLevels ?? []
    }

    /// True when the user has every available level enabled (or none, which
    /// we treat as "no filter applied" on the Verbs list specifically).
    private var allLevelsActive: Bool {
        selectedLevels.isEmpty || selectedLevels.count == VerbLevel.allCases.count
    }

    private var filteredVerbs: [Verb] {
        var result = verbs
        if !allLevelsActive {
            let activeRaws = Set(selectedLevels.map(\.rawValue))
            result = result.filter { verb in
                activeRaws.contains { VerbLevelGroup.matches(verb.level, selectedLevel: $0) }
            }
        }
        if let category = selectedIrregularity {
            result = result.filter { verb in
                guard let cats = irregularityByVerbId[verb.id] else { return false }
                return category == .anyIrregular ? !cats.isEmpty : cats.contains(category)
            }
        }
        if reflexiveOnly {
            result = result.filter { reflexiveStore.isReflexive(baseInfinitive: $0.infinitive) }
        }
        if !searchText.isEmpty {
            let query = searchText.lowercased()
            result = result.filter {
                $0.infinitive.lowercased().contains(query) ||
                $0.english.lowercased().contains(query)
            }
        }
        return result
    }

    private let levels: [VerbLevel] = VerbLevel.allCases

    var body: some View {
        NavigationSplitView {
            List(filteredVerbs, selection: $selectedVerb) { verb in
                NavigationLink(value: verb) {
                    VerbRowView(verb: verb, irregularities: irregularityByVerbId[verb.id] ?? [])
                }
            }
            .navigationTitle("Verbs")
            .searchable(text: $searchText, prompt: "Search verbs...")
            .safeAreaInset(edge: .top, spacing: 0) {
                if hasActiveFilter {
                    activeFilterBar
                }
            }
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Menu {
                        Section("Level") {
                            Button {
                                setAllLevels(enabled: true)
                            } label: {
                                Label("All Levels", systemImage: allLevelsActive ? "checkmark" : "circle")
                            }
                            ForEach(levels, id: \.self) { level in
                                Button {
                                    toggleLevel(level)
                                } label: {
                                    Label(level.displayName, systemImage: selectedLevels.contains(level) ? "checkmark" : "circle")
                                }
                            }
                        }

                        Section("Irregularity") {
                            Button {
                                selectedIrregularity = nil
                            } label: {
                                Label("All Verbs", systemImage: selectedIrregularity == nil ? "checkmark" : "circle")
                            }
                            ForEach(IrregularityCategory.allCases) { category in
                                Button {
                                    selectedIrregularity = category
                                } label: {
                                    Label(category.rawValue, systemImage: selectedIrregularity == category ? "checkmark" : category.systemImage)
                                }
                            }
                        }

                        Section("Reflexive") {
                            Button {
                                reflexiveOnly.toggle()
                            } label: {
                                Label("Reflexive verbs only", systemImage: reflexiveOnly ? "checkmark" : "arrow.triangle.2.circlepath")
                            }
                        }
                    } label: {
                        Label("Filter", systemImage: hasActiveFilter ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease.circle")
                    }
                }
            }
            .task {
                loadVerbs()
                loadProgress()
            }
            .onAppear {
                loadVerbs()
                loadProgress()
            }
        } detail: {
            if let verb = selectedVerb {
                VerbDetailView(verb: verb)
            } else {
                ContentUnavailableView("Select a Verb", systemImage: "textformat.abc", description: Text("Choose a verb from the list to see its conjugations."))
            }
        }
    }

    private var hasActiveFilter: Bool {
        !allLevelsActive || selectedIrregularity != nil || reflexiveOnly
    }

    @ViewBuilder
    private var activeFilterBar: some View {
        HStack(spacing: 8) {
            if !allLevelsActive {
                filterChip(text: levelChipLabel, systemImage: "graduationcap") {
                    setAllLevels(enabled: true)
                }
            }
            if let cat = selectedIrregularity {
                filterChip(text: cat.rawValue, systemImage: cat.systemImage) {
                    selectedIrregularity = nil
                }
            }
            if reflexiveOnly {
                filterChip(text: "Reflexive", systemImage: "arrow.triangle.2.circlepath") {
                    reflexiveOnly = false
                }
            }
            Spacer()
            Text("\(filteredVerbs.count)")
                .font(.caption.monospacedDigit())
                .foregroundStyle(.secondary)
        }
        .padding(.horizontal)
        .padding(.vertical, 8)
        .background(.bar)
    }

    private func filterChip(text: String, systemImage: String, onClear: @escaping () -> Void) -> some View {
        Button(action: onClear) {
            HStack(spacing: 4) {
                Image(systemName: systemImage)
                    .font(.caption2)
                Text(text)
                    .font(.caption.weight(.medium))
                Image(systemName: "xmark")
                    .font(.caption2)
            }
            .padding(.horizontal, 10)
            .padding(.vertical, 5)
            .background(.blue.opacity(0.15), in: Capsule())
            .foregroundStyle(.blue)
        }
        .buttonStyle(.plain)
    }

    private func loadVerbs() {
        // Hit the shared local container directly, bypassing @Environment.
        guard let container = SharedStore.localContainer else {
            print("[VerbListView] ⚠️ SharedStore.localContainer is nil")
            return
        }
        if let url = SharedStore.localStoreURL() {
            StoreInspector.dump(at: url, label: "verb-list-load")
        }
        let context = ModelContext(container)
        verbs = ReferenceStore(context: context).fetchVerbs()
        irregularityByVerbId = buildIrregularityIndex(context: context)
        print("[VerbListView] loaded \(verbs.count) verbs, \(irregularityByVerbId.count) flagged irregular (container: \(ObjectIdentifier(container)))")
    }

    // MARK: - Level filter (shared with Practice via UserProgress)

    private var levelChipLabel: String {
        let names = selectedLevels
            .sorted { $0.rawValue < $1.rawValue }
            .map(\.displayName)
        if names.isEmpty { return "No levels" }
        if names.count == 1 { return names[0] }
        return "\(names.count) levels"
    }

    private func loadProgress() {
        progress = ReviewStore.fetchOrCreateUserProgress(context: cloudContext)
    }

    private func toggleLevel(_ level: VerbLevel) {
        guard let progress else { return }
        let enabled = !progress.selectedVerbLevels.contains(level)
        progress.setLevelEnabled(level, enabled: enabled)
        try? cloudContext.save()
    }

    private func setAllLevels(enabled: Bool) {
        guard let progress else { return }
        if enabled {
            progress.selectedVerbLevels = Set(VerbLevel.allCases)
        } else {
            // Practice treats an empty set as "no verbs", so guard against
            // leaving the user with nothing — keep at least `basic`.
            progress.selectedVerbLevels = [.basic]
        }
        try? cloudContext.save()
    }

    private func buildIrregularityIndex(context: ModelContext) -> [Int: Set<IrregularityCategory>] {
        let spans = (try? context.fetch(FetchDescriptor<IrregularSpan>())) ?? []
        var index: [Int: Set<IrregularityCategory>] = [:]
        for span in spans {
            let category: IrregularityCategory
            switch span.spanType {
            case 100..<200: category = .spelling
            case 200..<300: category = .stemChange
            case 300..<400: category = .uniqueIrregular
            default: continue
            }
            index[span.verbId, default: []].insert(category)
        }
        return index
    }
}

struct VerbRowView: View {
    let verb: Verb
    var irregularities: Set<IrregularityCategory> = []

    var body: some View {
        HStack {
            VStack(alignment: .leading, spacing: 2) {
                Text(verb.infinitive)
                    .font(.headline)
                Text(verb.english)
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }

            Spacer()

            HStack(spacing: 4) {
                ForEach(orderedIrregularities, id: \.self) { cat in
                    Image(systemName: cat.systemImage)
                        .font(.caption2.weight(.semibold))
                        .foregroundStyle(irregularityColor(cat))
                        .help(cat.rawValue)
                        .accessibilityLabel(cat.rawValue)
                }

                Text(verb.level.prefix(3).uppercased())
                    .font(.caption2)
                    .fontWeight(.semibold)
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(levelColor(verb.level).opacity(0.15))
                    .foregroundStyle(levelColor(verb.level))
                    .clipShape(Capsule())
            }
        }
    }

    private var orderedIrregularities: [IrregularityCategory] {
        // Order: unique > stem > spelling (most notable first)
        let order: [IrregularityCategory] = [.uniqueIrregular, .stemChange, .spelling]
        return order.filter { irregularities.contains($0) }
    }

    private func irregularityColor(_ category: IrregularityCategory) -> Color {
        switch category {
        case .uniqueIrregular: return .purple
        case .stemChange: return .orange
        case .spelling: return .teal
        case .anyIrregular: return .gray
        }
    }

    private func levelColor(_ level: String) -> Color {
        switch level {
        case "basic": return .green
        case "elementary": return .blue
        case "intermediate": return .orange
        case "advanced": return .red
        case "expert": return .purple
        default: return .gray
        }
    }
}

#Preview {
    VerbListView()
        .modelContainer(for: Verb.self, inMemory: true)
}
