import SwiftUI
import SwiftData
import SharedModels

struct GuideView: View {
    @Environment(\.modelContext) private var modelContext

    @State private var guides: [TenseGuide] = []
    @State private var selectedGuide: TenseGuide?
    @State private var selectedNote: GrammarNote?
    @State private var selectedTab: GuideTab = .tenses

    enum GuideTab: String, CaseIterable {
        case tenses = "Tenses"
        case grammar = "Grammar"
    }

    private var guideMap: [String: TenseGuide] {
        Dictionary(uniqueKeysWithValues: guides.map { ($0.tenseId, $0) })
    }

    var body: some View {
        NavigationSplitView {
            VStack(spacing: 0) {
                Picker("Guide", selection: $selectedTab) {
                    ForEach(GuideTab.allCases, id: \.self) { tab in
                        Text(tab.rawValue).tag(tab)
                    }
                }
                .pickerStyle(.segmented)
                .padding(.horizontal)
                .padding(.vertical, 8)

                switch selectedTab {
                case .tenses:
                    tensesList
                case .grammar:
                    grammarList
                }
            }
            .navigationTitle("Guide")
            .task { loadGuides() }
            .onAppear(perform: loadGuides)
            .onChange(of: selectedTab) { _, newTab in
                // Only clear the *other* tab's selection so programmatic
                // cross-link jumps (chip taps in the detail pane) can keep
                // their newly-set selection on the destination tab.
                switch newTab {
                case .tenses: selectedNote = nil
                case .grammar: selectedGuide = nil
                }
            }
        } detail: {
            if let guide = selectedGuide {
                GuideDetailView(guide: guide, onJumpToNote: jumpToNote)
            } else if let note = selectedNote {
                GrammarNoteDetailView(note: note, onJumpToTense: jumpToTense)
            } else {
                ContentUnavailableView("Select a Topic", systemImage: "book", description: Text("Choose a tense or grammar topic to learn more."))
            }
        }
    }

    private var tensesList: some View {
        List(selection: $selectedGuide) {
            ForEach(TenseInfo.byMood(), id: \.0) { mood, tenses in
                Section(mood) {
                    ForEach(tenses) { tense in
                        if let guide = guideMap[tense.id] {
                            NavigationLink(value: guide) {
                                TenseRowView(tense: tense)
                            }
                        } else {
                            TenseRowView(tense: tense)
                                .foregroundStyle(.tertiary)
                        }
                    }
                }
            }
        }
    }

    private var grammarList: some View {
        GrammarNotesListView(selectedNote: $selectedNote)
    }

    private func jumpToNote(_ note: GrammarNote) {
        selectedTab = .grammar
        selectedNote = note
    }

    private func jumpToTense(_ guide: TenseGuide) {
        selectedTab = .tenses
        selectedGuide = guide
    }

    private func loadGuides() {
        // Hit the shared local container directly, bypassing @Environment.
        guard let container = SharedStore.localContainer else {
            print("[GuideView] ⚠️ SharedStore.localContainer is nil")
            return
        }
        let context = ModelContext(container)
        guides = ReferenceStore(context: context).fetchGuides()
        print("[GuideView] loaded \(guides.count) tense guides (container: \(ObjectIdentifier(container)))")
        if selectedGuide == nil {
            selectedGuide = guides.first
        }
    }
}

// MARK: - Tense Row

private struct TenseRowView: View {
    let tense: TenseInfo

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

            Spacer()

            if tense.isCore {
                Text("Essential")
                    .font(.caption2.weight(.semibold))
                    .foregroundStyle(.orange)
                    .padding(.horizontal, 8)
                    .padding(.vertical, 3)
                    .background(.orange.opacity(0.12), in: Capsule())
            }
        }
    }
}

// MARK: - Guide Detail

struct GuideDetailView: View {
    let guide: TenseGuide
    var onJumpToNote: ((GrammarNote) -> Void)? = nil
    @Environment(YouTubeVideoStore.self) private var videoStore

    private var relatedNotes: [GrammarNote] {
        GuideCrossLinks.noteIds(forTense: guide.tenseId).compactMap { id in
            GrammarNote.allNotesIncludingGenerated.first { $0.id == id }
        }
    }

    private var tenseInfo: TenseInfo? {
        TenseInfo.find(guide.tenseId)
    }

    private var curatedVideo: YouTubeVideoStore.VideoEntry? {
        videoStore.video(forTenseId: guide.tenseId)
    }

    private var endingTable: TenseEndingTable? {
        TenseEndingTable.find(guide.tenseId)
    }

