import SwiftUI
import SharedModels
import SwiftData

struct TextbookChapterView: View {
    let chapter: TextbookChapter

    @State private var expandedVocab: Set<Int> = []

    private var blocks: [TextbookBlock] { chapter.blocks() }

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                headerView
                Divider()
                ForEach(blocks) { block in
                    blockView(block)
                }
            }
            .padding(.horizontal)
            .padding(.vertical, 12)
        }
        .navigationTitle(chapter.title)
        .navigationBarTitleDisplayMode(.inline)
    }

    private var headerView: some View {
        VStack(alignment: .leading, spacing: 4) {
            if chapter.part > 0 {
                Text("Part \(chapter.part)")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }
            Text("Chapter \(chapter.number)")
                .font(.subheadline)
                .foregroundStyle(.secondary)
            Text(chapter.title)
                .font(.largeTitle.bold())
        }
    }

    @ViewBuilder
    private func blockView(_ block: TextbookBlock) -> some View {
        switch block.kind {
        case .heading:
            headingView(block)
        case .paragraph:
            paragraphView(block)
        case .keyVocabHeader:
            HStack(spacing: 6) {
                Image(systemName: "star.fill").foregroundStyle(.orange)
                Text("Key Vocabulary")
                    .font(.headline)
                    .foregroundStyle(.orange)
            }
            .padding(.top, 8)
        case .vocabTable:
            vocabTableView(block)
        case .exercise:
            exerciseLinkView(block)
        }
    }

    private func headingView(_ block: TextbookBlock) -> some View {
        let level = block.level ?? 3
        let font: Font
        switch level {
        case 2: font = .title.bold()
        case 3: font = .title2.bold()
        case 4: font = .title3.weight(.semibold)
        default: font = .headline
        }
        return Text(stripInlineEmphasis(block.text ?? ""))
            .font(font)
            .padding(.top, 10)
    }

    private func paragraphView(_ block: TextbookBlock) -> some View {
        Text(attributedFromMarkdownish(block.text ?? ""))
            .font(.body)
            .fixedSize(horizontal: false, vertical: true)
    }

    private func vocabTableView(_ block: TextbookBlock) -> some View {
        let expanded = expandedVocab.contains(block.index)
        let cards = block.cards ?? []
        let lines = block.ocrLines ?? []
        let itemCount = cards.isEmpty ? lines.count : cards.count
        return VStack(alignment: .leading, spacing: 4) {
            Button {
                if expanded { expandedVocab.remove(block.index) } else { expandedVocab.insert(block.index) }
            } label: {
                HStack {
                    Image(systemName: expanded ? "chevron.down" : "chevron.right")
                        .font(.caption)
                    Text("Vocabulary (\(itemCount) items)")
                        .font(.subheadline.weight(.medium))
                        .foregroundStyle(.primary)
                    Spacer()
                }
                .contentShape(Rectangle())
            }
            .buttonStyle(.plain)

            if expanded {
                if cards.isEmpty {
                    // Fallback: no paired cards available — show raw OCR lines.
                    VStack(alignment: .leading, spacing: 2) {
                        ForEach(Array(lines.enumerated()), id: \.offset) { _, line in
                            Text(line)
                                .font(.callout.monospaced())
                                .foregroundStyle(.secondary)
                        }
                    }
                    .padding(.leading, 14)
                } else {
                    vocabGrid(cards: cards)
                        .padding(.leading, 14)
                }
            }
        }
        .padding(10)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color.orange.opacity(0.08), in: RoundedRectangle(cornerRadius: 10))
    }

    @ViewBuilder
    private func vocabGrid(cards: [TextbookVocabPair]) -> some View {
        Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 6) {
            ForEach(Array(cards.enumerated()), id: \.offset) { _, card in
                GridRow {
                    Text(card.front)
                        .font(.callout)
                        .foregroundStyle(.primary)
                    Text(card.back)
                        .font(.callout)
                        .foregroundStyle(.secondary)
                }
            }
        }
    }

    private func exerciseLinkView(_ block: TextbookBlock) -> some View {
        NavigationLink(value: TextbookExerciseDestination(
            chapterId: chapter.id,
            chapterNumber: chapter.number,
            blockIndex: block.index
        )) {
            HStack(spacing: 10) {
                Image(systemName: "pencil.and.list.clipboard")
                    .foregroundStyle(.orange)
                    .font(.title3)
                VStack(alignment: .leading, spacing: 2) {
                    Text("Exercise \(block.exerciseId ?? "")")
                        .font(.headline)
                    if let inst = block.instruction, !inst.isEmpty {
                        Text(stripInlineEmphasis(inst))
                            .font(.caption)
                            .foregroundStyle(.secondary)
                            .lineLimit(2)
                    }
                }
                Spacer()
                Image(systemName: "chevron.right")
                    .foregroundStyle(.secondary)
                    .font(.caption)
            }
            .padding(12)
            .background(Color.orange.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
        }
        .buttonStyle(.plain)
    }

    // Strip our ad-hoc ** / * markers from parsed text
    private func stripInlineEmphasis(_ s: String) -> String {
        s.replacingOccurrences(of: "**", with: "")
            .replacingOccurrences(of: "*", with: "")
    }

    private func attributedFromMarkdownish(_ s: String) -> AttributedString {
        // Parser emits `**bold**` and `*italic*`. Try to render via AttributedString markdown.
        if let parsed = try? AttributedString(markdown: s, options: .init(allowsExtendedAttributes: true)) {
            return parsed
        }
        return AttributedString(stripInlineEmphasis(s))
    }
}

struct TextbookExerciseDestination: Hashable {
    let chapterId: String
    let chapterNumber: Int
    let blockIndex: Int
}

#Preview {
    NavigationStack {
        TextbookChapterView(chapter: TextbookChapter(
            id: "ch1",
            number: 1,
            title: "Sample",
            part: 1,
            courseName: "Preview",
            bodyJSON: Data(),
            exerciseCount: 0,
            vocabTableCount: 0
        ))
    }
}
