import * as m from '$lib/paraglide/messages.js';

/**
 * Mirror of the backend ErrorCode enum.
 * Keep in sync with backend/src/main/java/org/raddatz/familienarchiv/exception/ErrorCode.java
 */
export type ErrorCode =
	| 'PERSON_NOT_FOUND'
	| 'ALIAS_NOT_FOUND'
	| 'INVALID_PERSON_TYPE'
	| 'BIRTH_AFTER_DEATH'
	| 'INVALID_DATE_PRECISION'
	| 'INVALID_RELATIONSHIP_DATES'
	| 'INVALID_DATE_RANGE'
	| 'DOCUMENT_NOT_FOUND'
	| 'DOCUMENT_NO_FILE'
	| 'FILE_NOT_FOUND'
	| 'FILE_UPLOAD_FAILED'
	| 'UNSUPPORTED_FILE_TYPE'
	| 'USER_NOT_FOUND'
	| 'EMAIL_ALREADY_IN_USE'
	| 'WRONG_CURRENT_PASSWORD'
	| 'IMPORT_ALREADY_RUNNING'
	| 'IMPORT_ARTIFACT_INVALID'
	| 'INVALID_RESET_TOKEN'
	| 'INVITE_NOT_FOUND'
	| 'INVITE_EXHAUSTED'
	| 'INVITE_REVOKED'
	| 'INVITE_EXPIRED'
	| 'GROUP_HAS_ACTIVE_INVITES'
	| 'GROUP_NOT_FOUND'
	| 'ANNOTATION_NOT_FOUND'
	| 'ANNOTATION_UPDATE_FAILED'
	| 'TRANSCRIPTION_BLOCK_NOT_FOUND'
	| 'TRANSCRIPTION_BLOCK_CONFLICT'
	| 'COMMENT_NOT_FOUND'
	| 'OCR_SERVICE_UNAVAILABLE'
	| 'OCR_JOB_NOT_FOUND'
	| 'OCR_DOCUMENT_NOT_UPLOADED'
	| 'OCR_PROCESSING_FAILED'
	| 'TRAINING_ALREADY_RUNNING'
	| 'OCR_TRAINING_CONFLICT'
	| 'INVALID_TAG_COLOR'
	| 'TAG_CYCLE_DETECTED'
	| 'TAG_NOT_FOUND'
	| 'TAG_MERGE_SELF'
	| 'TAG_MERGE_INVALID_TARGET'
	| 'RELATIONSHIP_NOT_FOUND'
	| 'CIRCULAR_RELATIONSHIP'
	| 'DUPLICATE_RELATIONSHIP'
	| 'GESCHICHTE_NOT_FOUND'
	| 'JOURNEY_ITEM_NOT_FOUND'
	| 'JOURNEY_ITEM_POSITION_CONFLICT'
	| 'JOURNEY_AT_CAPACITY'
	| 'JOURNEY_NOTE_TOO_LONG'
	| 'JOURNEY_DOCUMENT_ALREADY_ADDED'
	| 'GESCHICHTE_TYPE_IMMUTABLE'
	| 'GESCHICHTE_TITLE_TOO_LONG'
	| 'GESCHICHTE_INTRO_TOO_LONG'
	| 'TIMELINE_EVENT_NOT_FOUND'
	| 'TIMELINE_EVENT_CONFLICT'
	| 'TIMELINE_TITLE_TOO_LONG'
	| 'INVALID_CREDENTIALS'
	| 'SESSION_EXPIRED'
	| 'MISSING_CREDENTIALS'
	| 'UNAUTHORIZED'
	| 'FORBIDDEN'
	| 'CSRF_TOKEN_MISSING'
	| 'TOO_MANY_LOGIN_ATTEMPTS'
	| 'VALIDATION_ERROR'
	| 'BATCH_TOO_LARGE'
	| 'BULK_EDIT_TOO_MANY_IDS'
	| 'CONFLICT'
	| 'INTERNAL_ERROR';

export interface BackendError {
	code: ErrorCode;
	message: string; // English developer message — not shown to users
}

/**
 * Attempts to parse a backend ErrorResponse from a failed fetch response.
 * Returns null if the body is not valid JSON or does not contain a code field.
 */
export async function parseBackendError(res: Response): Promise<BackendError | null> {
	try {
		const body = await res.json();
		if (body && typeof body.code === 'string') {
			return body as BackendError;
		}
	} catch {
		// Body was not JSON
	}
	return null;
}

