defmodule Berrypod.Theme.PreviewDataTest do
  use ExUnit.Case, async: true

  alias Berrypod.Theme.PreviewData

  describe "products/0" do
    test "returns a list of products" do
      products = PreviewData.products()

      assert is_list(products)
      assert products != []
    end

    test "each product has required fields" do
      products = PreviewData.products()
      product = List.first(products)

      assert is_map(product)
      assert Map.has_key?(product, :id)
      assert Map.has_key?(product, :title)
      assert Map.has_key?(product, :description)
      assert Map.has_key?(product, :cheapest_price)
      assert Map.has_key?(product, :images)
      assert Map.has_key?(product, :category)
      assert Map.has_key?(product, :in_stock)
      assert Map.has_key?(product, :on_sale)
    end

    test "products have valid prices" do
      products = PreviewData.products()

      for product <- products do
        assert is_integer(product.cheapest_price)
        assert product.cheapest_price > 0

        if product.compare_at_price do
          assert is_integer(product.compare_at_price)
          assert product.compare_at_price > product.cheapest_price
        end
      end
    end

    test "products have images" do
      products = PreviewData.products()

      for product <- products do
        assert is_list(product.images)
        assert length(product.images) >= 1

        for image <- product.images do
          assert is_integer(image.position)
          assert is_binary(image.src) or not is_nil(image.image_id)
        end
      end
    end

    test "some products are on sale" do
      products = PreviewData.products()
      on_sale_products = Enum.filter(products, & &1.on_sale)

      assert on_sale_products != []
    end

    test "on-sale products have compare_at_price" do
      products = PreviewData.products()
      on_sale_products = Enum.filter(products, & &1.on_sale)

      for product <- on_sale_products do
        assert product.compare_at_price != nil
      end
    end
  end

  describe "cart_items/0" do
    test "returns a list of cart items" do
      cart_items = PreviewData.cart_items()

      assert is_list(cart_items)
      assert length(cart_items) > 0
    end

    test "each cart item has required fields" do
      cart_items = PreviewData.cart_items()
      item = List.first(cart_items)

      assert is_map(item)
      assert Map.has_key?(item, :product)
      assert Map.has_key?(item, :quantity)
      assert Map.has_key?(item, :variant)
    end

    test "cart items have valid quantities" do
      cart_items = PreviewData.cart_items()

      for item <- cart_items do
        assert is_integer(item.quantity)
        assert item.quantity > 0
      end
    end

    test "cart items reference valid products" do
      cart_items = PreviewData.cart_items()

      for item <- cart_items do
        product = item.product
        assert is_map(product)
        assert Map.has_key?(product, :id)
        assert Map.has_key?(product, :title)
        assert Map.has_key?(product, :cheapest_price)
      end
    end
  end

  describe "testimonials/0" do
    test "returns a list of testimonials" do
      testimonials = PreviewData.testimonials()

      assert is_list(testimonials)
      assert length(testimonials) > 0
    end

    test "each testimonial has required fields" do
      testimonials = PreviewData.testimonials()
      testimonial = List.first(testimonials)

      assert is_map(testimonial)
      assert Map.has_key?(testimonial, :id)
      assert Map.has_key?(testimonial, :author)
      assert Map.has_key?(testimonial, :content)
      assert Map.has_key?(testimonial, :rating)
      assert Map.has_key?(testimonial, :date)
    end

    test "testimonials have valid ratings" do
      testimonials = PreviewData.testimonials()

      for testimonial <- testimonials do
        assert is_integer(testimonial.rating)
        assert testimonial.rating >= 1
        assert testimonial.rating <= 5
      end
    end

    test "testimonials have content" do
      testimonials = PreviewData.testimonials()

      for testimonial <- testimonials do
        assert is_binary(testimonial.content)
        assert String.length(testimonial.content) > 0
      end
    end
  end

  describe "categories/0" do
    test "returns a list of categories" do
      categories = PreviewData.categories()

      assert is_list(categories)
      assert categories != []
    end

    test "each category has required fields" do
      categories = PreviewData.categories()
      category = List.first(categories)

      assert is_map(category)
      assert Map.has_key?(category, :id)
      assert Map.has_key?(category, :name)
      assert Map.has_key?(category, :slug)
      assert Map.has_key?(category, :product_count)
      assert Map.has_key?(category, :image_url)
    end

    test "categories have valid slugs" do
      categories = PreviewData.categories()

      for category <- categories do
        assert is_binary(category.slug)
        assert String.match?(category.slug, ~r/^[a-z0-9-]+$/)
      end
    end

    test "categories have product counts" do
      categories = PreviewData.categories()

      for category <- categories do
        assert is_integer(category.product_count)
        assert category.product_count >= 0
      end
    end
  end

  describe "has_real_products?/0" do
    test "returns false when no real products exist" do
      assert PreviewData.has_real_products?() == false
    end
  end

  describe "category_by_slug/1" do
    test "returns category when slug exists" do
      category = PreviewData.category_by_slug("art-prints")

      assert category != nil
      assert category.slug == "art-prints"
      assert is_binary(category.name)
    end

    test "returns nil when slug does not exist" do
      assert PreviewData.category_by_slug("nonexistent") == nil
    end

    test "finds all known categories by slug" do
      categories = PreviewData.categories()

      for category <- categories do
        found = PreviewData.category_by_slug(category.slug)
        assert found != nil
        assert found.id == category.id
      end
    end
  end

  describe "products_by_category/1" do
    test "returns all products for nil" do
      all_products = PreviewData.products()
      filtered = PreviewData.products_by_category(nil)

      assert filtered == all_products
    end

    test "returns all products for 'all'" do
      all_products = PreviewData.products()
      filtered = PreviewData.products_by_category("all")

      assert filtered == all_products
    end

    test "returns empty list for nonexistent category" do
      assert PreviewData.products_by_category("nonexistent") == []
    end

    test "returns only products matching the category" do
      category = List.first(PreviewData.categories())
      products = PreviewData.products_by_category(category.slug)

      assert is_list(products)

      for product <- products do
        assert product.category == category.name
      end
    end

    test "products are filtered correctly for each category" do
      categories = PreviewData.categories()

      for category <- categories do
        products = PreviewData.products_by_category(category.slug)

        for product <- products do
          assert product.category == category.name
        end
      end
    end

    test "all products belong to at least one category" do
      all_products = PreviewData.products()
      categories = PreviewData.categories()
      category_names = Enum.map(categories, & &1.name)

      for product <- all_products do
        assert product.category in category_names
      end
    end
  end
end
