import Foundation

/// A decoded `{ "error": "some_code" }` body from the backend. Every route
/// under `src/app/api/**` returns one of these machine-readable codes on
/// failure (see `src/lib/auth/errors.ts` for the auth ones) — the app is
/// responsible for turning the code into user-facing German copy, the same
/// way the web dashboard's client code does.
struct APIErrorBody: Decodable {
    let error: String
    let retryAfter: Int?
}

enum APIError: Error, LocalizedError {
    /// HTTP 401 — no/invalid/expired session. Callers should route back to
    /// the login screen and clear the stored token.
    case unauthorized
    /// A recognised `{ error: <code> }` body, with the HTTP status attached
    /// (403 pro_required, 402 scan_limit_reached, 429 rate_limited, ...).
    case server(code: String, status: Int, retryAfterSeconds: Int?)
    /// A non-2xx response with a body that isn't the `{ error }` shape.
    case unexpectedStatus(Int)
    case network(Error)
    case decoding(Error)

    var errorDescription: String? {
        switch self {
        case .unauthorized:
            return "Bitte melde dich erneut an."
        case .server(let code, _, let retryAfter):
            return APIError.message(forCode: code, retryAfterSeconds: retryAfter)
        case .unexpectedStatus(let status):
            return "Unerwartete Antwort vom Server (\(status))."
        case .network:
            return "Keine Verbindung zum Server. Prüfe deine Internetverbindung."
        case .decoding:
            return "Antwort des Servers konnte nicht gelesen werden."
        }
    }

    /// Central place to translate a backend error code into German UI copy.
    /// Extend this switch as features land — it deliberately mirrors what the
    /// web app's route handlers can return, not a guess at future codes.
    static func message(forCode code: String, retryAfterSeconds: Int?) -> String {
        switch code {
        case "invalid_credentials":
            return "E-Mail oder Passwort ist falsch."
        case "email_not_verified":
            return "Bitte bestätige zuerst deine E-Mail-Adresse."
        case "rate_limited":
            if let seconds = retryAfterSeconds, seconds > 0 {
                return "Zu viele Versuche. Bitte in \(seconds) Sekunden erneut versuchen."
            }
            return "Zu viele Versuche. Bitte später erneut versuchen."
        case "invalid_email":
            return "Diese E-Mail-Adresse ist ungültig."
        case "weak_password":
            return "Das Passwort ist zu schwach."
        case "disposable_email":
            return "Bitte verwende eine reguläre E-Mail-Adresse."
        case "mail_failed":
            return "Bestätigungs-E-Mail konnte nicht gesendet werden. Bitte später erneut versuchen."
        case "database_unavailable":
            return "Server vorübergehend nicht erreichbar. Bitte später erneut versuchen."
        case "pro_required":
            return "Diese Funktion ist Pro-Nutzern vorbehalten."
        case "scan_limit_reached":
            return "Dein monatliches Scan-Kontingent ist aufgebraucht."
        case "daily_scan_limit_reached":
            return "Tageslimit für Scans erreicht. Bitte morgen erneut versuchen."
        case "csrf_failed":
            return "Sicherheitsprüfung fehlgeschlagen. Bitte App neu starten."
        case "unauthorized":
            return "Bitte melde dich erneut an."
        default:
            return "Etwas ist schiefgelaufen (\(code))."
        }
    }
}
