import Foundation

enum RecognitionSource: String, Codable, CaseIterable, Identifiable {
    case cloud
    case onDeviceOffline
    case onDeviceFallback
    case manual

    var id: String { rawValue }

    var title: String {
        switch self {
        case .cloud:
            return "Cloud OCR"
        case .onDeviceOffline:
            return "On-Device (Offline)"
        case .onDeviceFallback:
            return "On-Device Fallback"
        case .manual:
            return "Manual Entry"
        }
    }

    var detail: String {
        switch self {
        case .cloud:
            return "Prepared client boundary for future Convex/Mistral OCR."
        case .onDeviceOffline:
            return "Offline erkannt — Ergebnis kann weniger genau sein."
        case .onDeviceFallback:
            return "Cloud path unavailable — used the on-device Vision fallback."
        case .manual:
            return "No image is persisted after confirmation."
        }
    }
}

enum ConfidenceLevel: String, Codable, CaseIterable, Comparable {
    case low
    case medium
    case high

    private var score: Int {
        switch self {
        case .low: return 0
        case .medium: return 1
        case .high: return 2
        }
    }

    static func < (lhs: ConfidenceLevel, rhs: ConfidenceLevel) -> Bool {
        lhs.score < rhs.score
    }

    var title: String { rawValue.capitalized }

    var helperText: String {
        switch self {
        case .high:
            return "Looks solid — a quick confirmation should be enough."
        case .medium:
            return "Please review the extracted fields before confirming."
        case .low:
            return "Low confidence — manual corrections are recommended."
        }
    }
}

enum CardRarity: String, CaseIterable, Identifiable {
    case unknown = "Unknown"
    case common = "Common"
    case uncommon = "Uncommon"
    case rare = "Rare"
    case holoRare = "Holo Rare"
    case ultraRare = "Ultra Rare"
    case illustrationRare = "Illustration Rare"
    case specialArtRare = "Special Art Rare"
    case hyperRare = "Hyper Rare"
    case secretRare = "Secret Rare"

    var id: String { rawValue }
}

struct CardRecognitionDraft: Equatable {
    var cardName: String
    var cardNumber: String
    var setIdentifier: String
    var rarity: String
    var source: RecognitionSource
    var confidence: ConfidenceLevel
    var notes: [String]
    var rawText: String

    var hasDetectedContent: Bool {
        !cardName.isBlank || !cardNumber.isBlank || !setIdentifier.isBlank || !rarity.isBlank
    }

    var combinedNumberAndSet: String {
        let components = [cardNumber.trimmedNilIfEmpty, setIdentifier.trimmedNilIfEmpty].compactMap { $0 }
        return components.joined(separator: " · ")
    }

    static func manualPrefill(rawText: String = "") -> CardRecognitionDraft {
        CardRecognitionDraft(
            cardName: "",
            cardNumber: "",
            setIdentifier: "",
            rarity: CardRarity.unknown.rawValue,
            source: .manual,
            confidence: .low,
            notes: ["Manual entry is always available when OCR misses fields."],
            rawText: rawText
        )
    }
}

struct RecognitionSession: Identifiable, Equatable {
    let id: UUID
    var draft: CardRecognitionDraft
    var thumbnailJPEGData: Data?

    init(id: UUID = UUID(), draft: CardRecognitionDraft, thumbnailJPEGData: Data? = nil) {
        self.id = id
        self.draft = draft
        self.thumbnailJPEGData = thumbnailJPEGData
    }
}

private extension String {
    var isBlank: Bool {
        trimmedNilIfEmpty == nil
    }

    var trimmedNilIfEmpty: String? {
        let trimmed = trimmingCharacters(in: .whitespacesAndNewlines)
        return trimmed.isEmpty ? nil : trimmed
    }
}
