import type { OnboardingInput, Opportunity } from "@/lib/types";
import type { SamOpportunityRecord } from "@/lib/sam-gov/types";

function clamp(n: number, min = 0, max = 100) {
  return Math.max(min, Math.min(max, Math.round(n)));
}

function formatAgency(fullParentPathName?: string): string {
  if (!fullParentPathName) return "Federal agency";
  const parts = fullParentPathName.split(".").filter(Boolean);
  return parts[0]?.replace(/DEPT OF /i, "") ?? fullParentPathName;
}

function formatPlace(record: SamOpportunityRecord): string {
  const city = record.placeOfPerformance?.city?.name;
  const state = record.placeOfPerformance?.state?.code ?? record.placeOfPerformance?.state?.name;
  const country = record.placeOfPerformance?.country?.code;
  if (city && state) return `${city}, ${state}`;
  if (state) return state;
  if (country && country !== "USA") return country;
  return "United States";
}

function estimateContractValue(record: SamOpportunityRecord): number {
  const awardAmount = record.award?.amount;
  if (awardAmount) {
    const parsed = typeof awardAmount === "number" ? awardAmount : parseFloat(String(awardAmount));
    if (!Number.isNaN(parsed) && parsed > 0) return Math.round(parsed);
  }
  // Heuristic defaults by notice type when no award data
  const type = (record.type ?? "").toLowerCase();
  if (type.includes("combined") || type.includes("solicitation")) return 250000;
  if (type.includes("presolicitation") || type.includes("sources sought")) return 150000;
  return 100000;
}

function urgencyFromDeadline(deadline?: string): number {
  if (!deadline) return 45;
  const ms = new Date(deadline).getTime() - Date.now();
  const days = ms / (1000 * 60 * 60 * 24);
  if (days < 0) return 20;
  if (days <= 7) return 95;
  if (days <= 14) return 85;
  if (days <= 30) return 70;
  if (days <= 60) return 55;
  return 40;
}

function confidenceScore(record: SamOpportunityRecord, naicsMatched: string, stateMatched: boolean): number {
  let score = 72;
  if (record.naicsCode === naicsMatched || record.naicsCodes?.includes(naicsMatched)) score += 10;
  if (stateMatched) score += 8;
  if (record.active === "Yes") score += 5;
  if (record.responseDeadLine) score += 5;
  return clamp(score);
}

function primaryContact(record: SamOpportunityRecord) {
  return record.pointOfContact?.find((c) => c.type === "primary") ?? record.pointOfContact?.[0];
}

function buildRecommendedAction(record: SamOpportunityRecord): string {
  const deadline = record.responseDeadLine
    ? ` before ${new Date(record.responseDeadLine).toLocaleDateString()}`
    : "";
  if (record.type?.toLowerCase().includes("sources sought")) {
    return `Submit capability statement and register in SAM.gov${deadline}`;
  }
  return `Review solicitation ${record.solicitationNumber ?? record.noticeId} and prepare proposal${deadline}`;
}

function buildOutreach(record: SamOpportunityRecord, input: OnboardingInput): string {
  const contact = primaryContact(record);
  const agency = formatAgency(record.fullParentPathName);
  if (contact?.email) {
    return `Subject: Interest in ${record.solicitationNumber ?? "solicitation"}\n\nHi ${contact.fullName ?? "Contracting Officer"},\n\n${input.businessName} specializes in ${input.productsServices.toLowerCase()} and is interested in ${record.title}.\n\nWe are registered in SAM.gov and serve ${input.location}. Could we schedule a brief call to discuss requirements?\n\n— ${input.businessName}`;
  }
  return `Federal contract: ${record.title} (${agency}). View full solicitation on SAM.gov and align your capability statement to NAICS ${record.naicsCode ?? "match"}.`;
}

export function samRecordToOpportunity(
  record: SamOpportunityRecord,
  input: OnboardingInput,
  naicsMatched: string,
  stateCode?: string,
): Opportunity {
  const agency = formatAgency(record.fullParentPathName);
  const place = formatPlace(record);
  const stateMatched = Boolean(
    stateCode &&
      (record.placeOfPerformance?.state?.code?.includes(stateCode) ||
        record.placeOfPerformance?.state?.name?.toUpperCase().includes(stateCode)),
  );

  const setAside = record.typeOfSetAsideDescription ?? record.setAside;
  const descriptionParts = [
    `${record.type ?? "Notice"} posted ${record.postedDate ?? "recently"}.`,
    `Agency: ${agency}.`,
    `Place of performance: ${place}.`,
    record.naicsCode ? `NAICS ${record.naicsCode}.` : "",
    setAside ? `Set-aside: ${setAside}.` : "",
    record.responseDeadLine
      ? `Response deadline: ${new Date(record.responseDeadLine).toLocaleString()}.`
      : "",
  ].filter(Boolean);

  return {
    id: `sam-${record.noticeId}`,
    samNoticeId: record.noticeId,
    title: record.title,
    type: "government_contract",
    description: descriptionParts.join(" "),
    source: `SAM.gov · NAICS ${record.naicsCode ?? naicsMatched} · ${agency}`,
    estimatedValue: estimateContractValue(record),
    confidenceScore: confidenceScore(record, naicsMatched, stateMatched),
    urgencyScore: urgencyFromDeadline(record.responseDeadLine),
    recommendedAction: buildRecommendedAction(record),
    aiOutreach: buildOutreach(record, input),
    status: "new",
    externalUrl: record.uiLink ?? `https://sam.gov/opp/${record.noticeId}/view`,
    responseDeadline: record.responseDeadLine,
  };
}

export function mergeSamOpportunities(
  existing: Opportunity[],
  incoming: Opportunity[],
): Opportunity[] {
  const existingSamIds = new Set(
    existing.filter((o) => o.samNoticeId).map((o) => o.samNoticeId),
  );
  const merged = [...existing];
  for (const opp of incoming) {
    if (opp.samNoticeId && existingSamIds.has(opp.samNoticeId)) continue;
    merged.push(opp);
  }
  return merged;
}
