// #region TranslateRunsApi [C:2] [TYPE Module] [SEMANTICS translate, runs, api, control, status]
// @BRIEF API client for translation run control — trigger, status, history, records, retry, cancel, metrics.
// @LAYER API
// @RELATION DEPENDS_ON -> [ApiModule]
// @POST All functions return typed responses or throw normalized TranslateApiError.

import { api } from '$lib/api';
import type { TranslateApiError } from './jobs';

function normalizeTranslateError(error: unknown, defaultMessage: string = 'Translation API error'): TranslateApiError {
	const message =
		(error && typeof (error as Error).message === 'string' && (error as Error).message) ||
		(typeof error === 'string' && error) ||
		defaultMessage;
	return { message, code: 'TRANSLATE_API_ERROR' as const, retryable: true };
}

export interface RunQueryOptions {
	page?: number;
	page_size?: number;
}

export interface RunHistoryQueryOptions extends RunQueryOptions {
	status?: string;
}

export interface AllRunsQueryOptions extends RunQueryOptions {
	job_id?: string;
	status?: string;
	trigger_type?: string;
	created_by?: string;
}

// #region triggerRun [C:2] [TYPE Function] [SEMANTICS translate, runs, trigger]
// @BRIEF Trigger a new translation run for a job.
// @PRE jobId is a non-empty string.
// @POST Returns created run response with status.
// @SIDE_EFFECT Starts async translation processing on the backend.
// @RELATION DEPENDS_ON -> [ApiModule.postApi]
export async function triggerRun<T = unknown>(jobId: string, full: boolean = false): Promise<T> {
	try {
		const query = full ? '?full_translation=true' : '';
		return await api.postApi<T>(`/translate/jobs/${jobId}/run${query}`, {});
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to start translation run');
	}
}
// #endregion triggerRun

// #region fetchRunStatus [C:2] [TYPE Function] [SEMANTICS translate, runs, status]
// @BRIEF Fetch the current status of a translation run.
// @PRE runId is a non-empty string.
// @POST Returns run status object with progress.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchRunStatus<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.fetchApi<T>(`/translate/runs/${runId}`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch run status');
	}
}
// #endregion fetchRunStatus

// #region fetchRunHistory [C:2] [TYPE Function] [SEMANTICS translate, runs, history]
// @BRIEF Fetch paginated run history for a job.
// @PRE jobId is a non-empty string.
// @POST Returns paginated run list.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchRunHistory<T = unknown>(jobId: string, options: RunHistoryQueryOptions = {}): Promise<T> {
	try {
		const params = new URLSearchParams();
		if (options.page != null) params.append('page', String(options.page));
		if (options.page_size != null) params.append('page_size', String(options.page_size));
		const query = params.toString();
		return await api.fetchApi<T>(`/translate/jobs/${jobId}/runs${query ? `?${query}` : ''}`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch run history');
	}
}
// #endregion fetchRunHistory

// #region fetchRunRecords [C:2] [TYPE Function] [SEMANTICS translate, runs, records]
// @BRIEF Fetch paginated records for a translation run.
// @PRE runId is a non-empty string.
// @POST Returns paginated record list with translations.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchRunRecords<T = unknown>(runId: string, options: RunQueryOptions & { status?: string } = {}): Promise<T> {
	try {
		const params = new URLSearchParams();
		if (options.page != null) params.append('page', String(options.page));
		if (options.page_size != null) params.append('page_size', String(options.page_size));
		if (options.status) params.append('status', options.status);
		const query = params.toString();
		return await api.fetchApi<T>(`/translate/runs/${runId}/records${query ? `?${query}` : ''}`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch run records');
	}
}
// #endregion fetchRunRecords

// #region retryFailedBatches [C:2] [TYPE Function] [SEMANTICS translate, runs, retry, batches]
// @BRIEF Retry failed batches in a translation run.
// @PRE runId is a non-empty string.
// @POST Returns retry status.
// @SIDE_EFFECT Re-queues failed batches for processing.
// @RELATION DEPENDS_ON -> [ApiModule.postApi]
export async function retryFailedBatches<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.postApi<T>(`/translate/runs/${runId}/retry`, {});
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to retry batches');
	}
}
// #endregion retryFailedBatches

