import type { FastifyInstance } from "fastify";
import type {
  BibliographyRequest,
  BibliographyResponse,
  DeleteLibrarySourceRequest,
  ImportCitationRequest,
  ImportCitationResponse,
  ImportEnwRequest,
  ImportEnwResponse,
  LlmSupportClaimRequest,
  LlmSupportClaimResponse,
  ReferenceLibraryResponse,
  SupportClaimRequest,
  SupportClaimResponse
} from "@skola/shared";

import { getConfig } from "../config.js";
import {
  deleteCitationFromLibrary,
  getReferenceLibrary,
  importCitation,
  importEnwCitation
} from "../services/citation-library.js";
import { searchAcademicSources } from "../services/academic-search.js";
import { formatBibliography } from "../services/bibliography-generator.js";
import { runSupportClaimWithLLM } from "../services/ai-service.js";
import { requireAuthToken } from "../services/auth-store.js";

export async function registerReferenceRoutes(app: FastifyInstance): Promise<void> {
  const config = getConfig();

  app.get<{ Reply: ReferenceLibraryResponse }>("/v1/references/library", async () => getReferenceLibrary());

  // Legacy ENW import endpoint (backwards compat)
  app.post<{ Body: ImportEnwRequest; Reply: ImportEnwResponse }>(
    "/v1/references/import-enw",
    async (request) => {
      const fileName = request.body.fileName.trim();
      const content = request.body.content.trim();

      if (!fileName || !content) {
        throw new Error("An ENW file name and content are required for citation import.");
      }

      return importEnwCitation(fileName, content);
    }
  );

  // Unified citation import endpoint
  app.post<{ Body: ImportCitationRequest; Reply: ImportCitationResponse }>(
    "/v1/references/import",
    async (request) => {
      const { fileName, content, format } = request.body;
      if (!fileName || !content || !format)
        throw new Error("fileName, content, and format are required.");
      return importCitation(fileName.trim(), content.trim(), format);
    }
  );

  app.post<{ Body: DeleteLibrarySourceRequest; Reply: ReferenceLibraryResponse }>(
    "/v1/references/library/delete",
    async (request) => {
      if (!request.body.decimalId) {
        throw new Error("A decimal source id is required to delete a stored citation.");
      }

      return deleteCitationFromLibrary(request.body.decimalId);
    }
  );

  app.post<{ Body: SupportClaimRequest; Reply: SupportClaimResponse }>(
    "/v1/references/support-claim",
    async (request) => {
      const claimText = request.body.claimText.trim();

      if (!claimText) {
        return { claimText: "", intent: request.body.intent, results: [] };
      }

      try {
        const results = await searchAcademicSources(
          claimText,
          request.body.intent,
          request.body.maxResults || 5,
          {
            crossrefMailto: config.crossrefMailto,
            openalexEmail: config.openalexEmail
          }
        );
        return { claimText, intent: request.body.intent, results };
      } catch {
        return {
          claimText,
          intent: request.body.intent,
          warning: "Academic search unavailable.",
          results: []
        };
      }
    }
  );

  app.post<{
    Body: LlmSupportClaimRequest;
    Headers: { authorization?: string };
    Reply: LlmSupportClaimResponse;
  }>(
    "/v1/references/support-claim/llm",
    async (request) => {
      await requireAuthToken(request.headers.authorization);

      const claimText = request.body.claimText.trim();
      if (!claimText) {
        throw new Error("Selected claim text is required.");
      }

      return runSupportClaimWithLLM(
        {
          ...request.body,
          claimText
        },
        config.llm
      );
    }
  );

  app.post<{ Body: BibliographyRequest; Reply: BibliographyResponse }>(
    "/v1/references/bibliography",
    async (request) => {
      return formatBibliography(request.body.sources, request.body.style);
    }
  );
}
