import Foundation
import SwiftData

/// Per-prompt grading state recorded after the user submits an exercise.
public enum TextbookGrade: Int, Codable, Sendable {
    case wrong = 0
    case close = 1
    case correct = 2
}

/// User's attempt for one exercise. Stored in the cloud container so progress
/// syncs across devices.
@Model
public final class TextbookExerciseAttempt {
    /// Deterministic id: "<courseName>|<exerciseId>". CloudKit-synced models can't
    /// use @Attribute(.unique); code that writes attempts must fetch-or-create.
    public var id: String = ""
    public var courseName: String = ""
    public var chapterNumber: Int = 0
    public var exerciseId: String = ""

    /// JSON-encoded per-prompt state array.
    /// Each entry: { "number": Int, "userText": String, "grade": Int }
    public var stateJSON: Data = Data()

    public var lastAttemptAt: Date = Date()
    public var correctCount: Int = 0
    public var closeCount: Int = 0
    public var wrongCount: Int = 0
    public var totalCount: Int = 0

    public init(
        id: String,
        courseName: String,
        chapterNumber: Int,
        exerciseId: String,
        stateJSON: Data = Data(),
        lastAttemptAt: Date = Date(),
        correctCount: Int = 0,
        closeCount: Int = 0,
        wrongCount: Int = 0,
        totalCount: Int = 0
    ) {
        self.id = id
        self.courseName = courseName
        self.chapterNumber = chapterNumber
        self.exerciseId = exerciseId
        self.stateJSON = stateJSON
        self.lastAttemptAt = lastAttemptAt
        self.correctCount = correctCount
        self.closeCount = closeCount
        self.wrongCount = wrongCount
        self.totalCount = totalCount
    }

    public func promptStates() -> [TextbookPromptState] {
        (try? JSONDecoder().decode([TextbookPromptState].self, from: stateJSON)) ?? []
    }

    public func setPromptStates(_ states: [TextbookPromptState]) {
        stateJSON = (try? JSONEncoder().encode(states)) ?? Data()
        correctCount = states.filter { $0.grade == .correct }.count
        closeCount = states.filter { $0.grade == .close }.count
        wrongCount = states.filter { $0.grade == .wrong }.count
        totalCount = states.count
    }

    public static func attemptId(courseName: String, exerciseId: String) -> String {
        "\(courseName)|\(exerciseId)"
    }
}

public struct TextbookPromptState: Codable, Sendable {
    public var number: Int
    public var userText: String
    public var grade: TextbookGrade

    public init(number: Int, userText: String, grade: TextbookGrade) {
        self.number = number
        self.userText = userText
        self.grade = grade
    }
}
