import { BaseProvider } from '#templates/base/provider';
import { Client } from '#models/Client';

	export interface OidcProviderClientConfig {
	client_id: string;
	client_secret?: string;
	grant_types: string[];
	redirect_uris: string[];
	post_logout_redirect_uris: string[];
	response_types: string[];
	scope: string;
	token_endpoint_auth_method: string;
	require_pkce: boolean;
	backchannel_logout_uri?: string;
	backchannel_logout_session_required?: boolean;
}

export class ClientProvider extends BaseProvider<Client> {
	public static instance: ClientProvider;

	public static getInstance(): ClientProvider {
		ClientProvider.instance ??= new ClientProvider();
		return ClientProvider.instance;
	}

	public static get model() {
		return Client;
	}

	constructor() {
		super('Client');
	}

	async listActive(): Promise<Client[]> {
		const { rows } = await this.getAll({
			where: { status: 'active' },
			page: 1,
			pageSize: 1000,
		});
		return rows;
	}

	toOidcProviderConfig(client: Client): OidcProviderClientConfig {
		const scopes = Array.isArray(client.scopes) && client.scopes.length > 0
			? client.scopes
			: ['openid', 'profile', 'email'];
		const grantTypes = Array.isArray(client.grant_types) && client.grant_types.length > 0
			? client.grant_types
			: ['authorization_code', 'refresh_token'];
		const responseTypes = Array.isArray(client.response_types) && client.response_types.length > 0
			? client.response_types
			: ['code'];
		const redirectUris = Array.isArray(client.redirect_uris) ? client.redirect_uris : [];
		const postLogoutRedirectUris = Array.isArray(client.post_logout_redirect_uris)
			? client.post_logout_redirect_uris
			: [];

		const authMethod = client.token_endpoint_auth_method ?? 'none';
		const requirePkce = typeof client.require_pkce === 'boolean' ? client.require_pkce : authMethod === 'none';

		const config: OidcProviderClientConfig = {
			client_id: client.client_id,
			grant_types: grantTypes,
			redirect_uris: redirectUris,
			post_logout_redirect_uris: postLogoutRedirectUris,
			response_types: responseTypes,
			scope: scopes.join(' '),
			token_endpoint_auth_method: authMethod,
			require_pkce: requirePkce,
		};

		if (client.client_secret_hash && authMethod !== 'none') {
			config.client_secret = client.client_secret_hash;
		}

		if (client.backchannel_logout_uri) {
			config.backchannel_logout_uri = client.backchannel_logout_uri;
			config.backchannel_logout_session_required =
				typeof client.backchannel_logout_session_required === 'boolean'
					? client.backchannel_logout_session_required
					: false;
		}

		return config;
	}
}
