import type { Hono } from "hono";
import { z } from "zod";
import { WsBridge } from "../ws-bridge.js";
import { parseBody } from "../validation.js";
import { notFound, ErrorCode } from "../errors.js";

// ─── Zod Schemas ──────────────────────────────────────────────────

const imageSchema = z.object({
  media_type: z.string(),
  data: z.string(),
});

const queueAddSchema = z.object({
  content: z.string().min(1, "content is required").max(100_000),
  images: z.array(imageSchema).optional(),
});

const queueReorderSchema = z.object({
  orderedIds: z.array(z.string()).min(1),
});

const queueEditSchema = z.object({
  content: z.string().min(1, "content is required").max(100_000),
  images: z.array(imageSchema).optional(),
});

// ─── Dependencies ─────────────────────────────────────────────────

export interface QueueRouteDeps {
  wsBridge: WsBridge;
}

// ─── Routes ───────────────────────────────────────────────────────

export function registerQueueRoutes(api: Hono, deps: QueueRouteDeps): void {
  const { wsBridge } = deps;

  // ─── Get queue state ────────────────────────────────────────────

  api.get("/sessions/:id/queue", (c) => {
    const id = c.req.param("id");
    const state = wsBridge.getQueueState(id);
    if (!state) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);
    return c.json(state);
  });

  // ─── Add message to queue ──────────────────────────────────────

  api.post("/sessions/:id/queue", async (c) => {
    const id = c.req.param("id");
    const parsed = await parseBody(c, queueAddSchema);
    if (!parsed.success) return parsed.response;

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    const added = wsBridge.addToQueue(session, parsed.data.content, parsed.data.images);
    if (!added) {
      return c.json(
        { error: `Queue is full (max ${WsBridge.QUEUE_CAP} messages)` },
        400,
      );
    }

    return c.json({ ok: true, queue: session.messageQueue });
  });

  // ─── Remove single message from queue ──────────────────────────

  api.delete("/sessions/:id/queue/:msgId", (c) => {
    const id = c.req.param("id");
    const msgId = c.req.param("msgId");

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    const removed = wsBridge.removeFromQueue(session, msgId);
    if (!removed) {
      return c.json({ error: "Message not found in queue" }, 404);
    }

    return c.json({ ok: true, queue: session.messageQueue });
  });

  // ─── Clear queue ───────────────────────────────────────────────

  api.post("/sessions/:id/queue/clear", (c) => {
    const id = c.req.param("id");

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    wsBridge.clearQueue(session);
    return c.json({ ok: true });
  });

  // ─── Resume queue ─────────────────────────────────────────────

  api.post("/sessions/:id/queue/resume", (c) => {
    const id = c.req.param("id");

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    wsBridge.resumeQueue(session);
    return c.json({ ok: true });
  });

  // ─── Reorder queue ────────────────────────────────────────────

  api.post("/sessions/:id/queue/reorder", async (c) => {
    const id = c.req.param("id");
    const parsed = await parseBody(c, queueReorderSchema);
    if (!parsed.success) return parsed.response;

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    const ok = wsBridge.reorderQueue(session, parsed.data.orderedIds);
    if (!ok) {
      return c.json(
        { error: "invalid orderedIds — must contain all current queue IDs" },
        400,
      );
    }

    return c.json({ ok: true, queue: session.messageQueue });
  });

  // ─── Edit queue item ──────────────────────────────────────────

  api.patch("/sessions/:id/queue/:msgId", async (c) => {
    const id = c.req.param("id");
    const msgId = c.req.param("msgId");
    const parsed = await parseBody(c, queueEditSchema);
    if (!parsed.success) return parsed.response;

    const session = wsBridge.sessionManager.getSession(id);
    if (!session) throw notFound("Session not found", ErrorCode.SESSION_NOT_FOUND);

    const ok = wsBridge.editQueueItem(session, msgId, parsed.data.content, parsed.data.images);
    if (!ok) {
      return c.json({ error: "Message not found in queue" }, 404);
    }

    return c.json({ ok: true, queue: session.messageQueue });
  });
}
