import {
  DEFAULT_SITE_PRIMARY_COLOR,
  normalizeSitePrimaryColor,
} from "./site-settings";

type RgbColor = {
  r: number;
  g: number;
  b: number;
};

type HslColor = {
  h: number;
  s: number;
  l: number;
};

function clamp(value: number, min: number, max: number) {
  return Math.min(Math.max(value, min), max);
}

function hexToRgb(hex: string): RgbColor {
  const normalized = normalizeSitePrimaryColor(hex).slice(1);

  return {
    r: Number.parseInt(normalized.slice(0, 2), 16),
    g: Number.parseInt(normalized.slice(2, 4), 16),
    b: Number.parseInt(normalized.slice(4, 6), 16),
  };
}

function rgbToHsl({ r, g, b }: RgbColor): HslColor {
  const red = r / 255;
  const green = g / 255;
  const blue = b / 255;
  const max = Math.max(red, green, blue);
  const min = Math.min(red, green, blue);
  const delta = max - min;
  const lightness = (max + min) / 2;

  if (delta === 0) {
    return {
      h: 0,
      s: 0,
      l: Math.round(lightness * 100),
    };
  }

  const saturation =
    lightness > 0.5
      ? delta / (2 - max - min)
      : delta / (max + min);

  let hue = 0;

  switch (max) {
    case red:
      hue = (green - blue) / delta + (green < blue ? 6 : 0);
      break;
    case green:
      hue = (blue - red) / delta + 2;
      break;
    default:
      hue = (red - green) / delta + 4;
      break;
  }

  return {
    h: Math.round(hue * 60),
    s: Math.round(saturation * 100),
    l: Math.round(lightness * 100),
  };
}

function toChannels(color: HslColor): string {
  return `${Math.round(color.h)} ${Math.round(color.s)}% ${Math.round(color.l)}%`;
}

function deriveSecondaryColor(color: HslColor, dark = false): HslColor {
  return {
    h: (color.h + 10) % 360,
    s: clamp(color.s - (dark ? 2 : 8), 35, 95),
    l: clamp(color.l + (dark ? 10 : 8), 20, 80),
  };
}

function deriveDarkPrimary(color: HslColor): HslColor {
  return {
    h: color.h,
    s: clamp(color.s, 40, 95),
    l: clamp(color.l + 6, 30, 78),
  };
}

export function buildSiteThemeTokens(primaryColor: string) {
  const safePrimary = normalizeSitePrimaryColor(primaryColor || DEFAULT_SITE_PRIMARY_COLOR);
  const basePrimary = rgbToHsl(hexToRgb(safePrimary));
  const darkPrimary = deriveDarkPrimary(basePrimary);

  return {
    light: {
      primary: toChannels(basePrimary),
      secondary: toChannels(deriveSecondaryColor(basePrimary)),
    },
    dark: {
      primary: toChannels(darkPrimary),
      secondary: toChannels(deriveSecondaryColor(darkPrimary, true)),
    },
  };
}

export function buildSiteThemeStyleText(primaryColor: string) {
  const tokens = buildSiteThemeTokens(primaryColor);

  return `
:root {
  --primary: ${tokens.light.primary};
  --ring: ${tokens.light.primary};
  --brand-primary: ${tokens.light.primary};
  --brand-secondary: ${tokens.light.secondary};
  --sidebar-primary: ${tokens.light.primary};
  --sidebar-ring: ${tokens.light.primary};
}

.dark {
  --primary: ${tokens.dark.primary};
  --ring: ${tokens.dark.primary};
  --brand-primary: ${tokens.dark.primary};
  --brand-secondary: ${tokens.dark.secondary};
  --sidebar-primary: ${tokens.dark.primary};
  --sidebar-ring: ${tokens.dark.primary};
}
  `.trim();
}