    private var parsedContent: GuideContent {
        GuideContent.parse(guide.body)
    }

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 24) {
                // Header
                headerSection

                // Related grammar notes — cross-links into the Grammar tab
                if !relatedNotes.isEmpty {
                    relatedNotesSection
                }

                // Video section (Issue #21)
                videoSection

                // Conjugation ending table
                if let table = endingTable {
                    conjugationTableSection(table)
                }

                // Formula
                if let table = endingTable {
                    formulaSection(table)
                }

                Divider()

                // Description
                if !parsedContent.description.isEmpty {
                    descriptionSection
                }

                // Consolidated usages card
                if !parsedContent.usages.isEmpty {
                    usagesSummarySection
                }

                // Examples section
                if parsedContent.usages.contains(where: { !$0.examples.isEmpty }) {
                    examplesSection
                }
            }
            .padding()
            .adaptiveContainer(maxWidth: 800)
        }
        .navigationTitle(tenseInfo?.english ?? guide.title)
        .navigationBarTitleDisplayMode(.inline)
    }

    // MARK: - Related grammar notes

    private var relatedNotesSection: some View {
        VStack(alignment: .leading, spacing: 8) {
            Label("Related grammar", systemImage: "book")
                .font(.caption.weight(.semibold))
                .foregroundStyle(.secondary)
                .textCase(.uppercase)

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 8) {
                    ForEach(relatedNotes, id: \.id) { note in
                        Button {
                            onJumpToNote?(note)
                        } label: {
                            Text(note.title)
                                .font(.caption.weight(.semibold))
                                .padding(.horizontal, 12)
                                .padding(.vertical, 7)
                                .background(.indigo.opacity(0.12), in: Capsule())
                                .foregroundStyle(.indigo)
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
        }
    }

    // MARK: - Video (Issue #21)

    @ViewBuilder
    private var videoSection: some View {
        if let video = curatedVideo {
            VideoActionsButtonRow(video: video)
        } else {
            Label("No video yet", systemImage: "play.slash")
                .font(.caption)
                .foregroundStyle(.secondary)
                .padding(.vertical, 6)
                .padding(.horizontal, 10)
                .background(.fill.quinary, in: Capsule())
        }
    }

    // MARK: - Header

    private var headerSection: some View {
        VStack(alignment: .leading, spacing: 8) {
            if let info = tenseInfo {
                Text(info.spanish)
                    .font(.title2.weight(.bold))
                Text(info.english)
                    .font(.title3)
                    .foregroundStyle(.secondary)
                HStack {
                    Label(info.mood, systemImage: "tag")
                        .font(.caption.weight(.medium))
                        .padding(.horizontal, 10)
                        .padding(.vertical, 4)
                        .background(.fill.tertiary, in: Capsule())
                }
            }
        }
    }

    // MARK: - Conjugation Table

    private func conjugationTableSection(_ table: TenseEndingTable) -> some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Conjugation Endings")
                .font(.headline)

            if table.isCompound, let aux = table.auxiliaryForms {
                // Compound tense: show auxiliary + participle
                compoundTenseTable(table, auxiliary: aux)
            } else {
                // Simple tense: show endings grid
                simpleEndingsGrid(table)
            }
        }
        .padding()
        .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 16))
    }

    private func simpleEndingsGrid(_ table: TenseEndingTable) -> some View {
        VStack(spacing: 0) {
            // Header row
            HStack(spacing: 0) {
                Text("")
                    .frame(width: 80, alignment: .leading)
                Text("~ar")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.orange)
                    .frame(maxWidth: .infinity)
                Text("~er")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.green)
                    .frame(maxWidth: .infinity)
                Text("~ir")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.blue)
                    .frame(maxWidth: .infinity)
            }
            .padding(.vertical, 6)
            .background(.fill.quaternary)

            // Example verb names
            HStack(spacing: 0) {
                Text("")
                    .frame(width: 80, alignment: .leading)
                Text(table.arExample.verb)
                    .font(.caption2.italic())
                    .foregroundStyle(.secondary)
                    .frame(maxWidth: .infinity)
                Text(table.erExample.verb)
                    .font(.caption2.italic())
                    .foregroundStyle(.secondary)
                    .frame(maxWidth: .infinity)
                Text(table.irExample.verb)
                    .font(.caption2.italic())
                    .foregroundStyle(.secondary)
                    .frame(maxWidth: .infinity)
            }
            .padding(.vertical, 4)

            Divider()

            // Person rows
            ForEach(0..<6, id: \.self) { i in
                HStack(spacing: 0) {
                    Text(TenseEndingTable.persons[i])
                        .font(.subheadline.weight(.medium))
                        .frame(width: 80, alignment: .leading)

                    endingCell(table.arExample.stem, ending: table.arEndings[i], color: .orange)
                        .frame(maxWidth: .infinity)
                    endingCell(table.erExample.stem, ending: table.erEndings[i], color: .green)
                        .frame(maxWidth: .infinity)
                    endingCell(table.irExample.stem, ending: table.irEndings[i], color: .blue)
                        .frame(maxWidth: .infinity)
                }
                .padding(.vertical, 5)

                if i < 5 {
                    Divider().opacity(0.5)
                }
            }
        }
    }

    private func endingCell(_ stem: String, ending: String, color: Color) -> some View {
        Group {
            if ending == "—" {
                Text("—")
                    .font(.subheadline)
                    .foregroundStyle(.tertiary)
            } else {
                Text(
                    "\(Text(stem).foregroundStyle(.primary))\(Text(ending).foregroundStyle(color).fontWeight(.semibold))"
                )
                .font(.subheadline)
            }
        }
    }

    private func compoundTenseTable(_ table: TenseEndingTable, auxiliary: [String]) -> some View {
        VStack(spacing: 0) {
            // Header
            HStack(spacing: 0) {
                Text("")
                    .frame(width: 80, alignment: .leading)
                Text("Auxiliary")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.purple)
                    .frame(maxWidth: .infinity)
                Text("~ar")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.orange)
                    .frame(maxWidth: .infinity)
                Text("~er/~ir")
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.cyan)
                    .frame(maxWidth: .infinity)
            }
            .padding(.vertical, 6)
            .background(.fill.quaternary)

            Divider()

            ForEach(0..<6, id: \.self) { i in
                HStack(spacing: 0) {
                    Text(TenseEndingTable.persons[i])
                        .font(.subheadline.weight(.medium))
                        .frame(width: 80, alignment: .leading)

                    Text(auxiliary[i])
                        .font(.subheadline)
                        .foregroundStyle(.purple)
                        .frame(maxWidth: .infinity)

                    Text(table.arExample.stem + "ado")
                        .font(.subheadline)
                        .foregroundStyle(.orange)
                        .frame(maxWidth: .infinity)

                    Text(table.erExample.stem + "ido")
                        .font(.subheadline)
                        .foregroundStyle(.cyan)
                        .frame(maxWidth: .infinity)
                }
                .padding(.vertical, 5)

                if i < 5 {
                    Divider().opacity(0.5)
                }
            }
        }
    }

    // MARK: - Formula

    private func formulaSection(_ table: TenseEndingTable) -> some View {
        VStack(alignment: .leading, spacing: 6) {
            Label("How to form", systemImage: "function")
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(.secondary)

            Text(table.formula)
                .font(.body.weight(.medium))

            Text(table.stemRule)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 12))
    }

    // MARK: - Description

    private var descriptionSection: some View {
        Text(parsedContent.description)
            .font(.body)
            .lineSpacing(4)
    }

    // MARK: - Usages Summary (consolidated)

    private var usagesSummarySection: some View {
        VStack(alignment: .leading, spacing: 10) {
            Label("When to use", systemImage: "lightbulb")
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(.secondary)

            ForEach(parsedContent.usages) { usage in
                HStack(alignment: .top, spacing: 10) {
                    Text("\(usage.number).")
                        .font(.subheadline.weight(.bold))
                        .foregroundStyle(.blue)
                        .frame(width: 20, alignment: .trailing)

                    Text(usage.title)
                        .font(.subheadline)
                }
            }
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(.fill.quinary, in: RoundedRectangle(cornerRadius: 12))
    }

    // MARK: - Examples Section

    private var examplesSection: some View {
        VStack(alignment: .leading, spacing: 16) {
            Label("Examples", systemImage: "text.quote")
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(.secondary)

            ForEach(parsedContent.usages) { usage in
                ForEach(usage.examples) { example in
                    VStack(alignment: .leading, spacing: 4) {
                        Text(example.spanish)
                            .font(.body.weight(.medium))
                            .italic()

                        Text(example.english)
                            .font(.callout)
                            .foregroundStyle(.secondary)
                    }
                }
            }
        }
    }
}