/** Returns a localised message for the given error code via Paraglide. Falls back to INTERNAL_ERROR. */
export function getErrorMessage(code: ErrorCode | string | undefined): string {
	switch (code) {
		case 'PERSON_NOT_FOUND':
			return m.error_person_not_found();
		case 'ALIAS_NOT_FOUND':
			return m.error_alias_not_found();
		case 'INVALID_PERSON_TYPE':
			return m.error_invalid_person_type();
		case 'BIRTH_AFTER_DEATH':
			return m.error_birth_after_death();
		case 'INVALID_DATE_PRECISION':
			return m.error_invalid_date_precision();
		case 'INVALID_RELATIONSHIP_DATES':
			return m.error_invalid_relationship_dates();
		case 'INVALID_DATE_RANGE':
			return m.error_invalid_date_range();
		case 'DOCUMENT_NOT_FOUND':
			return m.error_document_not_found();
		case 'DOCUMENT_NO_FILE':
			return m.error_document_no_file();
		case 'FILE_NOT_FOUND':
			return m.error_file_not_found();
		case 'FILE_UPLOAD_FAILED':
			return m.error_file_upload_failed();
		case 'UNSUPPORTED_FILE_TYPE':
			return m.error_unsupported_file_type();
		case 'USER_NOT_FOUND':
			return m.error_user_not_found();
		case 'EMAIL_ALREADY_IN_USE':
			return m.error_email_already_in_use();
		case 'WRONG_CURRENT_PASSWORD':
			return m.error_wrong_current_password();
		case 'IMPORT_ALREADY_RUNNING':
			return m.error_import_already_running();
		case 'IMPORT_ARTIFACT_INVALID':
			return m.error_import_artifact_invalid();
		case 'INVALID_RESET_TOKEN':
			return m.error_invalid_reset_token();
		case 'INVITE_NOT_FOUND':
			return m.error_invite_not_found();
		case 'INVITE_EXHAUSTED':
			return m.error_invite_exhausted();
		case 'INVITE_REVOKED':
			return m.error_invite_revoked();
		case 'INVITE_EXPIRED':
			return m.error_invite_expired();
		case 'GROUP_HAS_ACTIVE_INVITES':
			return m.error_group_has_active_invites();
		case 'GROUP_NOT_FOUND':
			return m.error_group_not_found();
		case 'ANNOTATION_NOT_FOUND':
			return m.error_annotation_not_found();
		case 'ANNOTATION_UPDATE_FAILED':
			return m.error_annotation_update_failed();
		case 'TRANSCRIPTION_BLOCK_NOT_FOUND':
			return m.error_transcription_block_not_found();
		case 'TRANSCRIPTION_BLOCK_CONFLICT':
			return m.error_transcription_block_conflict();
		case 'COMMENT_NOT_FOUND':
			return m.error_comment_not_found();
		case 'OCR_SERVICE_UNAVAILABLE':
			return m.error_ocr_service_unavailable();
		case 'OCR_JOB_NOT_FOUND':
			return m.error_ocr_job_not_found();
		case 'OCR_DOCUMENT_NOT_UPLOADED':
			return m.error_ocr_document_not_uploaded();
		case 'OCR_PROCESSING_FAILED':
			return m.error_ocr_processing_failed();
		case 'TRAINING_ALREADY_RUNNING':
			return m.error_training_already_running();
		case 'OCR_TRAINING_CONFLICT':
			return m.error_internal_error();
		case 'INVALID_TAG_COLOR':
			return m.error_invalid_tag_color();
		case 'TAG_CYCLE_DETECTED':
			return m.error_tag_cycle_detected();
		case 'TAG_NOT_FOUND':
			return m.error_tag_not_found();
		case 'TAG_MERGE_SELF':
			return m.error_tag_merge_self();
		case 'TAG_MERGE_INVALID_TARGET':
			return m.error_tag_merge_invalid_target();
		case 'RELATIONSHIP_NOT_FOUND':
			return m.error_relationship_not_found();
		case 'CIRCULAR_RELATIONSHIP':
			return m.error_circular_relationship();
		case 'DUPLICATE_RELATIONSHIP':
			return m.error_duplicate_relationship();
		case 'GESCHICHTE_NOT_FOUND':
			return m.error_geschichte_not_found();
		case 'JOURNEY_ITEM_NOT_FOUND':
			return m.error_journey_item_not_found();
		case 'JOURNEY_ITEM_POSITION_CONFLICT':
			return m.error_journey_item_position_conflict();
		case 'JOURNEY_AT_CAPACITY':
			return m.error_journey_at_capacity();
		case 'JOURNEY_NOTE_TOO_LONG':
			return m.error_journey_note_too_long();
		case 'JOURNEY_DOCUMENT_ALREADY_ADDED':
			return m.error_journey_document_already_added();
		case 'GESCHICHTE_TYPE_IMMUTABLE':
			return m.error_geschichte_type_immutable();
		case 'GESCHICHTE_TITLE_TOO_LONG':
			return m.error_geschichte_title_too_long();
		case 'GESCHICHTE_INTRO_TOO_LONG':
			return m.error_geschichte_intro_too_long();
		case 'TIMELINE_EVENT_NOT_FOUND':
			return m.error_timeline_event_not_found();
		case 'TIMELINE_EVENT_CONFLICT':
			return m.error_timeline_event_conflict();
		case 'TIMELINE_TITLE_TOO_LONG':
			return m.error_timeline_title_too_long();
		case 'INVALID_CREDENTIALS':
			return m.error_invalid_credentials();
		case 'SESSION_EXPIRED':
			return m.error_session_expired();
		case 'MISSING_CREDENTIALS':
			return m.login_error_missing_credentials();
		case 'UNAUTHORIZED':
			return m.error_unauthorized();
		case 'FORBIDDEN':
			return m.error_forbidden();
		case 'CSRF_TOKEN_MISSING':
			return m.error_csrf_token_missing();
		case 'TOO_MANY_LOGIN_ATTEMPTS':
			return m.error_too_many_login_attempts();
		case 'VALIDATION_ERROR':
			return m.error_validation_error();
		case 'BATCH_TOO_LARGE':
			return m.error_batch_too_large();
		case 'BULK_EDIT_TOO_MANY_IDS':
			return m.error_bulk_edit_too_many_ids();
		case 'CONFLICT':
			return m.error_conflict();
		default:
			return m.error_internal_error();
	}
}
