/* eslint-disable @typescript-eslint/no-explicit-any */
import { OidcConfigService } from '#config/oidcConfigService';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyProvider = any;

export class OidcService {
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	private static instance: AnyProvider = undefined;
	private static readonly configService = new OidcConfigService();

	static getInstance(): AnyProvider {
		if (!this.instance) {
			throw new Error('OidcService not initialized. Call initialize() first.');
		}
		return this.instance;
	}

	static async initialize(): Promise<AnyProvider> {
		if (this.instance) return this.instance;

		// eslint-disable-next-line @typescript-eslint/no-var-requires
		const { default: OidcProvider } = require('oidc-provider');

		const { OidcAdapterService } = await import('./oidcAdapterService.js');
		// eslint-disable-next-line @typescript-eslint/no-var-requires
		const sequelize = require('#services/database/sequelize/sequelizeService').default;
		const adapterService = new OidcAdapterService(sequelize);

		// eslint-disable-next-line @typescript-eslint/no-explicit-any
		const provider = new (OidcProvider as any)(this.configService.issuer, {
			adapter: (name: string) => adapterService.createAdapter(name),
			findAccount: async (_ctx: unknown, sub: string) => ({
				accountId: sub,
				claims: () => ({ sub }),
			}),
			cookies: {
				keys: this.configService.cookieKeys,
				long: { httpOnly: true, sameSite: 'lax' },
				short: { httpOnly: true, sameSite: 'lax' },
			},
			claims: {
				openid: ['sub'],
				profile: ['name', 'preferred_username'],
				email: ['email', 'email_verified'],
			},
			ttl: {
				AccessToken: this.configService.accessTokenTtl,
				RefreshToken: this.configService.refreshTokenTtl,
			},
			features: {
				devInteractions: { enabled: false },
				introspection: { enabled: true },
				revocation: { enabled: true },
				rpInitiatedLogout: { enabled: true },
			},
			routes: {
				authorization: '/oauth/authorize',
				token: '/oauth/token',
				userinfo: '/oauth/userinfo',
				jwks: '/oauth/jwks',
				introspection: '/oauth/introspect',
				revocation: '/oauth/revoke',
				end_session: '/oauth/logout',
			},
			interactions: {
				url: (_ctx: unknown, interaction: { uid: string }) => `/oidc/interaction/${interaction.uid}`,
			},
		});

		this.instance = provider;
		return provider;
	}

	static callback() {
		return this.getInstance().callback();
	}

	static async interactionDetails(req: unknown, res: unknown) {
		return this.getInstance().interactionDetails(req, res);
	}

	static async interactionFinished(req: unknown, res: unknown, result: unknown, options?: unknown) {
		return this.getInstance().interactionFinished(req, res, result, options);
	}

	static async close(): Promise<void> {
		this.instance = undefined;
	}
}
