import Foundation
import SharedModels
import SwiftData

struct ReferenceStore {
    let context: ModelContext

    func fetchGuides() -> [TenseGuide] {
        let descriptor = FetchDescriptor<TenseGuide>(sortBy: [SortDescriptor(\TenseGuide.tenseId)])
        return (try? context.fetch(descriptor)) ?? []
    }

    func fetchGuideMap() -> [String: TenseGuide] {
        Dictionary(uniqueKeysWithValues: fetchGuides().map { ($0.tenseId, $0) })
    }

    func fetchVerbs() -> [Verb] {
        let descriptor = FetchDescriptor<Verb>(sortBy: [SortDescriptor(\Verb.infinitive)])
        return (try? context.fetch(descriptor)) ?? []
    }

    func fetchVerbs(selectedLevel: String) -> [Verb] {
        fetchVerbs().filter { VerbLevelGroup.matches($0.level, selectedLevel: selectedLevel) }
    }

    func allowedVerbIDs(selectedLevel: String) -> Set<Int> {
        Set(fetchVerbs(selectedLevel: selectedLevel).map(\.id))
    }

    func fetchVerb(id: Int) -> Verb? {
        let descriptor = FetchDescriptor<Verb>(predicate: #Predicate<Verb> { $0.id == id })
        return (try? context.fetch(descriptor))?.first
    }

    func fetchVerbForms(verbId: Int) -> [VerbForm] {
        let descriptor = FetchDescriptor<VerbForm>(
            predicate: #Predicate<VerbForm> { $0.verbId == verbId },
            sortBy: [SortDescriptor(\VerbForm.tenseId), SortDescriptor(\VerbForm.personIndex)]
        )
        return (try? context.fetch(descriptor)) ?? []
    }

    func fetchForms(verbId: Int, tenseId: String) -> [VerbForm] {
        let descriptor = FetchDescriptor<VerbForm>(
            predicate: #Predicate<VerbForm> { form in
                form.verbId == verbId && form.tenseId == tenseId
            },
            sortBy: [SortDescriptor(\VerbForm.personIndex)]
        )
        return (try? context.fetch(descriptor)) ?? []
    }

    func fetchForm(verbId: Int, tenseId: String, personIndex: Int) -> VerbForm? {
        let descriptor = FetchDescriptor<VerbForm>(
            predicate: #Predicate<VerbForm> { form in
                form.verbId == verbId &&
                form.tenseId == tenseId &&
                form.personIndex == personIndex
            }
        )
        return (try? context.fetch(descriptor))?.first
    }

    func fetchSpans(verbId: Int, tenseId: String, personIndex: Int) -> [IrregularSpan] {
        let descriptor = FetchDescriptor<IrregularSpan>(
            predicate: #Predicate<IrregularSpan> { span in
                span.verbId == verbId &&
                span.tenseId == tenseId &&
                span.personIndex == personIndex
            },
            sortBy: [SortDescriptor(\IrregularSpan.start)]
        )
        return (try? context.fetch(descriptor)) ?? []
    }
}
