import { requireProjectCwd } from "../../../../src/web/bridge-service.ts";
import {
	getOnboardingService,
	type OnboardingState,
} from "../../../../src/web/onboarding-service.ts";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

type OnboardingAction =
	| { action: "discover_providers" }
	| { action: "recheck" }
	| { action: "save_api_key"; providerId: string; apiKey: string }
	| { action: "start_provider_flow"; providerId: string }
	| { action: "continue_provider_flow"; flowId: string; input: string }
	| { action: "cancel_provider_flow"; flowId: string }
	| { action: "logout_provider"; providerId: string };

function noStoreHeaders(): HeadersInit {
	return {
		"Cache-Control": "no-store",
	};
}

function errorResponse(
	status: number,
	error: unknown,
	onboarding?: OnboardingState,
): Response {
	return Response.json(
		{
			error: error instanceof Error ? error.message : String(error),
			...(onboarding ? { onboarding } : {}),
		},
		{
			status,
			headers: noStoreHeaders(),
		},
	);
}

function isActionPayload(value: unknown): value is OnboardingAction {
	return (
		typeof value === "object" &&
		value !== null &&
		typeof (value as { action?: unknown }).action === "string"
	);
}

export async function GET(request: Request): Promise<Response> {
	requireProjectCwd(request);
	return Response.json(
		{
			onboarding: await getOnboardingService().getState(),
		},
		{
			headers: noStoreHeaders(),
		},
	);
}

export async function POST(request: Request): Promise<Response> {
	requireProjectCwd(request);
	let payload: unknown;
	try {
		payload = await request.json();
	} catch (error) {
		return errorResponse(400, error);
	}

	if (!isActionPayload(payload)) {
		return errorResponse(
			400,
			"Request body must be a JSON object with an action field",
		);
	}

	const onboardingService = getOnboardingService();

	try {
		switch (payload.action) {
			case "discover_providers":
			case "recheck": {
				return Response.json(
					{ onboarding: await onboardingService.getState() },
					{
						headers: noStoreHeaders(),
					},
				);
			}
			case "save_api_key": {
				const onboarding = await onboardingService.validateAndSaveApiKey(
					payload.providerId,
					payload.apiKey,
				);
				return Response.json(
					{ onboarding },
					{
						status:
							onboarding.lastValidation?.status === "failed"
								? 422
								: onboarding.lockReason === "bridge_refresh_failed"
									? 503
									: onboarding.lockReason === "bridge_refresh_pending"
										? 202
										: 200,
						headers: noStoreHeaders(),
					},
				);
			}
			case "start_provider_flow": {
				const onboarding = await onboardingService.startProviderFlow(
					payload.providerId,
				);
				return Response.json(
					{ onboarding },
					{
						status: 202,
						headers: noStoreHeaders(),
					},
				);
			}
			case "continue_provider_flow": {
				const onboarding = await onboardingService.submitProviderFlowInput(
					payload.flowId,
					payload.input,
				);
				return Response.json(
					{ onboarding },
					{
						status: 202,
						headers: noStoreHeaders(),
					},
				);
			}
			case "cancel_provider_flow": {
				const onboarding = await onboardingService.cancelProviderFlow(
					payload.flowId,
				);
				return Response.json(
					{ onboarding },
					{
						headers: noStoreHeaders(),
					},
				);
			}
			case "logout_provider": {
				const onboarding = await onboardingService.logoutProvider(
					payload.providerId,
				);
				return Response.json(
					{ onboarding },
					{
						status:
							onboarding.lockReason === "bridge_refresh_failed"
								? 503
								: onboarding.lockReason === "bridge_refresh_pending"
									? 202
									: 200,
						headers: noStoreHeaders(),
					},
				);
			}
			default:
				return errorResponse(
					400,
					`Unsupported onboarding action: ${(payload as { action: string }).action}`,
				);
		}
	} catch (error) {
		return errorResponse(400, error, await onboardingService.getState());
	}
}
