defmodule Berrypod.Pages.BlockTypes do
  @moduledoc """
  Registry of all block types available in the page builder.

  Each block type has a name, icon, allowed pages, settings schema,
  and an optional data loader that fetches extra data when the block
  is present on a page.
  """

  alias Berrypod.Pages.SettingsField
  alias Berrypod.Products
  alias Berrypod.Theme.PreviewData

  @block_types %{
    # ── Portable blocks (work on any page) ──────────────────────────

    "hero" => %{
      name: "Hero banner",
      description: "Full-width banner with title, description and call-to-action buttons",
      icon: "hero-megaphone",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "title", label: "Title", type: :text, default: ""},
        %SettingsField{key: "description", label: "Description", type: :textarea, default: ""},
        %SettingsField{key: "cta_text", label: "Button text", type: :text, default: ""},
        %SettingsField{key: "cta_href", label: "Button link", type: :text, default: ""},
        %SettingsField{
          key: "secondary_cta_text",
          label: "Secondary button text",
          type: :text,
          default: ""
        },
        %SettingsField{
          key: "secondary_cta_href",
          label: "Secondary button link",
          type: :text,
          default: ""
        },
        %SettingsField{
          key: "variant",
          label: "Style",
          type: :select,
          options: ~w(default page sunken error),
          default: "default"
        }
      ]
    },
    "featured_products" => %{
      name: "Featured products",
      description: "Grid of product cards — choose how many and which style",
      icon: "hero-star",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{
          key: "title",
          label: "Title",
          type: :text,
          default: "Featured products"
        },
        %SettingsField{
          key: "product_count",
          label: "Number of products",
          type: :number,
          default: 8
        },
        %SettingsField{
          key: "layout",
          label: "Layout",
          type: :select,
          options: ~w(section grid),
          default: "section"
        },
        %SettingsField{
          key: "card_variant",
          label: "Card style",
          type: :select,
          options: ~w(featured default minimal compact),
          default: "featured"
        },
        %SettingsField{
          key: "columns",
          label: "Columns",
          type: :select,
          options: ~w(auto fixed-4),
          default: "auto"
        }
      ],
      data_loader: :load_featured_products
    },
    "image_text" => %{
      name: "Image + text",
      description: "Side-by-side image and text with optional link",
      icon: "hero-photo",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "title", label: "Title", type: :text, default: ""},
        %SettingsField{key: "description", label: "Description", type: :textarea, default: ""},
        %SettingsField{key: "image_id", label: "Image", type: :image, default: nil},
        %SettingsField{key: "link_text", label: "Link text", type: :text, default: ""},
        %SettingsField{key: "link_href", label: "Link URL", type: :text, default: ""}
      ]
    },
    "category_nav" => %{
      name: "Category navigation",
      description: "Clickable category pills linking to filtered product collections",
      icon: "hero-squares-2x2",
      allowed_on: :all,
      settings_schema: []
    },
    "newsletter_card" => %{
      name: "Newsletter signup",
      description: "Email signup form with double opt-in — enable in admin settings",
      icon: "hero-envelope",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "title", label: "Title", type: :text, default: "Newsletter"},
        %SettingsField{
          key: "description",
          label: "Description",
          type: :textarea,
          default:
            "Sample newsletter signup. Replace with your own message to encourage subscribers."
        },
        %SettingsField{
          key: "button_text",
          label: "Button text",
          type: :text,
          default: "Subscribe"
        }
      ]
    },
    "social_links_card" => %{
      name: "Social links",
      description: "Icons linking to your social media profiles",
      icon: "hero-share",
      allowed_on: :all,
      settings_schema: []
    },
    "info_card" => %{
      name: "Info card",
      description: "Key-value list for shop details like materials, sizing or delivery info",
      icon: "hero-information-circle",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "title", label: "Title", type: :text, default: ""},
        %SettingsField{
          key: "items",
          label: "Items",
          type: :repeater,
          default: [],
          item_schema: [
            %SettingsField{key: "label", label: "Label", type: :text, default: ""},
            %SettingsField{key: "value", label: "Value", type: :text, default: ""}
          ]
        }
      ]
    },
    "trust_badges" => %{
      name: "Trust badges",
      description: "Icons for free shipping, secure payment and quality guarantees",
      icon: "hero-shield-check",
      allowed_on: :all,
      settings_schema: []
    },
    "reviews_section" => %{
      name: "Customer reviews",
      description: "Star ratings and customer testimonials",
      icon: "hero-chat-bubble-left-right",
      allowed_on: :all,
      settings_schema: [],
      data_loader: :load_reviews
    },
    "spacer" => %{
      name: "Spacer",
      description: "Vertical breathing room between blocks",
      icon: "hero-arrows-up-down",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{
          key: "size",
          label: "Size",
          type: :select,
          options: ~w(small medium large xlarge),
          default: "medium"
        }
      ]
    },
    "divider" => %{
      name: "Divider",
      description: "Horizontal line, dots or fade to separate sections",
      icon: "hero-minus",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{
          key: "style",
          label: "Style",
          type: :select,
          options: ~w(line dots fade),
          default: "line"
        }
      ]
    },
    "button" => %{
      name: "Button",
      description: "Standalone call-to-action button linking to any page",
      icon: "hero-cursor-arrow-rays",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "text", label: "Button text", type: :text, default: "Learn more"},
        %SettingsField{key: "href", label: "Link URL", type: :text, default: "/"},
        %SettingsField{
          key: "style",
          label: "Style",
          type: :select,
          options: ~w(primary outline),
          default: "primary"
        },
        %SettingsField{
          key: "alignment",
          label: "Alignment",
          type: :select,
          options: ~w(left centre right),
          default: "centre"
        }
      ]
    },
    "video_embed" => %{
      name: "Video embed",
      description: "Embedded YouTube or Vimeo video with optional caption",
      icon: "hero-play",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "url", label: "Video URL", type: :text, default: ""},
        %SettingsField{key: "caption", label: "Caption", type: :text, default: ""},
        %SettingsField{
          key: "aspect_ratio",
          label: "Aspect ratio",
          type: :select,
          options: ~w(16:9 4:3 1:1),
          default: "16:9"
        }
      ]
    },

    # ── PDP blocks ──────────────────────────────────────────────────

    "product_hero" => %{
      name: "Product hero",
      description: "Product image gallery, title, price and add-to-cart button",
      icon: "hero-cube",
      allowed_on: ["pdp"],
      settings_schema: []
    },
    "breadcrumb" => %{
      name: "Breadcrumb",
      description: "Navigation trail showing Home > Category > Product",
      icon: "hero-chevron-right",
      allowed_on: ["pdp"],
      settings_schema: []
    },
    "product_details" => %{
      name: "Product details",
      description: "Full product description text",
      icon: "hero-document-text",
      allowed_on: ["pdp"],
      settings_schema: []
    },
    "related_products" => %{
      name: "Related products",
      description: "Products from the same category",
      icon: "hero-squares-plus",
      allowed_on: ["pdp"],
      settings_schema: [],
      data_loader: :load_related_products
    },

    # ── Collection blocks ───────────────────────────────────────────

    "collection_header" => %{
      name: "Collection header",
      description: "Category title and product count",
      icon: "hero-tag",
      allowed_on: ["collection"],
      settings_schema: []
    },
    "filter_bar" => %{
      name: "Filter bar",
      description: "Category filter pills and sort dropdown",
      icon: "hero-funnel",
      allowed_on: ["collection"],
      settings_schema: []
    },
    "product_grid" => %{
      name: "Product grid",
      description: "Responsive grid of all products in the collection",
      icon: "hero-squares-2x2",
      allowed_on: ["collection"],
      settings_schema: []
    },

    # ── Cart blocks ─────────────────────────────────────────────────

    "cart_items" => %{
      name: "Cart items",
      description: "List of items in the customer's cart with quantity controls",
      icon: "hero-shopping-cart",
      allowed_on: ["cart"],
      settings_schema: []
    },
    "order_summary" => %{
      name: "Order summary",
      description: "Subtotal, shipping estimate and checkout button",
      icon: "hero-calculator",
      allowed_on: ["cart"],
      settings_schema: []
    },

    # ── Contact blocks ──────────────────────────────────────────────

    "contact_form" => %{
      name: "Contact form",
      description: "Name, email and message form that sends to your inbox",
      icon: "hero-envelope",
      allowed_on: ["contact"],
      settings_schema: [
        %SettingsField{key: "email", label: "Email", type: :text, default: "hello@example.com"}
      ]
    },
    "order_tracking_card" => %{
      name: "Order tracking",
      description: "Lets customers look up their order status",
      icon: "hero-truck",
      allowed_on: ["contact"],
      settings_schema: []
    },

    # ── Content blocks ──────────────────────────────────────────────

    "content_body" => %{
      name: "Page content",
      description: "Rich text block with optional image — the main body of a content page",
      icon: "hero-document-text",
      allowed_on: :all,
      settings_schema: [
        %SettingsField{key: "content", label: "Content", type: :textarea, default: ""},
        %SettingsField{key: "image_id", label: "Image", type: :image, default: nil}
      ]
    },

    # ── Checkout success ────────────────────────────────────────────

    "checkout_result" => %{
      name: "Checkout result",
      description: "Order confirmation message with order number",
      icon: "hero-check-circle",
      allowed_on: ["checkout_success"],
      settings_schema: []
    },

    # ── Orders ──────────────────────────────────────────────────────

    "order_card" => %{
      name: "Order cards",
      description: "List of past orders with status and totals",
      icon: "hero-clipboard-document-list",
      allowed_on: ["orders"],
      settings_schema: []
    },

    # ── Order detail ────────────────────────────────────────────────

    "order_detail_card" => %{
      name: "Order detail",
      description: "Full order breakdown with items, shipping and payment info",
      icon: "hero-clipboard-document",
      allowed_on: ["order_detail"],
      settings_schema: []
    },

    # ── Search ──────────────────────────────────────────────────────

    "search_results" => %{
      name: "Search results",
      description: "Product search results grid with thumbnails and prices",
      icon: "hero-magnifying-glass",
      allowed_on: ["search"],
      settings_schema: []
    }
  }

  @doc "Returns the full block type registry."
  def all, do: @block_types

  @doc "Returns the definition for a single block type, or nil."
  def get(type), do: Map.get(@block_types, type)

  @doc "Returns block types allowed on the given page slug."
  def allowed_for(page_slug) do
    @block_types
    |> Enum.filter(fn {_type, def} ->
      def.allowed_on == :all or page_slug in def.allowed_on
    end)
    |> Map.new()
  end

  @doc """
  Runs data loaders for a list of blocks, merging results into a single map.

  Each block type can declare a `data_loader` — a function that returns
  extra assigns needed by that block. Only fires when the block is on the page.
  """
  def load_data(blocks, assigns) do
    blocks
    |> Enum.reduce(%{}, fn block, acc ->
      case get(block["type"]) do
        %{data_loader: loader} ->
          Map.merge(acc, run_loader(loader, assigns, block["settings"] || %{}))

        _ ->
          acc
      end
    end)
  end

  # ── Data loaders ────────────────────────────────────────────────

  defp run_loader(:load_featured_products, assigns, settings) do
    limit = settings["product_count"] || 8

    products =
      if assigns[:mode] == :preview do
        PreviewData.products() |> Enum.take(limit)
      else
        Products.list_visible_products(limit: limit)
      end

    %{products: products}
  end

  defp run_loader(:load_related_products, assigns, _settings) do
    products =
      if assigns[:mode] == :preview do
        PreviewData.products() |> Enum.take(4)
      else
        case assigns[:product] do
          %{category: cat, id: id} when not is_nil(cat) ->
            Products.list_visible_products(category: cat, limit: 4, exclude: id)

          _ ->
            []
        end
      end

    %{related_products: products}
  end

  defp run_loader(:load_reviews, assigns, _settings) do
    if assigns[:mode] == :preview do
      %{
        reviews: PreviewData.reviews(),
        average_rating: Decimal.new(5),
        review_count: 2
      }
    else
      case assigns[:product] do
        %{id: product_id} ->
          reviews =
            Berrypod.Reviews.list_reviews_for_product(product_id, limit: 10)
            |> Enum.map(&format_review_for_display/1)

          {avg, count} = Berrypod.Reviews.average_rating_for_product(product_id)

          %{
            reviews: reviews,
            average_rating: avg,
            review_count: count
          }

        _ ->
          %{reviews: [], average_rating: nil, review_count: 0}
      end
    end
  end

  defp format_review_for_display(review) do
    %{
      id: review.id,
      rating: review.rating,
      title: review.title,
      body: review.body,
      author: review.author_name,
      date: relative_time(review.inserted_at),
      verified: not is_nil(review.order_id),
      images: Berrypod.Reviews.get_review_images(review)
    }
  end

  defp relative_time(datetime) do
    now = DateTime.utc_now()
    diff = DateTime.diff(now, datetime, :second)

    cond do
      diff < 60 -> "just now"
      diff < 3600 -> "#{div(diff, 60)} minutes ago"
      diff < 86400 -> "#{div(diff, 3600)} hours ago"
      diff < 604_800 -> "#{div(diff, 86400)} days ago"
      diff < 2_592_000 -> "#{div(diff, 604_800)} weeks ago"
      true -> "#{div(diff, 2_592_000)} months ago"
    end
  end
end
