import type { FastifyInstance } from 'fastify';
import { BadRequestError, ForbiddenError, UnauthorizedError } from '../../lib/errors.js';
import { CreateIPRuleSchema } from './types.js';
import type { IPRuleDoc } from './types.js';
import * as repo from './repository.js';

const DEFAULT_PRODUCT_ID = 'lysnrai';

export async function ipRuleRoutes(app: FastifyInstance) {
  function requireAdmin(req: import('fastify').FastifyRequest): string {
    const role = req.jwtPayload?.role;
    if (!role || !['super_admin', 'admin'].includes(role)) {
      throw new ForbiddenError('Admin access required');
    }
    const sub = req.jwtPayload?.sub;
    if (!sub) throw new UnauthorizedError('Missing sub in token');
    return sub;
  }

  // List all IP rules
  app.get('/ratelimit/ip-rules', async req => {
    requireAdmin(req);
    return repo.listRules(DEFAULT_PRODUCT_ID);
  });

  // Create an IP rule
  app.post('/ratelimit/ip-rules', async (req, reply) => {
    const adminId = requireAdmin(req);
    const parsed = CreateIPRuleSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const doc: IPRuleDoc = {
      id: `ipr_${crypto.randomUUID()}`,
      productId: DEFAULT_PRODUCT_ID,
      ip: parsed.data.ip,
      action: parsed.data.action,
      reason: parsed.data.reason,
      createdBy: adminId,
      createdAt: new Date().toISOString(),
      expiresAt: parsed.data.expiresAt,
    };

    const created = await repo.createRule(doc);
    req.log.info(
      { ruleId: created.id, ip: created.ip, action: created.action },
      `[ip-rules] IP rule created: ${created.action} ${created.ip}`
    );

    return reply.status(201).send(created);
  });

  // Delete an IP rule
  app.delete('/ratelimit/ip-rules/:id', async req => {
    requireAdmin(req);
    const { id } = req.params as { id: string };
    const deleted = await repo.deleteRule(id, DEFAULT_PRODUCT_ID);
    if (!deleted) throw new BadRequestError('IP rule not found');
    return { success: true };
  });

  // Check if an IP is allowed/denied (utility endpoint)
  app.get('/ratelimit/check-ip/:ip', async req => {
    requireAdmin(req);
    const { ip } = req.params as { ip: string };
    const result = await repo.checkIP(ip, DEFAULT_PRODUCT_ID);
    return { ip, action: result, hasRule: result !== null };
  });
}
