import { Router, type Request, type Response } from 'express';
import { randomUUID } from 'crypto';
import type { Repository } from '../../db/repository.js';
import { logger } from '../../logger.js';
import { viewerOf } from '../space-viewer.js';
import { revokeDelegationCascade } from './revoke.js';

function isHttpsUri(u: string): boolean {
  try { return new URL(u).protocol === 'https:'; } catch { return false; }
}

/** admin ゲートの A2A クライアント登録。requireAdmin を server.ts 側で前段に置く前提。 */
export function createA2aClientsAdminRouter(repo: Repository, authActive: boolean): Router {
  const router = Router();

  router.post('/', (req: Request, res: Response) => {
    const { name, redirect_uris: redirectUris } = req.body ?? {};
    if (typeof name !== 'string' || !name.trim()) { res.status(400).json({ error: 'name required' }); return; }
    if (!Array.isArray(redirectUris) || redirectUris.length === 0) {
      res.status(400).json({ error: 'redirect_uris required' }); return;
    }
    if (!redirectUris.every((u: unknown) => typeof u === 'string' && isHttpsUri(u))) {
      res.status(400).json({ error: 'redirect_uris must all be https' }); return;
    }
    const clientId = `a2a_${randomUUID()}`;
    const actor = (req.user as Express.User | undefined)?.id ?? null;
    repo.createA2aClient({
      clientId, name: name.trim(), redirectUris,
      secretHash: null, tokenEndpointAuthMethod: 'none',
      agentCardUrl: null, issuer: null, keyFingerprint: null,
      status: 'active', createdBy: actor,
    });
    logger.info(`[a2a-oidc] client registered client_id=${clientId} by=${actor}`);
    res.status(201).json({ client_id: clientId, token_endpoint_auth_method: 'none' });
  });

  router.get('/', (_req: Request, res: Response) => {
    res.json({ clients: repo.listA2aClients().map(c => ({ ...c, secretHash: undefined })) });
  });

  router.post('/:id/disable', async (req: Request, res: Response) => {
    try {
      const c = repo.getA2aClient(req.params.id);
      if (!c) { res.status(404).json({ error: 'not found' }); return; }

      repo.setA2aClientStatus(req.params.id, 'disabled');

      const now = new Date().toISOString();
      const live = repo.listLiveA2aDelegationsForClient(req.params.id, now);
      const admin = viewerOf(req, authActive);

      let revokedDelegations = 0;
      let cancelledJobs = 0;
      for (const d of live) {
        const out = await revokeDelegationCascade(repo, d.id, { userId: admin.id, isAdmin: true }, now);
        if (out.status === 'revoked') {
          revokedDelegations++;
          cancelledJobs += out.cancelledJobs;
        }
      }

      logger.info(
        `[a2a-admin] client disabled client_id=${req.params.id} revokedDelegations=${revokedDelegations} cancelledJobs=${cancelledJobs} by=${admin.id}`,
      );
      res.json({ status: 'disabled', revokedDelegations, cancelledJobs });
    } catch (err) {
      logger.error(`[a2a-admin] disable client failed: ${err}`);
      res.status(500).json({ error: 'internal' });
    }
  });

  return router;
}