// #region retryInsert [C:2] [TYPE Function] [SEMANTICS translate, runs, retry, insert]
// @BRIEF Retry failed insert operations for a run.
// @PRE runId is a non-empty string.
// @POST Returns retry status.
// @SIDE_EFFECT Re-attempts failed DB insert operations.
// @RELATION DEPENDS_ON -> [ApiModule.postApi]
export async function retryInsert<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.postApi<T>(`/translate/runs/${runId}/retry-insert`, {});
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to retry insert');
	}
}
// #endregion retryInsert

// #region cancelRun [C:2] [TYPE Function] [SEMANTICS translate, runs, cancel]
// @BRIEF Cancel a running translation run.
// @PRE runId is a non-empty string referring to a RUNNING run.
// @POST Run is cancelled and no further batches will be processed.
// @SIDE_EFFECT Interrupts processing and marks run as CANCELLED.
// @RELATION DEPENDS_ON -> [ApiModule.postApi]
export async function cancelRun<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.postApi<T>(`/translate/runs/${runId}/cancel`, {});
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to cancel run');
	}
}
// #endregion cancelRun

// #region fetchRunBatches [C:2] [TYPE Function] [SEMANTICS translate, runs, batches]
// @BRIEF Fetch batch-level breakdown for a run.
// @PRE runId is a non-empty string.
// @POST Returns batch list with status and record counts.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchRunBatches<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.fetchApi<T>(`/translate/runs/${runId}/batches`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch run batches');
	}
}
// #endregion fetchRunBatches

// #region fetchAllRuns [C:2] [TYPE Function] [SEMANTICS translate, runs, all, list]
// @BRIEF Fetch all translation runs across jobs with optional filters.
// @POST Returns paginated cross-job run list.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchAllRuns<T = unknown>(options: AllRunsQueryOptions = {}): Promise<T> {
	try {
		const params = new URLSearchParams();
		if (options.page != null) params.append('page', String(options.page));
		if (options.page_size != null) params.append('page_size', String(options.page_size));
		if (options.job_id) params.append('job_id', options.job_id);
		if (options.status) params.append('status', options.status);
		if (options.trigger_type) params.append('trigger_type', options.trigger_type);
		if (options.created_by) params.append('created_by', options.created_by);
		const query = params.toString();
		return await api.fetchApi<T>(`/translate/runs${query ? `?${query}` : ''}`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch runs');
	}
}
// #endregion fetchAllRuns

// #region fetchRunDetail [C:2] [TYPE Function] [SEMANTICS translate, runs, detail]
// @BRIEF Fetch detailed run information with aggregated stats.
// @PRE runId is a non-empty string.
// @POST Returns run detail with progress and record breakdown.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchRunDetail<T = unknown>(runId: string): Promise<T> {
	try {
		return await api.fetchApi<T>(`/translate/runs/${runId}/detail`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch run detail');
	}
}
// #endregion fetchRunDetail

// #region fetchJobMetrics [C:2] [TYPE Function] [SEMANTICS translate, metrics, job]
// @BRIEF Fetch aggregate metrics for a translation job.
// @PRE jobId is a non-empty string.
// @POST Returns metrics object with counts and stats.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchJobMetrics<T = unknown>(jobId: string): Promise<T> {
	try {
		return await api.fetchApi<T>(`/translate/jobs/${jobId}/metrics`);
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch job metrics');
	}
}
// #endregion fetchJobMetrics

// #region fetchAllMetrics [C:2] [TYPE Function] [SEMANTICS translate, metrics, all]
// @BRIEF Fetch aggregate metrics across all translation jobs.
// @POST Returns cross-job metrics.
// @RELATION DEPENDS_ON -> [ApiModule.fetchApi]
export async function fetchAllMetrics<T = unknown>(): Promise<T> {
	try {
		return await api.fetchApi<T>('/translate/metrics');
	} catch (error) {
		throw normalizeTranslateError(error, 'Failed to fetch metrics');
	}
}
// #endregion fetchAllMetrics
// #endregion TranslateRunsApi
