import Foundation
import SwiftData

/// One chapter of the textbook. Ordered content blocks are stored as JSON in `bodyJSON`
/// (encoded [TextbookBlock]) since SwiftData @Model doesn't support heterogeneous arrays.
@Model
public final class TextbookChapter {
    @Attribute(.unique) public var id: String = ""
    public var number: Int = 0
    public var title: String = ""
    public var part: Int = 0                    // 0 = no part assignment
    public var courseName: String = ""
    public var bodyJSON: Data = Data()
    public var exerciseCount: Int = 0
    public var vocabTableCount: Int = 0

    public init(
        id: String,
        number: Int,
        title: String,
        part: Int,
        courseName: String,
        bodyJSON: Data,
        exerciseCount: Int,
        vocabTableCount: Int
    ) {
        self.id = id
        self.number = number
        self.title = title
        self.part = part
        self.courseName = courseName
        self.bodyJSON = bodyJSON
        self.exerciseCount = exerciseCount
        self.vocabTableCount = vocabTableCount
    }

    public func blocks() -> [TextbookBlock] {
        (try? JSONDecoder().decode([TextbookBlock].self, from: bodyJSON)) ?? []
    }
}

/// One content block within a chapter. Polymorphic via `kind`.
public struct TextbookBlock: Codable, Identifiable, Sendable {
    public enum Kind: String, Codable, Sendable {
        case heading
        case paragraph
        case keyVocabHeader = "key_vocab_header"
        case vocabTable = "vocab_table"
        case exercise
    }

    public var id: String { "\(kind.rawValue):\(index)" }
    public var index: Int
    public var kind: Kind

    // heading
    public var level: Int?
    // heading / paragraph
    public var text: String?

    // vocab_table
    public var sourceImage: String?
    public var ocrLines: [String]?
    public var ocrConfidence: Double?
    public var cards: [TextbookVocabPair]?

    // exercise
    public var exerciseId: String?
    public var instruction: String?
    public var extra: [String]?
    public var prompts: [String]?
    public var answerItems: [TextbookAnswerItem]?
    public var freeform: Bool?
}

public struct TextbookVocabPair: Codable, Sendable {
    public var front: String
    public var back: String
}

public struct TextbookAnswerItem: Codable, Sendable {
    public var label: String?      // A/B/C subpart label or nil
    public var number: Int
    public var answer: String
    public var alternates: [String]
}
