import Foundation

/// Mirrors `ProcessedReceipt` (src/lib/schema/receipt.ts) exactly — this is
/// the shape returned by `GET /api/receipts` and accepted by
/// `POST /api/receipts`. Keep this file and that Zod schema in sync; when the
/// web schema gains a field, add it here too rather than silently dropping it
/// on decode (optional fields decode fine as `nil` when absent, so older
/// receipts synced before a schema change won't crash the app).
struct Receipt: Codable, Identifiable, Equatable {
    let id: String
    var projectId: String?
    let imageHash: String
    let originalFileName: String
    let fileSizeBytes: Int
    var previewUrl: String?
    let createdAt: String
    let updatedAt: String
    var status: ReceiptStatus

    var merchant: Merchant
    var date: ReceiptDate
    var documentType: DocumentType
    var receiptNumber: String?
    var currency: String
    var totalAmount: AmountWithConfidence
    var netAmount: Double?
    var tipAmount: Double?
    var taxBreakdown: [TaxBreakdownItem]
    var lineItems: [LineItem]
    var suggestedCategory: ReceiptCategory
    var paymentMethod: PaymentMethod?
    var hospitality: Hospitality?
    var validation: Validation

    /// Total actually paid: `totalAmount.value + tipAmount`. Mirrors
    /// `grossWithTip()` on the backend — tip is deliberately excluded from
    /// `totalAmount` there because VAT is never charged on it.
    var grossWithTip: Double {
        ((totalAmount.value + (tipAmount ?? 0)) * 100).rounded() / 100
    }

    struct Merchant: Codable, Equatable {
        var name: String
        var address: String?
        var taxId: String?
        var confidence: Double
    }

    struct ReceiptDate: Codable, Equatable {
        var isoDate: String
        var time: String?
        var confidence: Double
    }

    struct AmountWithConfidence: Codable, Equatable {
        var value: Double
        var confidence: Double
    }

    struct TaxBreakdownItem: Codable, Equatable, Identifiable {
        var ratePercent: Double
        var taxAmount: Double
        var netAmount: Double?
        var id: String { "\(ratePercent)-\(taxAmount)" }
    }

    struct LineItem: Codable, Equatable, Identifiable {
        var id = UUID()
        var description: String
        var quantity: Double
        var price: Double
        var unitPrice: Double?
        var taxRate: Double?

        enum CodingKeys: String, CodingKey {
            case description, quantity, price, unitPrice, taxRate
        }
    }

    struct Hospitality: Codable, Equatable {
        var occasion: String?
        var participants: String?
    }

    struct Validation: Codable, Equatable {
        var isMathValid: Bool
        var isDuplicateSuspected: Bool
        var needsUserReview: Bool
        var reviewField: String
        var reviewReason: String?
        var issues: [Issue]?
        var userConfirmed: Bool?

        struct Issue: Codable, Equatable {
            var field: String
            var severity: String
            var message: String
        }
    }

    enum ReceiptStatus: String, Codable {
        case pending, processing, ready, needsReview = "needs_review", error
    }

    enum DocumentType: String, Codable, CaseIterable {
        case kassenbon = "KASSENBON"
        case rechnung = "RECHNUNG"
        case tankbeleg = "TANKBELEG"
        case bewirtungsbeleg = "BEWIRTUNGSBELEG"
        case parkticket = "PARKTICKET"
        case sonstiges = "SONSTIGES"
    }

    enum PaymentMethod: String, Codable, CaseIterable {
        case bar = "BAR"
        case ecKarte = "EC_KARTE"
        case kreditkarte = "KREDITKARTE"
        case ueberweisung = "UEBERWEISUNG"
        case paypal = "PAYPAL"
        case applePay = "APPLE_PAY"
        case googlePay = "GOOGLE_PAY"
        case sonstige = "SONSTIGE"
    }

    enum ReceiptCategory: String, Codable, CaseIterable {
        case bewirtung = "Bewirtung"
        case reisekosten = "Reisekosten & Hotel"
        case tanken = "Tanken & KFZ"
        case buerobedarf = "Bürobedarf & IT"
        case verpflegungsmehraufwand = "Verpflegungsmehraufwand"
        case material = "Material & Einkauf"
        case sonstiges = "Sonstiges"
    }
}

/// `GET /api/receipts` response envelope.
struct ReceiptListResponse: Decodable {
    let success: Bool
    let receipts: [Receipt]
    let count: Int
}

/// `POST /api/receipts` response envelope (batch upsert).
struct ReceiptSyncResponse: Decodable {
    let success: Bool
    let syncedCount: Int?
    let message: String?
}