// MARK: - Content Parsing

struct GuideContent {
    let description: String
    let usages: [GuideUsage]

    static func parse(_ body: String) -> GuideContent {
        let lines = body.components(separatedBy: "\n")
        var description = ""
        var usages: [GuideUsage] = []
        var currentUsageTitle = ""
        var currentUsageNumber = 0
        var currentExamples: [GuideExample] = []
        var inUsages = false
        var spanishLine: String?

        func flushUsage() {
            // Only emit a usage if it has at least one example. This suppresses
            // the implicit "Usage 1" seeded when we enter an unnumbered
            // *Usages* block but the body actually has numbered headers below.
            if currentUsageNumber > 0 && !currentExamples.isEmpty {
                usages.append(GuideUsage(
                    number: currentUsageNumber,
                    title: currentUsageTitle,
                    examples: currentExamples
                ))
            }
            currentExamples = []
        }

        for line in lines {
            let trimmed = line.trimmingCharacters(in: .whitespaces)

            // Skip empty lines
            if trimmed.isEmpty {
                if let sp = spanishLine {
                    // Spanish line with no English translation
                    currentExamples.append(GuideExample(spanish: sp, english: ""))
                    spanishLine = nil
                }
                continue
            }

            // Detect usage headers like "*1 Current actions*" or "**1 Current actions**"
            let usagePattern = /^\*{1,2}(\d+)\s+(.+?)\*{0,2}$/
            if let match = trimmed.firstMatch(of: usagePattern) {
                flushUsage()
                inUsages = true
                currentUsageNumber = Int(match.1) ?? 0
                currentUsageTitle = String(match.2)
                    .replacingOccurrences(of: "**", with: "")
                    .replacingOccurrences(of: "*", with: "")
                continue
            }

            // Detect usage headers without numbers
            let usageTitlePattern = /^\*{1,2}(.+?)\*{0,2}$/
            if !inUsages, let match = trimmed.firstMatch(of: usageTitlePattern) {
                let title = String(match.1).replacingOccurrences(of: "*", with: "")
                if title.lowercased().contains("usage") {
                    inUsages = true
                    // Seed an implicit Usage 1 so content that follows without a
                    // numbered "*1 Title*" header still gets captured. Any numbered
                    // header below will replace this via flushUsage().
                    currentUsageNumber = 1
                    currentUsageTitle = "Usage"
                    continue
                }
            }

            if !inUsages {
                // Before usages section, accumulate description
                let cleanLine = trimmed
                    .replacingOccurrences(of: "**", with: "")
                    .replacingOccurrences(of: "*", with: "")
                if !description.isEmpty { description += " " }
                description += cleanLine
                continue
            }

            // In usages: detect example pairs (Spanish line followed by English line)
            if let sp = spanishLine {
                // This line is the English translation of the previous Spanish line
                currentExamples.append(GuideExample(spanish: sp, english: trimmed))
                spanishLine = nil
            } else {
                // Check if this looks like a Spanish sentence
                let startsWithDash = trimmed.hasPrefix("-") || trimmed.hasPrefix("–")
                let cleanLine = startsWithDash ? String(trimmed.dropFirst()).trimmingCharacters(in: .whitespaces) : trimmed

                // Heuristic: Spanish sentences contain accented chars or start with ¿/¡
                let isSpanish = cleanLine.contains("á") || cleanLine.contains("é") || cleanLine.contains("í") ||
                                cleanLine.contains("ó") || cleanLine.contains("ú") || cleanLine.contains("ñ") ||
                                cleanLine.hasPrefix("¿") || cleanLine.hasPrefix("¡") ||
                                cleanLine.first?.isUppercase == true

                if isSpanish && !cleanLine.lowercased().hasPrefix("i ") && !cleanLine.lowercased().hasPrefix("the ") &&
                   !cleanLine.lowercased().hasPrefix("all ") && !cleanLine.lowercased().hasPrefix("when ") &&
                   !cleanLine.lowercased().hasPrefix("what ") {
                    spanishLine = cleanLine
                } else {
                    // English or context line
                    if currentUsageNumber == 0 && usages.isEmpty {
                        // Still description
                        if !description.isEmpty { description += " " }
                        description += cleanLine
                    }
                }
            }
        }

        flushUsage()

        // If no usages were found, create one from the whole body
        if usages.isEmpty && !body.isEmpty {
            usages.append(GuideUsage(number: 1, title: "Usage", examples: []))
        }

        return GuideContent(description: description, usages: usages)
    }
}

struct GuideUsage: Identifiable {
    let number: Int
    let title: String
    let examples: [GuideExample]
    var id: Int { number }
}

struct GuideExample: Identifiable {
    let spanish: String
    let english: String
    var id: String { spanish }
}

#Preview {
    GuideView()
        .modelContainer(for: TenseGuide.self, inMemory: true)
        .environment(YouTubeVideoStore())
}
