import type { CSSProperties } from 'react';
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';
import {
  PROSTHESIS_FALLBACK_COLORS,
  PROSTHESIS_TYPE_COLORS,
  prosthesisCategoryFamilyColor,
  resolveCatalogTypeColor,
} from '@/components/shared/catalog-type-colors';

/**
 * Prosthesis-type colors for Cases, Tasks, Treatment chart/dispatch, and Today.
 * Uses a category family pastel; sibling types are stepped tones of that hue.
 */

type ProsthesisColorCatalog = readonly Pick<
  ProsthesisCatalogEntry,
  'code' | 'sortOrder' | 'category'
>[];
const BADGE_INK = '#14253d';

export function primaryProsthesisCode(code: string): string {
  return splitProsthesisGroupCode(code)[0] || code;
}

export function splitProsthesisGroupCode(code: string): string[] {
  return code.split('+').map((p) => p.trim()).filter(Boolean);
}

/** Stable catalog index for fallback colors — use sortOrder, not list row position. */
export function prosthesisCatalogColorIndex(
  code: string,
  catalog: ProsthesisColorCatalog,
): number {
  const entry = catalog.find((e) => e.code === primaryProsthesisCode(code));
  if (entry) return Math.max(0, entry.sortOrder - 1);
  const idx = catalog.findIndex((e) => e.code === code);
  return idx >= 0 ? idx : 0;
}

export function prosthesisTypeColor(code: string, index = 0): string {
  return resolveCatalogTypeColor(
    primaryProsthesisCode(code),
    PROSTHESIS_TYPE_COLORS,
    index,
    PROSTHESIS_FALLBACK_COLORS,
  );
}

export function prosthesisTypeColorFromCatalog(
  code: string,
  catalog: ProsthesisColorCatalog,
): string {
  const primary = primaryProsthesisCode(code);
  const entry = catalog.find((e) => e.code === primary);
  if (!entry?.category) {
    return prosthesisTypeColor(primary, prosthesisCatalogColorIndex(code, catalog));
  }
  const siblings = catalog
    .filter((e) => e.category === entry.category)
    .sort((a, b) => a.sortOrder - b.sortOrder || a.code.localeCompare(b.code));
  const idx = siblings.findIndex((e) => e.code === primary);
  return prosthesisCategoryFamilyColor(entry.category, Math.max(0, idx) + 1);
}

function hexToRgb(hex: string): [number, number, number] | null {
  const raw = hex.replace('#', '').trim();
  if (raw.length !== 6) return null;
  const n = Number.parseInt(raw, 16);
  if (Number.isNaN(n)) return null;
  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
}

function rgbToHsl(r: number, g: number, b: number): [number, number, number] {
  const rr = r / 255;
  const gg = g / 255;
  const bb = b / 255;
  const max = Math.max(rr, gg, bb);
  const min = Math.min(rr, gg, bb);
  const l = (max + min) / 2;
  if (max === min) return [0, 0, l];
  const d = max - min;
  const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  let h = 0;
  if (max === rr) h = ((gg - bb) / d + (gg < bb ? 6 : 0)) / 6;
  else if (max === gg) h = ((bb - rr) / d + 2) / 6;
  else h = ((rr - gg) / d + 4) / 6;
  return [h, s, l];
}

function hslToHex(h: number, s: number, l: number): string {
  const hue2rgb = (p: number, q: number, t: number) => {
    let tt = t;
    if (tt < 0) tt += 1;
    if (tt > 1) tt -= 1;
    if (tt < 1 / 6) return p + (q - p) * 6 * tt;
    if (tt < 1 / 2) return q;
    if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6;
    return p;
  };
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  const p = 2 * l - q;
  const r = Math.round(hue2rgb(p, q, h + 1 / 3) * 255);
  const g = Math.round(hue2rgb(p, q, h) * 255);
  const b = Math.round(hue2rgb(p, q, h - 1 / 3) * 255);
  return `#${[r, g, b].map((c) => c.toString(16).padStart(2, '0')).join('')}`;
}

/** Darker same-hue tone for icons sitting on a pastel fill (readable in light and dark). */
export function prosthesisTypeFillAccent(hex: string): string {
  const rgb = hexToRgb(hex);
  if (!rgb) return '#334155';
  const [h, s, l] = rgbToHsl(rgb[0], rgb[1], rgb[2]);
  const nextS = Math.min(1, Math.max(s, 0.4) + 0.14);
  const nextL = Math.min(0.38, Math.max(0.24, l * 0.42));
  return hslToHex(h, nextS, nextL);
}

/** Boost washed catalog pastels so type-name text stays hued on page backgrounds. */
function prosthesisTypeLabelSwatch(hex: string): string {
  const rgb = hexToRgb(hex);
  if (!rgb) return hex;
  const [h, s, l] = rgbToHsl(rgb[0], rgb[1], rgb[2]);
  const nextS = Math.min(1, Math.max(s, 0.42) + 0.1);
  const nextL = l > 0.72 ? 0.58 : l < 0.38 ? 0.5 : l;
  return hslToHex(h, nextS, nextL);
}

/**
 * Type-name color on page backgrounds. Mixes the catalog swatch with theme text
 * so the hue stays recognizable in both light and dark.
 */
export function prosthesisTypeLabelStyleFromCatalog(
  code: string,
  catalog: ProsthesisColorCatalog,
): CSSProperties {
  const swatch = prosthesisTypeLabelSwatch(prosthesisTypeColorFromCatalog(code, catalog));
  return {
    ['--prosthesis-swatch' as string]: swatch,
    color: 'color-mix(in srgb, var(--prosthesis-swatch) 80%, var(--color-text-primary))',
  };
}

/** Filled swatch (small indicator dots). */
export function prosthesisTypeSwatchStyle(code: string, index = 0): CSSProperties {
  return { backgroundColor: prosthesisTypeColor(code, index), borderColor: 'rgba(0, 0, 0, 0.18)' };
}

export function prosthesisTypeSwatchStyleFromCatalog(
  code: string,
  catalog: ProsthesisColorCatalog,
): CSSProperties {
  return {
    backgroundColor: prosthesisTypeColorFromCatalog(code, catalog),
    borderColor: 'rgba(0, 0, 0, 0.18)',
  };
}

/** Pastel pill / banner fill with readable dark text (group headers, badges). */
export function prosthesisTypeBadgeStyle(code: string, index = 0): CSSProperties {
  return {
    backgroundColor: prosthesisTypeColor(code, index),
    borderColor: 'rgba(0, 0, 0, 0.16)',
    color: BADGE_INK,
  };
}

export function prosthesisTypeBadgeStyleFromCatalog(
  code: string,
  catalog: ProsthesisColorCatalog,
): CSSProperties {
  return {
    backgroundColor: prosthesisTypeColorFromCatalog(code, catalog),
    borderColor: 'rgba(0, 0, 0, 0.16)',
    color: BADGE_INK,
  };
}

export function formatToothList(
  teeth: string[],
  archLabels?: { UA?: string; LA?: string },
): string {
  return teeth
    .map((tooth) => {
      if (tooth === 'UA') return archLabels?.UA ?? tooth;
      if (tooth === 'LA') return archLabels?.LA ?? tooth;
      return tooth;
    })
    .join(', ');
}
