import { logger } from "@infra/logger";
import type { Job, JobSearchProfile } from "@shared/types";
import { LlmService } from "./llm/service";
import type { JsonSchemaDefinition } from "./llm/types";
import { resolveLlmModel } from "./modelSelection";
import { sanitizeProfileForPrompt } from "./scorer";

const COVER_LETTER_SCHEMA: JsonSchemaDefinition = {
  name: "cover_letter",
  schema: {
    type: "object",
    properties: {
      coverLetter: {
        type: "string",
        description:
          "Complete, ready-to-send cover letter (plain text, professional formatting with line breaks)",
      },
    },
    required: ["coverLetter"],
    additionalProperties: false,
  },
};

interface CoverLetterResponse {
  coverLetter: string;
}

function buildCoverLetterPrompt(
  job: Job,
  resumeProfile: Record<string, unknown>,
  searchProfile: JobSearchProfile | null,
): string {
  const parts: string[] = [];

  parts.push(
    "Write a professional, compelling cover letter for this job application.",
  );
  parts.push("");
  parts.push("RULES:");
  parts.push("- Keep it concise: 3-4 paragraphs, under 400 words");
  parts.push(
    "- Lead with what makes the candidate a strong fit for THIS specific role",
  );
  parts.push(
    "- Reference specific requirements from the job description and match them to candidate experience",
  );
  parts.push(
    "- Be genuine and enthusiastic without being generic or sycophantic",
  );
  parts.push("- Use a professional but personable tone");
  parts.push("- Do NOT include placeholder text like [Your Name] or [Date]");
  parts.push(
    "- Do NOT make up experience or skills the candidate doesn't have",
  );
  parts.push(
    "- End with a strong closing that expresses interest in next steps",
  );
  parts.push("");

  parts.push("=== JOB DETAILS ===");
  parts.push(`Title: ${job.title}`);
  parts.push(`Company: ${job.employer}`);
  if (job.location) parts.push(`Location: ${job.location}`);
  if (job.jobDescription) {
    const desc =
      job.jobDescription.length > 3000
        ? `${job.jobDescription.slice(0, 3000)}...`
        : job.jobDescription;
    parts.push(`Description:\n${desc}`);
  }

  parts.push("");
  parts.push("=== CANDIDATE RESUME ===");
  parts.push(JSON.stringify(resumeProfile, null, 2));

  if (searchProfile) {
    parts.push("");
    parts.push("=== CANDIDATE PREFERENCES ===");
    if (searchProfile.aboutMe) {
      parts.push(`About: ${searchProfile.aboutMe}`);
    }
    if (searchProfile.targetRoles.length > 0) {
      parts.push(`Target roles: ${searchProfile.targetRoles.join(", ")}`);
    }
    if (searchProfile.mustHaveSkills.length > 0) {
      parts.push(
        `Key skills to highlight: ${searchProfile.mustHaveSkills.join(", ")}`,
      );
    }
  }

  return parts.join("\n");
}

export async function generateCoverLetter(
  job: Job,
  resumeProfile: Record<string, unknown>,
  searchProfile: JobSearchProfile | null,
): Promise<{ coverLetter: string }> {
  const model = await resolveLlmModel("scoring");

  const prompt = buildCoverLetterPrompt(
    job,
    sanitizeProfileForPrompt(resumeProfile),
    searchProfile,
  );

  const llm = new LlmService();
  const result = await llm.callJson<CoverLetterResponse>({
    model,
    messages: [{ role: "user", content: prompt }],
    jsonSchema: COVER_LETTER_SCHEMA,
    maxRetries: 1,
    jobId: job.id,
  });

  if (!result.success) {
    logger.error("Cover letter generation failed", {
      jobId: job.id,
      error: result.error,
    });
    throw new Error(`Cover letter generation failed: ${result.error}`);
  }

  const letter = result.data.coverLetter;
  if (!letter || typeof letter !== "string") {
    throw new Error("LLM returned empty cover letter");
  }

  return { coverLetter: letter };
}
