import SwiftUI
import PokerCoach

/// The basics, as a short course somebody can read in ten minutes.
///
/// Deliberately not part of the first-run walk-through. That one exists to get somebody to the
/// table without being lost; this exists for the moment a few hands in when they realise nobody
/// ever told them how big a bet is supposed to be. Putting the two together would mean either
/// burying this where nobody finds it, or making the way in ten pages long.
///
/// One lesson at a time, with the answer first. Somebody looking up "how much do I raise" wants the
/// number, not three paragraphs and then the number.
struct BasicsView: View {
    @Environment(AppState.self) var app
    @Environment(\.metrics) var metrics
    @Environment(\.dismiss) var dismiss
    @State var open: String?

    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            header
            Divider().overlay(Color.white.opacity(0.07))
            ScrollView {
                LazyVStack(alignment: .leading, spacing: 12) {
                    ForEach(Basics.lessons) { lesson in
                        LessonRow(lesson: lesson,
                                  open: open == lesson.id,
                                  toggle: { toggle(lesson.id) },
                                  practise: practise(lesson))
                    }
                    Text(Copy.basicsFooter)
                        .body(Theme.coachBase(TextRole.caption.base)).foregroundStyle(Theme.dim)
                        .fixedSize(horizontal: false, vertical: true)
                        .padding(.top, 6)
                }
                .padding(metrics.gutter)
            }
        }
        .frame(minWidth: metrics.compact ? nil : Theme.size(620),
               minHeight: metrics.compact ? nil : Theme.size(520))
        .background(Theme.background)
    }

    /// Reading it is half of it. The other half is being put in the spot until the answer stops
    /// needing to be worked out — which the drills already do, so a lesson borrows the one that
    /// deals its situation rather than growing a second machine that does the same thing.
    private func practise(_ lesson: BasicLesson) -> (() -> Void)? {
        guard let id = lesson.practises,
              let leak = LeakCatalogue.all.first(where: { $0.id == id }) else { return nil }
        return {
            dismiss()
            app.offerDrill(leak)
        }
    }

    private func toggle(_ id: String) {
        withAnimation(.easeOut(duration: 0.16)) { open = open == id ? nil : id }
    }

    private var header: some View {
        HStack(alignment: .top, spacing: 12) {
            VStack(alignment: .leading, spacing: 4) {
                Text(Copy.basicsTitle)
                    .font(.system(size: metrics.titleSize, weight: .bold, design: .rounded))
                    .foregroundStyle(Theme.text)
                Text(Copy.basicsSubtitle(Basics.lessons.count))
                    .body(Theme.coachBase(TextRole.body.base)).foregroundStyle(Theme.dim)
                    .fixedSize(horizontal: false, vertical: true)
            }
            Spacer(minLength: 0)
            // Every sheet in the app needs its own way out. A sheet opened from a button and
            // closable only by a gesture somebody has to already know is a dead end on a Mac.
            GhostButton(title: "Done") { dismiss() }
        }
        .padding(metrics.gutter)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Theme.panel)
    }

    /// A question, its one-line answer, and the reasoning underneath once it is asked for.
    ///
    /// The short answer is always visible. Somebody who only wants the number gets it without
    /// opening anything, and somebody who wants to know why it is that number can have the rest.
    struct LessonRow: View {
        @Environment(\.metrics) var metrics
        let lesson: BasicLesson
        let open: Bool
        let toggle: () -> Void
        let practise: (() -> Void)?
        @State var showing: GlossaryTerm?

        var body: some View {
            VStack(alignment: .leading, spacing: 10) {
                Button(action: toggle) {
                    VStack(alignment: .leading, spacing: 5) {
                        HStack(alignment: .firstTextBaseline, spacing: 8) {
                            Text(lesson.question)
                                .heading(Theme.coachBase(TextRole.heading.base)).foregroundStyle(Theme.text)
                                .fixedSize(horizontal: false, vertical: true)
                                .frame(maxWidth: .infinity, alignment: .leading)
                            Symbol(open ? "chevron.up" : "chevron.down", size: 11)
                                .foregroundStyle(Theme.dim)
                        }
                        GlossaryText(lesson.short, size: TextRole.body.base, colour: Theme.accent, showing: $showing)
                    }
                    .contentShape(Rectangle())
                }
                .buttonStyle(.plain)

                if open {
                    VStack(alignment: .leading, spacing: 10) {
                        // The one-sentence answer is already in the header above, so it is not
                        // repeated here.
                        LessonBody(lesson: lesson, showing: $showing, showShort: false)
                        if let practise {
                            HStack {
                                GhostButton(title: Copy.practiseThis, wide: metrics.compact,
                                            action: practise)
                                if !metrics.compact { Spacer() }
                            }
                        }
                    }
                    .transition(.opacity)
                }

                DefinitionSlot(showing: $showing)
            }
            .padding(14)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(
                RoundedRectangle(cornerRadius: 11, style: .continuous).fill(Theme.panel)
            )
        }
    }
}

/// The inside of a lesson: the one-sentence answer, the reasoning, and the arithmetic where a rule
/// of thumb needs it to mean anything.
///
/// Shared between the basics screen, where somebody goes looking for it, and the coach's review,
/// where it arrives because they were told a decision was wrong and wanted to know why. Two
/// renderings of the same lesson would drift, and the review's whole job here is to say the same
/// thing the basics screen says rather than a shortened version of it.
struct LessonBody: View {
    let lesson: BasicLesson
    @Binding var showing: GlossaryTerm?
    /// False where the caller has already shown the one-line answer in a header of its own.
    var showShort = true

    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            if showShort {
                GlossaryText(lesson.short, size: TextRole.body.base, colour: Theme.accent, showing: $showing)
            }
            ForEach(Array(lesson.paragraphs.enumerated()), id: \.offset) { _, para in
                GlossaryText(para, size: TextRole.body.base, showing: $showing)
            }
            if let worked = lesson.worked {
                VStack(alignment: .leading, spacing: 6) {
                    Text(Copy.workedThrough.uppercased())
                        .caption(weight: .medium).foregroundStyle(Theme.gold.opacity(0.9))
                    GlossaryText(worked, size: TextRole.body.base, colour: Theme.text.opacity(0.9),
                                 showing: $showing)
                }
                .padding(12)
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(
                    RoundedRectangle(cornerRadius: 9, style: .continuous).fill(Theme.panelRaised)
                )
            }
        }
        .transition(.opacity)
    }
}
