defmodule SimpleshopTheme.Theme.CSSCacheTest do
  use SimpleshopTheme.DataCase

  alias SimpleshopTheme.Theme.CSSCache
  alias SimpleshopTheme.Theme.CSSGenerator
  alias SimpleshopTheme.Settings.ThemeSettings

  describe "get/0" do
    test "returns cached CSS after warm" do
      # Cache should be pre-warmed on startup
      assert {:ok, css} = CSSCache.get()
      assert is_binary(css)
      assert css =~ ".themed {"
    end
  end

  describe "put/1 and get/0" do
    test "stores and retrieves CSS" do
      test_css = "/* test css */"
      :ok = CSSCache.put(test_css)

      assert {:ok, ^test_css} = CSSCache.get()

      # Restore original cache
      CSSCache.warm()
    end
  end

  describe "invalidate/0" do
    test "clears cached CSS" do
      # Ensure cache has something
      CSSCache.warm()
      assert {:ok, _} = CSSCache.get()

      # Invalidate
      :ok = CSSCache.invalidate()
      assert :miss = CSSCache.get()

      # Restore
      CSSCache.warm()
    end
  end

  describe "warm/0" do
    test "populates cache from current settings" do
      CSSCache.invalidate()
      assert :miss = CSSCache.get()

      :ok = CSSCache.warm()
      assert {:ok, css} = CSSCache.get()
      assert is_binary(css)
    end
  end

  describe "performance" do
    @tag :benchmark
    test "cache hit is faster than generation" do
      # Ensure cache is warm
      CSSCache.warm()
      settings = %ThemeSettings{}

      # Benchmark cache hit (should be microseconds)
      {cache_time, {:ok, _cached_css}} =
        :timer.tc(fn ->
          CSSCache.get()
        end)

      # Benchmark CSS generation (should be milliseconds)
      {gen_time, _generated_css} =
        :timer.tc(fn ->
          CSSGenerator.generate(settings)
        end)

      # Log results for visibility
      IO.puts("\n")
      IO.puts("  Cache hit:     #{cache_time} µs")
      IO.puts("  CSS generate:  #{gen_time} µs")
      IO.puts("  Speedup:       #{Float.round(gen_time / max(cache_time, 1), 1)}x faster")

      # Cache should be faster than generation
      assert cache_time < gen_time,
             "Cache (#{cache_time}µs) should be faster than generation (#{gen_time}µs)"
    end

    @tag :benchmark
    test "multiple cache hits are consistent" do
      CSSCache.warm()

      times =
        for _ <- 1..100 do
          {time, {:ok, _}} = :timer.tc(fn -> CSSCache.get() end)
          time
        end

      avg = Enum.sum(times) / length(times)
      max_time = Enum.max(times)
      min_time = Enum.min(times)

      IO.puts("\n")
      IO.puts("  100 cache hits:")
      IO.puts("    Avg: #{Float.round(avg, 1)} µs")
      IO.puts("    Min: #{min_time} µs")
      IO.puts("    Max: #{max_time} µs")

      # Average should be under 100 microseconds (ETS is fast)
      assert avg < 100, "Average cache hit (#{avg}µs) should be under 100µs"
    end
  end
end
