import type { WidgetTheme } from "./public-contracts.js";

/** Applies only validated theme tokens to a single isolated surface. */
export function applyWidgetTheme(
  target: HTMLElement,
  theme: WidgetTheme,
): void {
  const [firstColor, secondColor, thirdColor] = fillBorderColors(
    theme.borderColors,
  );
  target.style.setProperty("--akintu-border-color-1", firstColor);
  target.style.setProperty("--akintu-border-color-2", secondColor);
  target.style.setProperty("--akintu-border-color-3", thirdColor);
  target.style.setProperty("--akintu-button-color", theme.buttonColor);
  target.style.setProperty(
    "--akintu-button-text",
    getContrastingTextColor(theme.buttonColor),
  );
  target.style.setProperty("--akintu-primary-color", theme.primaryColor);
  target.style.setProperty(
    "--akintu-primary-text",
    getContrastingTextColor(theme.primaryColor),
  );
  target.style.setProperty(
    "--akintu-primary-soft",
    mixColorWithWhite(theme.primaryColor, 0.08),
  );
  target.style.setProperty(
    "--akintu-primary-border",
    mixColorWithWhite(theme.primaryColor, 0.3),
  );
}

function fillBorderColors(colors: string[]): [string, string, string] {
  if (colors.length === 1) return [colors[0]!, colors[0]!, colors[0]!];
  if (colors.length === 2) return [colors[0]!, colors[1]!, colors[0]!];
  return [colors[0]!, colors[1]!, colors[2]!];
}

function getContrastingTextColor(hexColor: string): "#07111f" | "#ffffff" {
  const red = Number.parseInt(hexColor.slice(1, 3), 16);
  const green = Number.parseInt(hexColor.slice(3, 5), 16);
  const blue = Number.parseInt(hexColor.slice(5, 7), 16);
  const luminance = (red * 299 + green * 587 + blue * 114) / 1000;
  return luminance >= 150 ? "#07111f" : "#ffffff";
}

function mixColorWithWhite(hexColor: string, colorWeight: number): string {
  const channels = [1, 3, 5].map((offset) =>
    Math.round(
      Number.parseInt(hexColor.slice(offset, offset + 2), 16) * colorWeight +
        255 * (1 - colorWeight),
    ),
  );
  return `#${channels.map((channel) => channel.toString(16).padStart(2, "0")).join("")}`;
}
