import Foundation
import SwiftData

/// A long-form bilingual book bundled with the app. Chapter content lives in
/// `BookChapter` rows; this model carries the per-book metadata.
@Model
public final class Book {
    @Attribute(.unique) public var id: String = ""    // matches `slug`
    public var slug: String = ""
    public var title: String = ""
    public var author: String = ""
    public var language: String = ""
    public var chapterCount: Int = 0
    public var accentColorHex: String = ""
    /// JSON-encoded `[String: WordGloss]` — the book reader's primary word
    /// lookup, keyed by the cleaned (lowercased, punctuation-trimmed) word.
    /// Pre-computed at import time so taps resolve instantly and in context.
    public var glossaryJSON: Data = Data()

    public init(
        slug: String,
        title: String,
        author: String,
        language: String,
        chapterCount: Int,
        accentColorHex: String,
        glossaryJSON: Data = Data()
    ) {
        self.id = slug
        self.slug = slug
        self.title = title
        self.author = author
        self.language = language
        self.chapterCount = chapterCount
        self.accentColorHex = accentColorHex
        self.glossaryJSON = glossaryJSON
    }

    /// The decoded per-book glossary. Decode once and cache at the call site —
    /// this re-decodes on every call.
    public func glossary() -> [String: WordGloss] {
        (try? JSONDecoder().decode([String: WordGloss].self, from: glossaryJSON)) ?? [:]
    }
}

/// One glossary entry: a word's dictionary base form, English meaning, and
/// part of speech, translated in the book's context at import time. `gender`
/// is populated by the glossary pipeline for nouns ("m"/"f"/"m/f"); nil for
/// non-nouns or when the pipeline hasn't been re-run yet.
public struct WordGloss: Codable, Hashable, Sendable {
    public let baseForm: String
    public let english: String
    public let partOfSpeech: String
    public let gender: String?

    public init(
        baseForm: String,
        english: String,
        partOfSpeech: String,
        gender: String? = nil
    ) {
        self.baseForm = baseForm
        self.english = english
        self.partOfSpeech = partOfSpeech
        self.gender = gender
    }
}
