package org.raddatz.familienarchiv.exception;

/**
 * Machine-readable error codes returned in API responses.
 * The frontend uses these to display localised messages to the user.
 * Every code must be documented here with its meaning and the HTTP status
 * it is paired with in DomainException.
 */
public enum ErrorCode {

    // --- Persons ---
    /** A person with the given ID does not exist. 404 */
    PERSON_NOT_FOUND,
    /** A person name alias with the given ID does not exist. 404 */
    ALIAS_NOT_FOUND,
    /** The submitted personType value is not allowed (e.g. SKIP is import-only). 400 */
    INVALID_PERSON_TYPE,
    /** A person's birth date is after their death date. 400 */
    BIRTH_AFTER_DEATH,
    /** A life date and its precision are incoherent: date present with UNKNOWN precision, or precision set without a date. 400 */
    INVALID_DATE_PRECISION,
    // --- Documents ---
    /** A document with the given ID does not exist. 404 */
    DOCUMENT_NOT_FOUND,
    /** The document exists but has no file attached yet. 404 */
    DOCUMENT_NO_FILE,
    /** The file referenced by the document is missing in object storage. 404 */
    FILE_NOT_FOUND,
    /** An error occurred while uploading a file to object storage. 500 */
    FILE_UPLOAD_FAILED,
    /** The uploaded file's content type is not supported (PDF/JPEG/PNG/TIFF only). 400 */
    UNSUPPORTED_FILE_TYPE,
    /** A RANGE date is invalid: meta_date_end is before meta_date, or an end date is set without RANGE precision. 400 */
    INVALID_DATE_RANGE,

    // --- Users ---
    /** A user with the given ID or username does not exist. 404 */
    USER_NOT_FOUND,
    /** A group with the given ID does not exist. 404 */
    GROUP_NOT_FOUND,
    /** The supplied email address is already used by another account. 409 */
    EMAIL_ALREADY_IN_USE,
    /** The supplied current password does not match the stored hash. 400 */
    WRONG_CURRENT_PASSWORD,

    // --- Import ---
    /** A mass import is already in progress; only one can run at a time. 409 */
    IMPORT_ALREADY_RUNNING,
    /** A canonical import artifact is missing, unreadable, or missing a required header. 400 */
    IMPORT_ARTIFACT_INVALID,

    // --- Thumbnails ---
    /** A thumbnail backfill is already in progress; only one can run at a time. 409 */
    THUMBNAIL_BACKFILL_ALREADY_RUNNING,

    // --- Invites ---
    /** The invite code does not exist. 404 */
    INVITE_NOT_FOUND,
    /** The invite has already reached its use limit. 409 */
    INVITE_EXHAUSTED,
    /** The invite has been revoked by an admin. 409 */
    INVITE_REVOKED,
    /** The invite has passed its expiry date. 410 */
    INVITE_EXPIRED,
    /** A group cannot be deleted because one or more active invites reference it. 409 */
    GROUP_HAS_ACTIVE_INVITES,

    // --- Auth ---
    /** The request is not authenticated. 401 */
    UNAUTHORIZED,
    /** The authenticated user lacks the required permission. 403 */
    FORBIDDEN,
    /** The supplied email/password combination does not match any active account. 401 */
    INVALID_CREDENTIALS,
    /** The session has expired or been invalidated. 401 */
    SESSION_EXPIRED,
    /** The password-reset token is missing, expired, or already used. 400 */
    INVALID_RESET_TOKEN,
    /** CSRF token is missing or does not match the expected value. 403 */
    CSRF_TOKEN_MISSING,
    /** The login rate limit has been exceeded for this IP/email combination. 429 */
    TOO_MANY_LOGIN_ATTEMPTS,

    // --- Annotations ---
    /** The annotation with the given ID does not exist. 404 */
    ANNOTATION_NOT_FOUND,
    /** The annotation position/size could not be saved (bounds constraint violated). 400 */
    ANNOTATION_UPDATE_FAILED,

    // --- Transcription Blocks ---
    /** The transcription block with the given ID does not exist. 404 */
    TRANSCRIPTION_BLOCK_NOT_FOUND,
    /** Optimistic locking conflict — block was modified by another user. 409 */
    TRANSCRIPTION_BLOCK_CONFLICT,

    // --- Comments ---
    /** The comment with the given ID does not exist. 404 */
    COMMENT_NOT_FOUND,

