import { createAiClient, isAiConfigured, loggedAiCall } from "../ai-client.js";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { logger } from "../lib/logger.js";
import { managerProcedure } from "../trpc.js";

export const DEFAULT_SUMMARY_PROMPT = `You are writing a short professional profile for an internal resource planning tool.

Artist profile:
- Role: {role}
- Chapter: {chapter}
- Main skills: {mainSkills}
- Top skills: {topSkills}

Write a 2–3 sentence professional bio. Be specific, use skill names. No fluff.`;

type SkillRow = {
  skill: string;
  category?: string;
  proficiency: number;
  isMainSkill?: boolean;
};

export const resourceAiSummaryProcedures = {
  generateAiSummary: managerProcedure
    .input(z.object({ resourceId: z.string() }))
    .mutation(async ({ ctx, input }) => {
      const [resource, settings] = await Promise.all([
        findUniqueOrThrow(
          ctx.db.resource.findUnique({
            where: { id: input.resourceId },
            include: { areaRole: { select: { name: true } } },
          }),
          "Resource",
        ),
        ctx.db.systemSettings.findUnique({ where: { id: "singleton" } }),
      ]);

      if (!isAiConfigured(settings)) {
        throw new TRPCError({
          code: "PRECONDITION_FAILED",
          message: "AI is not configured. Please set credentials in Admin → Settings.",
        });
      }

      const skills = (resource.skills as unknown as SkillRow[]) ?? [];
      const mainSkills = skills.filter((skill) => skill.isMainSkill).map((skill) => skill.skill);
      const top10 = [...skills]
        .sort((left, right) => right.proficiency - left.proficiency)
        .slice(0, 10)
        .map((skill) => `${skill.skill} (${skill.proficiency}/5)`);

      const vars = {
        role: resource.areaRole?.name ?? "Not specified",
        chapter: resource.chapter ?? "Not specified",
        mainSkills: mainSkills.length > 0 ? mainSkills.join(", ") : "Not specified",
        topSkills: top10.join(", "),
      };

      const templateStr = settings!.aiSummaryPrompt ?? DEFAULT_SUMMARY_PROMPT;
      const prompt = templateStr
        .replace("{role}", vars.role)
        .replace("{chapter}", vars.chapter)
        .replace("{mainSkills}", vars.mainSkills)
        .replace("{topSkills}", vars.topSkills);

      const client = createAiClient(settings!);
      const model = settings!.azureOpenAiDeployment!;
      const maxTokens = settings!.aiMaxCompletionTokens ?? 300;
      const temperature = settings!.aiTemperature ?? 1;
      const provider = settings!.aiProvider ?? "openai";

      async function callChatCompletions(withTemperature: boolean) {
        return loggedAiCall(provider, model, prompt.length, () =>
          client.chat.completions.create({
            messages: [{ role: "user", content: prompt }],
            max_completion_tokens: maxTokens,
            model,
            ...(withTemperature && temperature !== 1 ? { temperature } : {}),
          }),
        );
      }

      let summary = "";
      try {
        let completion;
        try {
          completion = await callChatCompletions(true);
          logger.debug(
            {
              provider,
              model,
              choiceCount: completion.choices?.length ?? 0,
            },
            "AI summary chat completion succeeded",
          );
        } catch (tempErr) {
          const status = (tempErr as { status?: number }).status;
          const msg = (tempErr as Error).message ?? "";
          if (status === 400 && msg.includes("temperature")) {
            logger.info(
              { provider, model, status },
              "Retrying AI summary generation without temperature override",
            );
            completion = await callChatCompletions(false);
          } else if (status === 404) {
            logger.info(
              { provider, model, status },
              "Falling back to AI responses API for summary generation",
            );
            const resp = await client.responses.create({ model, input: prompt, max_output_tokens: maxTokens });
            logger.debug(
              {
                provider,
                model,
                summaryLength: resp.output_text?.trim().length ?? 0,
              },
              "AI summary responses API call succeeded",
            );
            summary = resp.output_text?.trim() ?? "";
            completion = null;
          } else {
            throw tempErr;
          }
        }
        if (completion) {
          summary = completion.choices[0]?.message?.content?.trim() ?? "";
        }
      } catch (error) {
        throw error;
      }

      await ctx.db.resource.update({
        where: { id: input.resourceId },
        data: { aiSummary: summary, aiSummaryUpdatedAt: new Date() },
      });

      return { summary };
    }),
};
