import Foundation

struct ImitationAssessmentRequest {
    let mediaId: String
    let sentence: SentenceBoundary
    let recordingURL: URL
    let locale: String?
}

struct TextSubstitution: Decodable {
    let expected: String
    let actual: String
}

struct ImitationAssessmentResult: Decodable {
    let attemptId: String?
    let scoringVersion: String?
    let overallScore: Float
    let passed: Bool?
    let passScore: Float?
    let contentScore: Float?
    let completenessScore: Float?
    let fluencyScore: Float?
    let pronunciationScore: Float?
    let prosodyScore: Float?
    let durationScore: Float?
    let pauseScore: Float?
    let speechRateScore: Float?
    let referenceText: String?
    let recognizedText: String?
    let referenceDurationMs: Int64?
    let referenceSpeechDurationMs: Int64?
    let studentRecordingDurationMs: Int64?
    let studentSpeechDurationMs: Int64?
    let durationRatio: Float?
    let missingTokens: [String]
    let extraTokens: [String]
    let substitutions: [TextSubstitution]
    let feedback: String?
    let details: [String: String]

    private enum CodingKeys: String, CodingKey {
        case attemptId = "attempt_id"
        case scoringVersion = "scoring_version"
        case overallScore = "overall_score"
        case passed
        case passScore = "pass_score"
        case contentScore = "content_score"
        case completenessScore = "completeness_score"
        case fluencyScore = "fluency_score"
        case pronunciationScore = "pronunciation_score"
        case prosodyScore = "prosody_score"
        case durationScore = "duration_score"
        case pauseScore = "pause_score"
        case speechRateScore = "speech_rate_score"
        case referenceText = "reference_text"
        case recognizedText = "recognized_text"
        case referenceDurationMs = "reference_duration_ms"
        case referenceSpeechDurationMs = "reference_speech_duration_ms"
        case studentRecordingDurationMs = "student_recording_duration_ms"
        case studentSpeechDurationMs = "student_speech_duration_ms"
        case durationRatio = "duration_ratio"
        case missingTokens = "missing_tokens"
        case extraTokens = "extra_tokens"
        case substitutions
        case feedback
        case details
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        attemptId = try container.decodeIfPresent(String.self, forKey: .attemptId)
        scoringVersion = try container.decodeIfPresent(String.self, forKey: .scoringVersion)
        overallScore = try container.decodeIfPresent(Float.self, forKey: .overallScore) ?? 0
        passed = try container.decodeIfPresent(Bool.self, forKey: .passed)
        passScore = try container.decodeIfPresent(Float.self, forKey: .passScore)
        contentScore = try container.decodeIfPresent(Float.self, forKey: .contentScore)
        completenessScore = try container.decodeIfPresent(Float.self, forKey: .completenessScore)
        fluencyScore = try container.decodeIfPresent(Float.self, forKey: .fluencyScore)
        pronunciationScore = try container.decodeIfPresent(Float.self, forKey: .pronunciationScore)
        prosodyScore = try container.decodeIfPresent(Float.self, forKey: .prosodyScore)
        durationScore = try container.decodeIfPresent(Float.self, forKey: .durationScore)
        pauseScore = try container.decodeIfPresent(Float.self, forKey: .pauseScore)
        speechRateScore = try container.decodeIfPresent(Float.self, forKey: .speechRateScore)
        referenceText = try container.decodeIfPresent(String.self, forKey: .referenceText)
        recognizedText = try container.decodeIfPresent(String.self, forKey: .recognizedText)
        referenceDurationMs = try container.decodeIfPresent(Int64.self, forKey: .referenceDurationMs)
        referenceSpeechDurationMs = try container.decodeIfPresent(Int64.self, forKey: .referenceSpeechDurationMs)
        studentRecordingDurationMs = try container.decodeIfPresent(Int64.self, forKey: .studentRecordingDurationMs)
        studentSpeechDurationMs = try container.decodeIfPresent(Int64.self, forKey: .studentSpeechDurationMs)
        durationRatio = try container.decodeIfPresent(Float.self, forKey: .durationRatio)
        missingTokens = try container.decodeIfPresent([String].self, forKey: .missingTokens) ?? []
        extraTokens = try container.decodeIfPresent([String].self, forKey: .extraTokens) ?? []
        substitutions = try container.decodeIfPresent([TextSubstitution].self, forKey: .substitutions) ?? []
        feedback = try container.decodeIfPresent(String.self, forKey: .feedback)
        details = try container.decodeIfPresent([String: String].self, forKey: .details) ?? [:]
    }
}
