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

import {
  getICalStats,
  ingestCalendars,
  ingestEvents,
  listPendingCalendarSends,
  markCalendarSendResult,
} from '@/features/ical';
import { withSyncHistory } from '@/shared/sync-history';

const calendarSchema = z.object({
  calendarIdentifier: z.string().min(1),
  title: z.string().min(1),
  calendarType: z.string(),
  color: z.string(),
  source: z.string(),
});

const syncCalendarsSchema = z.object({
  calendars: z.array(calendarSchema),
});

const eventSchema = z.object({
  eventIdentifier: z.string().min(1),
  calendarIdentifier: z.string(),
  title: z.string(),
  notes: z.string().nullish(),
  location: z.string().nullish(),
  url: z.string().nullish(),
  isAllDay: z.boolean(),
  startDate: z.string(),
  endDate: z.string(),
  createdAt: z.string().nullish(),
  modifiedAt: z.string().nullish(),
  status: z.string(),
  availability: z.string(),
  isDetached: z.boolean(),
  hasAlarms: z.boolean(),
  hasRecurrenceRules: z.boolean(),
  recurrenceRule: z.string().nullish(),
  organizerEmail: z.string().nullish(),
  organizerName: z.string().nullish(),
  attendeeCount: z.number(),
});

const syncEventsSchema = z.object({
  events: z.array(eventSchema),
});

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

export const icalClientRouter = new Hono()
  .get('/stats', (c) => {
    const stats = getICalStats();
    return c.json({ success: true, data: stats });
  })
  .post('/calendars', async (c) => {
    const deviceId = c.get('deviceId');
    const payload = syncCalendarsSchema.parse(await c.req.json());
    const result = await withSyncHistory(deviceId, 'calendar', () => ingestCalendars(deviceId, payload));
    return c.json({ success: true, data: result });
  })
  .post('/events', async (c) => {
    const deviceId = c.get('deviceId');
    const payload = syncEventsSchema.parse(await c.req.json());
    const result = await withSyncHistory(deviceId, 'calendar', () => ingestEvents(deviceId, payload));
    return c.json({ success: true, data: result });
  })
  .get('/send-queue/pending', async (c) => {
    try {
      const deviceId = c.get('deviceId');
      const items = await listPendingCalendarSends(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 calendar 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 markCalendarSendResult({ 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 calendar send result',
          },
        },
        500,
      );
    }
  });
