import type { Hono } from "hono";
import { z } from "zod";
import type { SessionStore } from "../session-store.js";
import * as sessionNames from "../session-names.js";
import { createLogger } from "../logger.js";

const log = createLogger("history-routes");

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

const historyQuerySchema = z.object({
  search: z.string().max(500).optional(),
  sessionId: z.string().max(200).optional(),
  limit: z.coerce.number().int().min(1).max(500).optional().default(100),
  offset: z.coerce.number().int().min(0).optional().default(0),
  includeArchived: z.coerce.boolean().optional().default(false),
});

// ─── Types ────────────────────────────────────────────────────────

export interface HistoryPromptItem {
  id: string;
  sessionId: string;
  sessionName: string;
  content: string;
  timestamp: number;
}

export interface HistoryPromptsResponse {
  prompts: HistoryPromptItem[];
  total: number;
  limit: number;
  offset: number;
}

export interface SessionPromptsResponse {
  prompts: HistoryPromptItem[];
  total: number;
}

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

export function registerHistoryRoutes(api: Hono, sessionStore: SessionStore): void {
  api.get("/history/prompts", async (c) => {
    try {
      const raw = {
        search: c.req.query("search"),
        sessionId: c.req.query("sessionId"),
        limit: c.req.query("limit"),
        offset: c.req.query("offset"),
        includeArchived: c.req.query("includeArchived"),
      };
      const parsed = historyQuerySchema.safeParse(raw);
      if (!parsed.success) {
        return c.json({ error: "Invalid query parameters", details: parsed.error.flatten() }, 400);
      }
      const { search, sessionId, limit, offset, includeArchived } = parsed.data;

      const allSessions = await sessionStore.loadAll();

      const prompts: HistoryPromptItem[] = [];

      for (const session of allSessions) {
        if (session.archived && !includeArchived) continue;
        if (sessionId && session.id !== sessionId) continue;

        for (const msg of session.messageHistory) {
          if (msg.type === "user_message") {
            const content = typeof msg.content === "string" ? msg.content : "";

            if (!content.trim()) continue;

            if (search && !content.toLowerCase().includes(search.toLowerCase())) continue;

            prompts.push({
              id: msg.id ?? `${session.id}-${msg.timestamp}`,
              sessionId: session.id,
              sessionName: sessionNames.getName(session.id) ?? "",
              content,
              timestamp: msg.timestamp ?? 0,
            });
          }
        }
      }

      prompts.sort((a, b) => b.timestamp - a.timestamp);

      const total = prompts.length;
      const paginated = prompts.slice(offset, offset + limit);

      return c.json({ prompts: paginated, total, limit, offset });
    } catch (err) {
      log.error({ err }, "Failed to fetch prompt history");
      return c.json({ error: "Failed to fetch prompt history" }, 500);
    }
  });

  api.get("/history/sessions/:sessionId/prompts", async (c) => {
    try {
      const targetSessionId = c.req.param("sessionId");
      const session = sessionStore.load(targetSessionId);

      if (!session) {
        return c.json({ error: "Session not found" }, 404);
      }

      const prompts: HistoryPromptItem[] = [];
      for (const msg of session.messageHistory) {
        if (msg.type === "user_message") {
          const content = typeof msg.content === "string" ? msg.content : "";
          if (!content.trim()) continue;

          prompts.push({
            id: msg.id ?? `${session.id}-${msg.timestamp}`,
            sessionId: session.id,
            sessionName: sessionNames.getName(session.id) ?? "",
            content,
            timestamp: msg.timestamp ?? 0,
          });
        }
      }

      prompts.sort((a, b) => a.timestamp - b.timestamp);

      return c.json({ prompts, total: prompts.length });
    } catch (err) {
      log.error({ err, sessionId: c.req.param("sessionId") }, "Failed to fetch session prompts");
      return c.json({ error: "Failed to fetch session prompts" }, 500);
    }
  });
}
