defmodule AprsmeWeb.ThemeManagerTest do
  use ExUnit.Case, async: true

  import Phoenix.LiveViewTest

  alias AprsmeWeb.ThemeManager
  alias Phoenix.LiveView.Socket

  describe "resolve_theme/2" do
    test "returns system_preference for 'auto'" do
      assert ThemeManager.resolve_theme("auto", "dark") == "dark"
      assert ThemeManager.resolve_theme("auto", "light") == "light"
    end

    test "returns the explicit theme for 'light' or 'dark'" do
      assert ThemeManager.resolve_theme("light", "dark") == "light"
      assert ThemeManager.resolve_theme("dark", "light") == "dark"
    end

    test "falls back to system_preference for unknown themes" do
      assert ThemeManager.resolve_theme("neon", "light") == "light"
      assert ThemeManager.resolve_theme(nil, "dark") == "dark"
    end
  end

  describe "get_theme_colors/1" do
    test "returns dark-themed colors for 'dark'" do
      colors = ThemeManager.get_theme_colors("dark")
      assert colors.text == "#e5e7eb"
      assert colors.grid == "#374151"
      assert colors.primary == "#3b82f6"
    end

    test "returns light-themed colors for 'light'" do
      colors = ThemeManager.get_theme_colors("light")
      assert colors.text == "#111827"
      assert colors.primary == "#2563eb"
    end

    test "any non-dark value returns light colors" do
      assert ThemeManager.get_theme_colors("auto").text == "#111827"
      assert ThemeManager.get_theme_colors(nil).text == "#111827"
      assert ThemeManager.get_theme_colors("whatever").text == "#111827"
    end

    test "dark and light colors are distinct" do
      dark = ThemeManager.get_theme_colors("dark")
      light = ThemeManager.get_theme_colors("light")
      refute dark.text == light.text
      refute dark.grid == light.grid
    end

    test "all expected keys are present" do
      for theme <- ["dark", "light"] do
        colors = ThemeManager.get_theme_colors(theme)
        assert Map.has_key?(colors, :text)
        assert Map.has_key?(colors, :grid)
        assert Map.has_key?(colors, :background)
        assert Map.has_key?(colors, :primary)
        assert Map.has_key?(colors, :secondary)
        assert Map.has_key?(colors, :accent)
      end
    end
  end

  describe "init_theme/2" do
    test "initializes with stored theme from session" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      result = ThemeManager.init_theme(socket, %{"theme" => "dark"})
      assigns = Map.get(result, :assigns)
      assert assigns.theme == "dark"
      assert assigns.resolved_theme == "dark"
      assert assigns.theme_colors.text == "#e5e7eb"
    end

    test "defaults to 'auto' when no session theme" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      result = ThemeManager.init_theme(socket, %{})
      assigns = Map.get(result, :assigns)
      assert assigns.theme == "auto"
      # system_preference is "light" in this module
      assert assigns.resolved_theme == "light"
    end

    test "ignores unknown stored themes, defaulting to auto" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      result = ThemeManager.init_theme(socket, %{"theme" => "neon"})
      assigns = Map.get(result, :assigns)
      assert assigns.theme == "auto"
    end

    test "defaults to auto when session arg is omitted" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      result = ThemeManager.init_theme(socket)
      assigns = Map.get(result, :assigns)
      assert assigns.theme == "auto"
    end
  end

  describe "handle_theme_change/2" do
    test "returns unchanged socket for invalid themes" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      assert ThemeManager.handle_theme_change(socket, "invalid") == socket
    end

    test "updates assigns for valid themes" do
      socket = %Socket{assigns: %{__changed__: %{}}}
      result = ThemeManager.handle_theme_change(socket, "dark")
      assigns = Map.get(result, :assigns)
      assert assigns.theme == "dark"
      assert assigns.resolved_theme == "dark"
    end
  end

  describe "theme_selector/1" do
    test "renders buttons for light, dark and auto" do
      html = render_component(&ThemeManager.theme_selector/1, %{theme: "light"})
      assert html =~ "Light"
      assert html =~ "Dark"
      assert html =~ "Auto"
      # The active theme should have the distinctive selected styling.
      assert html =~ "set_theme"
    end

    test "highlights the dark button when theme is dark" do
      html = render_component(&ThemeManager.theme_selector/1, %{theme: "dark"})
      # Dark-button block appears twice with different classes depending on
      # whether it's active, but the label text is always present.
      assert html =~ "Dark"
    end

    test "accepts a custom class" do
      html =
        render_component(&ThemeManager.theme_selector/1, %{
          theme: "auto",
          class: "my-custom-class"
        })

      assert html =~ "my-custom-class"
    end
  end
end
