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

import {
  getImailStats,
  ingestMail,
  listPendingMailSends,
  markMailSendResult,
} from '@/features/imail';
import { withSyncHistory } from '@/shared/sync-history';

const sendResultSchema = z.object({
  status: z.enum(['sent', 'failed']),
  error: z.string().optional(),
});

const emailAddressSchema = z.object({
  address: z.string().min(1),
  name: z.string().nullish(),
});

const emailSchema = z.object({
  messageId: z.string().min(1),
  threadId: z.string().nullish(),
  subject: z.string().nullish(),
  fromAddress: z.string().min(1),
  fromName: z.string().nullish(),
  to: z.array(emailAddressSchema).nullish(),
  cc: z.array(emailAddressSchema).nullish(),
  folder: z.string().default('INBOX'),
  direction: z.enum(['incoming', 'outgoing']),
  textBody: z.string().nullish(),
  htmlBody: z.string().nullish(),
  hasAttachments: z.boolean().nullish(),
  attachmentCount: z.number().nullish(),
  sentAt: z.string(),
  receivedAt: z.string().nullish(),
  isRead: z.boolean().nullish(),
});

const syncMailSchema = z.object({
  emails: z.array(emailSchema),
});

export const imailClientRouter = new Hono()
  .get('/stats', (c) => {
    const deviceId = c.get('deviceId');
    const stats = getImailStats(deviceId);
    return c.json({ success: true, data: stats });
  })
  .post('/sync', async (c) => {
    const deviceId = c.get('deviceId');
    const payload = syncMailSchema.parse(await c.req.json());
    const result = await withSyncHistory(deviceId, 'mail', () => ingestMail(deviceId, payload));
    return c.json({ success: true, data: result });
  })
  .get('/send-queue/pending', async (c) => {
    try {
      const deviceId = c.get('deviceId');
      const items = await listPendingMailSends(deviceId);
      return c.json({ success: true, data: { items } });
    } catch (err) {
      return c.json(
        {
          success: false,
          error: {
            code: 'send_queue_error',
            message: err instanceof Error ? err.message : 'failed to fetch pending mail sends',
          },
        },
        500,
      );
    }
  })
  .post('/send-queue/:id/result', async (c) => {
    try {
      const id = c.req.param('id');
      const body = sendResultSchema.parse(await c.req.json());
      await markMailSendResult({ id, status: body.status, error: body.error ?? null });
      return c.json({ success: true, data: {} });
    } catch (err) {
      if (err instanceof z.ZodError) {
        return c.json(
          {
            success: false,
            error: { code: 'validation_error', message: 'invalid request payload', issues: err.issues },
          },
          400,
        );
      }
      return c.json(
        {
          success: false,
          error: {
            code: 'send_queue_error',
            message: err instanceof Error ? err.message : 'failed to mark mail send result',
          },
        },
        500,
      );
    }
  });
