import { api } from "./api";

// Mirrors the backend CvVariantSettings (the lens over the master career profile).
export type CvSectionSetting = {
  key: string;
  hidden?: boolean;
  title?: string;
  itemOrder?: string[];
  items?: string[];
  presentation?: "rows" | "grid" | "compact" | "bubble" | null;
  columns?: 1 | 2 | null;
};
export type CvItemOverride = { hidden?: boolean; title?: string; subtitle?: string; bullets?: string[] };
export type CvCustomSectionSetting = {
  key: string;
  title?: string;
  items: string[];
  hidden?: boolean;
  presetKey?: string | null;
  contentType?: "paragraphs" | "bullets" | "entries";
};
export type CvSkillGroupSetting = { name: string; items: string[] };

export type CvVariantSettings = {
  themeId: string;
  accentColor?: string | null;
  headingFont?: string | null;
  bodyFont?: string | null;
  density?: string | null;
  pageSize?: string | null;
  dateFormat?: string | null;
  language?: string | null;
  headline?: string | null;
  textColor?: string | null;
  mutedColor?: string | null;
  headingColor?: string | null;
  backgroundColor?: string | null;
  baseFontSizePt?: number | null;
  headingSizePt?: number | null;
  lineHeight?: number | null;
  pageMarginMm?: number | null;
  sectionGapMm?: number | null;
  entryGapMm?: number | null;
  headingStyle?: "caps-rule" | "underline" | "plain" | "bar" | null;
  headerStyle?: "plain" | "band" | "centered" | "kicker" | null;
  skillsStyle?: "tags" | "text" | "bullets" | "grouped" | null;
  skillGroups?: CvSkillGroupSetting[] | null;
  layout?: "single" | "sidebar-left" | "sidebar-right" | "header-band" | null;
  sidebarWidthMm?: number | null;
  sidebarSections?: string[] | null;
  showPhoto: boolean;
  showPageNumbers: boolean;
  showIcons: boolean;
  sections: CvSectionSetting[];
  overrides: Record<string, CvItemOverride>;
  customSections: CvCustomSectionSetting[];
};

export type CvTheme = {
  id: string;
  name: string;
  category: string;
  description: string;
  layout: string;
  accent: string;
  photoShape: string;
  supportsIcons: boolean;
  atsFriendly: boolean;
  requiresPro: boolean;
  available: boolean;
  swatches: string[];
  supportedSettings?: string[];
  pageMarginMm?: number;
};

// Master profile resolved to sections+entries (GET /api/cv/outline) — what the Content tab edits.
export type CvOutlineEntry = { key?: string; title?: string; subtitle?: string; meta?: string; bullets: string[]; tags: string[] };
export type CvOutlineSection = { key: string; title: string; kind: "bullets" | "tags" | "entries"; bullets: string[]; tags: string[]; entries: CvOutlineEntry[] };
export type CvOutline = { fullName: string; headline?: string; sections: CvOutlineSection[] };

export type CvVariantSummary = {
  id: number;
  name: string;
  themeId: string;
  language?: string | null;
  publicSlug: string;
  isPublic: boolean;
  version: number;
  jobApplicationId: number | null;
  jobTitle?: string | null;
  companyName?: string | null;
  updatedAtUtc: string;
};

export type CvVariant = {
  id: number;
  name: string;
  settings: CvVariantSettings;
  isPublic: boolean;
  publicSlug: string;
  version: number;
  jobApplicationId: number | null;
  updatedAtUtc: string;
};

export type CvVariantVersionInfo = { version: number; source: string; createdAtUtc: string; isCurrent: boolean };
export type CvRender = { themeId: string; html: string; suggestedFileName: string };

export const AI_ACTIONS: { key: string; label: string }[] = [
  { key: "improve", label: "Improve writing" },
  { key: "professional", label: "Professional tone" },
  { key: "shorten", label: "Shorten" },
  { key: "expand", label: "Expand" },
  { key: "grammar", label: "Fix grammar" },
  { key: "impact", label: "Add measurable impact" },
  { key: "ats", label: "ATS optimise" },
  { key: "bullets", label: "Generate bullets" },
  { key: "summary", label: "Generate summary" },
  { key: "rewrite", label: "Rewrite" },
  { key: "tailor", label: "Tailor to role" },
];

export const DEFAULT_SECTION_ORDER = [
  "summary", "experience", "education", "projects", "skills", "certifications", "languages", "awards",
  "publications", "organisations", "interests", "references",
];

export const SECTION_LABELS: Record<string, string> = {
  summary: "Professional Summary",
  experience: "Experience",
  education: "Education",
  projects: "Projects",
  skills: "Skills",
  certifications: "Certifications",
  languages: "Languages",
  interests: "Interests",
  awards: "Awards",
  publications: "Publications",
  organisations: "Organisations",
  references: "References",
};

