import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { rotateSigningKey, getValidKeys, getActiveKey } from '#jobs/secretRotation';
import { Req, Res } from '#interfaces/IApi';
import verify, { requireAdmin } from '#middlewares/auth';
import { auditAccessLogger } from '#middlewares/audit-access-logger';
import { sendSuccess } from '#utils/responseUtils';

/**
 * Admin API: OIDC Signing Key Management
 *
 * Handles zero-downtime rotation of RSA key pairs used by oidc-provider.
 *
 * Rotation flow:
 *   POST /rotate-signing-keys  →  Add new key, mark old for retirement (24h grace)
 *   (cron) retireOldKeys      →  Every hour; removes keys past deadline
 *
 * Key rotation is NOT auto-scheduled — only triggered manually by admins
 * to ensure controlled rollout and avoid mid-flight token invalidation.
 */
export default (_express: Application) => {
	return <Resource>{
		/**
		 * POST /api/v1/admin/keys/rotate
		 *
		 * Triggers a new signing key rotation:
		 * 1. Generates a new RSA-2048 key pair
		 * 2. Adds it to the keystore and marks it active
		 * 3. Marks the previous key for retirement (grace period: 24h)
		 * 4. The retireOldKeys cron job removes it after the grace period
		 */
		post: {
			middleware: [verify, requireAdmin, auditAccessLogger('ROTATED')],
			handler: async (req: Req, res: Res) => {
				try {
					const { newKid, retiredKid } = await rotateSigningKey();

					return sendSuccess(res, {
						newKid,
						retiredKid: retiredKid || null,
						gracePeriodHours: 24,
						message: retiredKid
							? `New key ${newKid} activated. Old key ${retiredKid} will be retired after 24h grace period.`
							: `First key ${newKid} activated (no previous key to retire).`,
					});
				} catch (error) {
					return res.error(error);
				}
			},
		},

		/**
		 * GET /api/v1/admin/keys
		 *
		 * Returns current keystore status: active key + pending-retirement keys.
		 * Used by admins to audit the signing key state.
		 */
		get: {
			middleware: [verify, requireAdmin],
			handler: async (req: Req, res: Res) => {
				try {
					const activeKey = getActiveKey();
					const validKeys = getValidKeys();

					return sendSuccess(res, {
						activeKid: activeKey?.kid || null,
						keys: validKeys.map((k) => ({
							kid: k.kid,
							alg: k.alg,
							use: k.use,
							createdAt: k.createdAt,
							rotatedAt: k.rotatedAt || null,
							isPendingRetirement: k.rotatedAt !== undefined,
						})),
					});
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};
