import type { FastifyInstance } from 'fastify';
import { extractAuth } from '../../lib/auth.js';
import { BadRequestError } from '../../lib/errors.js';
import { TriggerJobSchema, UpdateJobSchema } from './types.js';
import * as repo from './repository.js';
import { getJobHandler } from './registry.js';
import { executeJob } from './runner.js';

const DEFAULT_PRODUCT_ID = 'lysnrai';

export async function jobRoutes(app: FastifyInstance) {
  // List all job definitions
  app.get('/jobs', async req => {
    await extractAuth(req);
    return repo.listJobDefinitions(DEFAULT_PRODUCT_ID);
  });

  // Get a specific job definition
  app.get('/jobs/:id', async req => {
    await extractAuth(req);
    const { id } = req.params as { id: string };
    return repo.getJobDefinition(id, DEFAULT_PRODUCT_ID);
  });

  // Update job (enable/disable, change cron, etc.)
  app.put('/jobs/:id', async req => {
    await extractAuth(req);
    const { id } = req.params as { id: string };
    const parsed = UpdateJobSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }
    return repo.updateJobDefinition(id, DEFAULT_PRODUCT_ID, parsed.data);
  });

  // Manually trigger a job
  app.post('/jobs/trigger', async req => {
    await extractAuth(req);
    const parsed = TriggerJobSchema.safeParse(req.body);
    if (!parsed.success) {
      throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
    }

    const { jobName } = parsed.data;
    const handler = getJobHandler(jobName);
    if (!handler) {
      throw new BadRequestError(`No handler registered for job '${jobName}'`);
    }

    const def = await repo.getJobDefinition(`job_${jobName}`, DEFAULT_PRODUCT_ID);
    const run = await executeJob(def, 'manual', req.log);
    return run;
  });

  // List recent runs for a job
  app.get('/jobs/:name/runs', async req => {
    await extractAuth(req);
    const { name } = req.params as { name: string };
    const limit = parseInt((req.query as Record<string, string>).limit || '20', 10);
    return repo.listJobRuns(DEFAULT_PRODUCT_ID, name, Math.min(limit, 100));
  });
}
