import { get, post, withQuery } from './client';
import type { Fix, FixesPage, FixRequest } from './types/fixes';
import type { Job, JobId, JobUpdate } from './types/jobs';
import type {
	CheckResult,
	LinkDetail,
	LinksPage,
	LinksQuery,
	Suggestion,
} from './types/links';
import type { Settings, SettingsUpdate } from './types/settings';
import type { ScanAction, Status } from './types/status';

export const FIXES_PER_PAGE = 20;

export const api = {
	status: async ( signal: AbortSignal ) =>
		( await get( '/status', signal ) ) as Status,
	scan: async ( action: ScanAction ) =>
		( await post( '/scan', { action } ) ) as Status,
	scanStep: async () => {
		await post( '/scan/step' );
	},
	links: async ( query: LinksQuery, signal: AbortSignal ) => {
		const path = withQuery( '/links', [
			[ 'status', query.status ],
			[ 'search', query.search ],
			[ 'orderby', query.orderby ],
			[ 'order', query.order ],
			[ 'page', query.page ],
			[ 'per_page', query.per_page ],
		] );

		return ( await get( path, signal ) ) as LinksPage;
	},
	link: async ( linkId: number, signal: AbortSignal ) =>
		( await get( `/links/${ String( linkId ) }`, signal ) ) as LinkDetail,
	suggestions: async ( linkId: number, signal: AbortSignal ) =>
		( await get(
			`/links/${ String( linkId ) }/suggestions`,
			signal
		) ) as Suggestion[],
	recheck: async ( linkId: number ) =>
		( await post( `/links/${ String( linkId ) }/recheck` ) ) as LinkDetail,
	test: async ( url: string ) =>
		( await post( '/links/test', { url } ) ) as CheckResult,
	createFix: async ( request: FixRequest ) =>
		( await post( '/fixes', request ) ) as Fix,
	runFix: async ( fixId: number ) =>
		( await post( `/fixes/${ String( fixId ) }/run` ) ) as Fix,
	undoFix: async ( fixId: number ) =>
		( await post( `/fixes/${ String( fixId ) }/undo` ) ) as Fix,
	fixes: async ( page: number, signal: AbortSignal ) => {
		const path = withQuery( '/fixes', [
			[ 'page', page ],
			[ 'per_page', FIXES_PER_PAGE ],
		] );

		return ( await get( path, signal ) ) as FixesPage;
	},
	jobs: async ( signal: AbortSignal ) =>
		( await get( '/jobs', signal ) ) as Job[],
	updateJob: async ( jobId: JobId, update: JobUpdate ) =>
		( await post( `/jobs/${ jobId }`, update ) ) as Job,
	runJobs: async () => ( await post( '/jobs/run' ) ) as Job[],
	settings: async ( signal: AbortSignal ) =>
		( await get( '/settings', signal ) ) as Settings,
	updateSettings: async ( update: SettingsUpdate ) =>
		( await post( '/settings', update ) ) as Settings,
};