    // --- Notifications ---
    /** The notification with the given ID does not exist. 404 */
    NOTIFICATION_NOT_FOUND,

    // --- OCR ---
    /** The OCR service is not available or not healthy. 503 */
    OCR_SERVICE_UNAVAILABLE,
    /** The OCR job with the given ID does not exist. 404 */
    OCR_JOB_NOT_FOUND,
    /** The document is not in UPLOADED status and cannot be OCR'd. 400 */
    OCR_DOCUMENT_NOT_UPLOADED,
    /** OCR processing failed for the document. 500 */
    OCR_PROCESSING_FAILED,
    /** A training run is already in progress. 409 */
    TRAINING_ALREADY_RUNNING,
    /** Internal inconsistency: expected training run row was not found after creation. 500 */
    OCR_TRAINING_CONFLICT,

    // --- Relationships (Stammbaum) ---
    /** A relationship row with the given ID does not exist. 404 */
    RELATIONSHIP_NOT_FOUND,
    /** Adding this relationship would create a cycle (e.g. reverse PARENT_OF already exists). 409 */
    CIRCULAR_RELATIONSHIP,
    /** A relationship with the same (person, relatedPerson, type) already exists. 409 */
    DUPLICATE_RELATIONSHIP,
    /** A relationship's toDate is before its fromDate. 400 */
    INVALID_RELATIONSHIP_DATES,

    // --- Geschichten (Stories) ---
    /** A Geschichte (story) with the given ID does not exist, or is a DRAFT and the caller lacks BLOG_WRITE. 404 */
    GESCHICHTE_NOT_FOUND,
    /** A JourneyItem with the given ID does not exist, or belongs to a different journey (IDOR). 404 */
    JOURNEY_ITEM_NOT_FOUND,
    /** A position uniqueness conflict occurred on the journey_items table — concurrent append or reorder. 409 */
    JOURNEY_ITEM_POSITION_CONFLICT,
    /** The journey already has the maximum allowed number of items (100). 400 */
    JOURNEY_AT_CAPACITY,
    /** The document is already present in this journey — duplicate items are not allowed. 409 */
    JOURNEY_DOCUMENT_ALREADY_ADDED,
    /** The type of an existing Geschichte cannot be changed via PATCH. 409 */
    GESCHICHTE_TYPE_IMMUTABLE,
    /** A journey-item note exceeds the maximum length (2000 characters). 400 */
    JOURNEY_NOTE_TOO_LONG,
    /** A Geschichte title exceeds the maximum length (255 characters — the DB column bound). 400 */
    GESCHICHTE_TITLE_TOO_LONG,
    /** A JOURNEY intro (body) exceeds the maximum length (4000 characters). 400 */
    GESCHICHTE_INTRO_TOO_LONG,

    // --- Tags ---
    /** A tag with the given ID does not exist. 404 */
    TAG_NOT_FOUND,
    /** The supplied color token is not in the allowed palette. 400 */
    INVALID_TAG_COLOR,
    /** Setting this parent would create a cycle in the tag hierarchy. 400 */
    TAG_CYCLE_DETECTED,
    /** Merge source and target are the same tag. 400 */
    TAG_MERGE_SELF,
    /** The merge target is a descendant of the source tag. 400 */
    TAG_MERGE_INVALID_TARGET,

    // --- Timeline (Zeitstrahl) ---
    /** A timeline event with the given ID does not exist. 404 */
    TIMELINE_EVENT_NOT_FOUND,
    /** Optimistic-locking conflict — the timeline event was modified by another curator. 409 */
    TIMELINE_EVENT_CONFLICT,
    /** A timeline event title exceeds the maximum length (255 characters — the DB column bound). 400 */
    TIMELINE_TITLE_TOO_LONG,

    // --- Generic ---
    /** Request validation failed (missing or malformed fields). 400 */
    VALIDATION_ERROR,
    /** Batch upload exceeds the maximum allowed file count per request. 400 */
    BATCH_TOO_LARGE,
    /** Bulk edit request exceeds the per-request document ID cap. 400 */
    BULK_EDIT_TOO_MANY_IDS,
    /** A concurrent modification was detected (generic optimistic-lock backstop). 409 */
    CONFLICT,
    /** An unexpected server-side error occurred. 500 */
    INTERNAL_ERROR,
}