export const CUSTOM_SECTION_PRESETS = [
  { key: "courses", title: "Courses", contentType: "entries" as const },
  { key: "volunteer", title: "Volunteer Experience", contentType: "entries" as const },
  { key: "additional-experience", title: "Additional Experience", contentType: "entries" as const },
  { key: "declaration", title: "Declaration", contentType: "paragraphs" as const },
] as const;

const CSS_PIXELS_PER_MM = 96 / 25.4;

export type CvPageMetrics = {
  widthMm: number;
  heightMm: number;
  widthPx: number;
  heightPx: number;
};

export function getCvPageMetrics(pageSize?: string | null): CvPageMetrics {
  const letter = pageSize?.trim().toLowerCase() === "letter";
  const widthMm = letter ? 215.9 : 210;
  const heightMm = letter ? 279.4 : 297;
  return {
    widthMm,
    heightMm,
    widthPx: widthMm * CSS_PIXELS_PER_MM,
    heightPx: heightMm * CSS_PIXELS_PER_MM,
  };
}

// Browser layout dimensions are rounded to whole pixels. The small tolerance prevents a page whose
// min-height rounds up by one pixel from being reported as two pages, while still using ceil for any
// genuine spill onto the next page.
export function getCvPageCount(contentHeightPx: number, pageHeightPx: number): number {
  if (!Number.isFinite(contentHeightPx) || !Number.isFinite(pageHeightPx) || pageHeightPx <= 0) return 1;
  return Math.max(1, Math.ceil(Math.max(0, contentHeightPx - 2) / pageHeightPx));
}

export function normalizeCvLanguage(language?: string | null): string {
  const normalized = language?.trim().toLowerCase();
  return normalized === "no" || normalized === "nb" || normalized === "nb-no" ? "nb-NO" : normalized || "en";
}

export function emptyCvVariantSettings(themeId = "modern"): CvVariantSettings {
  return {
    themeId,
    showPhoto: false,
    showPageNumbers: false,
    showIcons: true,
    sections: [],
    overrides: {},
    customSections: [],
  };
}

// --- API ---
// --- Pure helpers (unit-tested) ---

// Move an array item from one index to another, returning a new array.
export function moveItem<T>(arr: T[], from: number, to: number): T[] {
  if (from === to || from < 0 || to < 0 || from >= arr.length || to >= arr.length) return arr;
  const next = [...arr];
  const [item] = next.splice(from, 1);
  next.splice(to, 0, item);
  return next;
}

// Wrap the [start,end) selection of `text` with markdown markers, for the rich-text toolbar.
// Returns the new text and the selection to restore. If nothing is selected, inserts a placeholder.
export function wrapSelection(
  text: string,
  start: number,
  end: number,
  before: string,
  after: string,
  placeholder = "text",
): { text: string; selStart: number; selEnd: number } {
  const selected = text.slice(start, end) || placeholder;
  const next = text.slice(0, start) + before + selected + after + text.slice(end);
  return { text: next, selStart: start + before.length, selEnd: start + before.length + selected.length };
}

export const cvBuilderApi = {
  themes: () => api.get<CvTheme[]>("/cv/themes").then((r) => r.data),
  themePreview: (themeId: string) => api.get<CvRender>(`/cv/themes/${encodeURIComponent(themeId)}/preview`).then((r) => r.data),
  outline: () => api.get<CvOutline>("/cv/outline").then((r) => r.data),
  list: () => api.get<CvVariantSummary[]>("/cv/variants").then((r) => r.data),
  create: (body: { name?: string; jobApplicationId?: number | null; settings?: CvVariantSettings }) =>
    api.post<CvVariant>("/cv/variants", body).then((r) => r.data),
  get: (id: number) => api.get<CvVariant>(`/cv/variants/${id}`).then((r) => r.data),
  save: (id: number, body: { name?: string; settings: CvVariantSettings; source?: string }) =>
    api.put<CvVariant>(`/cv/variants/${id}`, body).then((r) => r.data),
  remove: (id: number) => api.delete(`/cv/variants/${id}`),
  duplicate: (id: number, name?: string) => api.post<CvVariant>(`/cv/variants/${id}/duplicate`, { name }).then((r) => r.data),
  setPublic: (id: number, isPublic: boolean) => api.put<CvVariant>(`/cv/variants/${id}/public`, { isPublic }).then((r) => r.data),
  versions: (id: number) => api.get<CvVariantVersionInfo[]>(`/cv/variants/${id}/versions`).then((r) => r.data),
  restore: (id: number, version: number) => api.post<CvVariant>(`/cv/variants/${id}/versions/${version}/restore`).then((r) => r.data),
  previewSettings: (settings: CvVariantSettings) => api.post<CvRender>("/cv/preview", { settings }).then((r) => r.data),
  aiAssist: (body: { action: string; text: string; role?: string; language?: string; context?: string }) =>
    api.post<{ original: string; result: string }>("/cv/ai/assist", body).then((r) => r.data),
  exportPdfUrl: (id: number) => `/cv/variants/${id}/export-pdf`,
};
