import type { FastifyInstance } from 'fastify';
import { intakeService } from '../services/intake.service.js';
import { requireMajWpAuth } from '../middleware/auth.js';
import { claimSchema, createdSchema, statusUpdateSchema } from '../schemas.js';

export async function majWpRoutes(app: FastifyInstance): Promise<void> {
  app.addHook('preHandler', requireMajWpAuth);

  app.get('/api/v1/tickets/ready', async (request) => {
    const limit = Math.min(parseInt((request.query as { limit?: string }).limit ?? '50', 10), 100);
    const items = intakeService.listReady(limit);
    return {
      items: items.map(publicItem),
      count: items.length,
    };
  });

  app.post('/api/v1/intake/:id/claim', async (request, reply) => {
    const { id } = request.params as { id: string };
    const body = claimSchema.parse(request.body ?? {});
    const result = intakeService.claim(id, body.consumer_id);

    if (!result.ok) {
      const code = result.reason === 'not_found' ? 404 : 409;
      return reply.code(code).send({
        error: result.reason,
        item: result.item ? publicItem(result.item) : undefined,
      });
    }

    return {
      item: publicItem(result.item),
      claim_token: result.claim_token,
      lease_seconds: parseInt(process.env.CLAIM_LEASE_SECONDS ?? '300', 10),
    };
  });

  app.post('/api/v1/intake/claim-next', async (request, reply) => {
    const body = claimSchema.parse(request.body ?? {});
    const result = intakeService.claimNextReady(body.consumer_id);

    if (!result.ok) {
      return reply.code(404).send({ error: result.reason });
    }

    return {
      item: publicItem(result.item),
      claim_token: result.claim_token,
      lease_seconds: parseInt(process.env.CLAIM_LEASE_SECONDS ?? '300', 10),
    };
  });

  app.post('/api/v1/intake/:id/created', async (request, reply) => {
    const { id } = request.params as { id: string };
    const body = createdSchema.parse(request.body);
    const item = intakeService.acknowledgeCreated(id, body);

    if (!item) {
      return reply.code(404).send({ error: 'not_found_or_invalid_claim' });
    }

    return { item: publicItem(item), idempotent: item.maj_wp_ticket_id === body.maj_wp_ticket_id };
  });

  app.post('/api/v1/intake/:id/status', async (request, reply) => {
    const { id } = request.params as { id: string };
    const body = statusUpdateSchema.parse(request.body);
    const item = intakeService.updateRemoteStatus(id, body);

    if (!item) return reply.code(404).send({ error: 'not_found' });
    return { item: publicItem(item) };
  });

  app.get('/api/v1/intake/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const item = intakeService.getById(id);
    if (!item) return reply.code(404).send({ error: 'not_found' });
    return publicItem(item);
  });
}

function publicItem(item: ReturnType<typeof intakeService.getById> extends infer T ? NonNullable<T> : never) {
  return {
    id: item.id,
    source_type: item.source_type,
    source_url: item.source_url,
    sender_name: item.sender_name,
    sender_email: item.sender_email,
    client_project: item.client_project,
    title: item.title,
    body: item.body,
    metadata: item.metadata,
    attachments: item.attachments,
    received_at: item.received_at,
    ingested_at: item.ingested_at,
    decision: item.decision,
    status: item.status,
    maj_wp_ticket_id: item.maj_wp_ticket_id,
    remote_status: item.remote_status,
    remote_message: item.remote_message,
    last_sync_at: item.last_sync_at,
    error: item.error,
  };
}
