defmodule Berrypod.Theme.Contrast do
  @moduledoc """
  WCAG contrast ratio calculations for accessibility checking.

  Used to warn shop owners when header background images might make text hard to read.
  """

  @doc """
  Calculate relative luminance from sRGB values (0-255).
  Uses the WCAG 2.1 formula.
  """
  def relative_luminance([r, g, b]) do
    [r, g, b]
    |> Enum.map(fn c ->
      c = c / 255

      if c <= 0.03928 do
        c / 12.92
      else
        :math.pow((c + 0.055) / 1.055, 2.4)
      end
    end)
    |> then(fn [r, g, b] -> 0.2126 * r + 0.7152 * g + 0.0722 * b end)
  end

  @doc """
  Calculate WCAG contrast ratio between two colors.
  Returns a ratio >= 1.0 (higher = better contrast).
  """
  def contrast_ratio(color1, color2) do
    l1 = relative_luminance(color1)
    l2 = relative_luminance(color2)
    {lighter, darker} = if l1 > l2, do: {l1, l2}, else: {l2, l1}
    (lighter + 0.05) / (darker + 0.05)
  end

  @doc """
  Analyze header image colors against text color, return warning level.

  Returns:
  - `:ok` - All dominant colors have acceptable contrast
  - `:caution` - Some colors may be problematic
  - `:poor` - Most colors have poor contrast
  """
  def analyze_header_contrast(nil, _text_color), do: :ok
  def analyze_header_contrast([], _text_color), do: :ok

  def analyze_header_contrast(dominant_colors, text_color) when is_list(dominant_colors) do
    text_rgb = hex_to_rgb(text_color)

    ratios = Enum.map(dominant_colors, &contrast_ratio(&1, text_rgb))
    min_ratio = Enum.min(ratios)
    avg_ratio = Enum.sum(ratios) / length(ratios)

    cond do
      # All colors have good contrast (3:1 is WCAG AA for large text)
      Enum.all?(ratios, &(&1 >= 3.0)) -> :ok
      # Most colors are problematic
      avg_ratio < 3.0 -> :poor
      # Some colors might be problematic
      min_ratio < 2.0 -> :caution
      true -> :ok
    end
  end

  @doc """
  Parse JSON-encoded dominant colors string.
  """
  def parse_dominant_colors(nil), do: nil
  def parse_dominant_colors(""), do: nil

  def parse_dominant_colors(json) when is_binary(json) do
    case Jason.decode(json) do
      {:ok, colors} when is_list(colors) -> colors
      _ -> nil
    end
  end

  @doc """
  Get the text color for a given mood setting.
  """
  def text_color_for_mood("dark"), do: "#fafafa"
  def text_color_for_mood("neutral"), do: "#171717"
  def text_color_for_mood("warm"), do: "#1c1917"
  def text_color_for_mood("cool"), do: "#0f172a"
  def text_color_for_mood(_), do: "#171717"

  @doc """
  Convert hex color to RGB list.
  """
  def hex_to_rgb("#" <> hex), do: hex_to_rgb(hex)

  def hex_to_rgb(hex) when byte_size(hex) == 6 do
    [
      String.slice(hex, 0..1) |> Integer.parse(16) |> elem(0),
      String.slice(hex, 2..3) |> Integer.parse(16) |> elem(0),
      String.slice(hex, 4..5) |> Integer.parse(16) |> elem(0)
    ]
  end
end
