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

import { noteSendPayloadSchema } from '@/entities/noteSendItem';
import { enqueueNoteChange, getINoteStats, queryNotes } from '@/features/inotes';

// Auth follow-up: deviceId is currently passed as a query/body param. Once
// SSO session resolution lands, derive it from the session.
const deviceIdQuery = z.string().min(1);
const optionalDeviceIdQuery = z.string().min(1).optional();
const limitParam = z.coerce.number().int().positive().max(1000).default(200);

const createSchema = noteSendPayloadSchema.extend({
  deviceId: z.string().min(1),
});
const updateSchema = noteSendPayloadSchema.extend({
  deviceId: z.string().min(1),
});

function errorResponse(c: Context, err: unknown, fallback: string) {
  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: 'enqueue_error', message: err instanceof Error ? err.message : fallback },
    },
    500,
  );
}

export const notesMyRouter = new Hono()
  .get('/stats', async (c) => {
    try {
      const deviceId = deviceIdQuery.parse(c.req.query('deviceId'));
      return c.json({ success: true, data: await getINoteStats(deviceId) });
    } catch (err) {
      return errorResponse(c, err, 'failed to load note stats');
    }
  })
  .get('/', async (c) => {
    try {
      const deviceId = optionalDeviceIdQuery.parse(c.req.query('deviceId'));
      const folder = z.string().optional().parse(c.req.query('folder'));
      const limit = limitParam.parse(c.req.query('limit') ?? '200');
      const offset = z.coerce
        .number()
        .int()
        .nonnegative()
        .default(0)
        .parse(c.req.query('offset') ?? '0');
      const notes = await queryNotes({ deviceId, folder, limit, offset });
      return c.json({ success: true, data: { notes } });
    } catch (err) {
      return errorResponse(c, err, 'failed to list notes');
    }
  })
  .post('/', async (c) => {
    try {
      const body = createSchema.parse(await c.req.json());
      const { deviceId, ...payload } = body;
      const { id } = await enqueueNoteChange({ deviceId, action: 'create_note', payload });
      return c.json({ success: true, data: { sendQueueId: id } });
    } catch (err) {
      return errorResponse(c, err, 'failed to enqueue create_note');
    }
  })
  .put('/:id', async (c) => {
    try {
      const noteIdentifier = c.req.param('id');
      const body = updateSchema.parse(await c.req.json());
      const { deviceId, ...rest } = body;
      const payload = { ...rest, noteIdentifier };
      const { id } = await enqueueNoteChange({ deviceId, action: 'update_note', payload });
      return c.json({ success: true, data: { sendQueueId: id } });
    } catch (err) {
      return errorResponse(c, err, 'failed to enqueue update_note');
    }
  })
  .delete('/:id', async (c) => {
    try {
      const noteIdentifier = c.req.param('id');
      const deviceId = deviceIdQuery.parse(c.req.query('deviceId'));
      const { id } = await enqueueNoteChange({
        deviceId,
        action: 'delete_note',
        payload: { noteIdentifier },
      });
      return c.json({ success: true, data: { sendQueueId: id } });
    } catch (err) {
      return errorResponse(c, err, 'failed to enqueue delete_note');
    }
  });
