import { Hono } from 'hono';
import { z } from 'zod';

import { listDueReplies, claimForSend, recordResult } from '@/features/outbox';

const limitSchema = z.coerce.number().int().positive().max(100).default(25);
const resultSchema = z.object({
  status: z.enum(['sent', 'delivered', 'failed']),
  channelUsed: z.enum(['imessage', 'sms']).nullish(),
  error: z.string().max(2000).nullish(),
});

export const outboxClientRouter = new Hono()
  // Mac polls for due items (queued + not_before <= now), hottest first.
  .get('/due', async (c) => {
    const deviceId = c.get('deviceId');
    const limit = limitSchema.parse(c.req.query('limit') ?? '25');
    const items = await listDueReplies(deviceId, limit);
    return c.json({ success: true, data: { items } });
  })
  // Claim an item before sending (queued → sending, attempts++).
  // Scoped to the authenticated device — a token can only claim its own rows.
  .post('/:id/sending', async (c) => {
    const id = z.string().uuid().parse(c.req.param('id'));
    const ok = await claimForSend(id, c.get('deviceId'));
    if (!ok) return c.json({ success: false, error: { code: 'not_found' } }, 404);
    return c.json({ success: true, data: { id, status: 'sending' } });
  })
  // Report true delivery result (verified against chat.db on the Mac).
  .post('/:id/result', async (c) => {
    const id = z.string().uuid().parse(c.req.param('id'));
    const parsed = resultSchema.safeParse(await c.req.json().catch(() => null));
    if (!parsed.success) {
      return c.json({ success: false, error: { code: 'validation_error', issues: parsed.error.flatten() } }, 400);
    }
    const ok = await recordResult({ id, deviceId: c.get('deviceId'), ...parsed.data });
    if (!ok) return c.json({ success: false, error: { code: 'not_found' } }, 404);
    return c.json({ success: true, data: { id, status: parsed.data.status } });
  });
