defmodule Berrypod.Analytics.Referrer do
  @moduledoc """
  Referrer cleaning and source categorisation.

  Extracts the domain from a referrer URL and maps known domains to
  human-readable source names (Google, Facebook, etc.).
  """

  @source_map %{
    "google" => "Google",
    "bing" => "Bing",
    "duckduckgo" => "DuckDuckGo",
    "yahoo" => "Yahoo",
    "baidu" => "Baidu",
    "yandex" => "Yandex",
    "ecosia" => "Ecosia",
    "facebook" => "Facebook",
    "instagram" => "Instagram",
    "twitter" => "Twitter",
    "x" => "Twitter",
    "reddit" => "Reddit",
    "linkedin" => "LinkedIn",
    "pinterest" => "Pinterest",
    "tiktok" => "TikTok",
    "youtube" => "YouTube",
    "t" => "Telegram"
  }

  @doc """
  Parses a referrer URL into `{domain, source}`.

  Returns `{nil, nil}` for empty/invalid referrers.

      iex> Berrypod.Analytics.Referrer.parse("https://www.google.com/search?q=test")
      {"google.com", "Google"}

      iex> Berrypod.Analytics.Referrer.parse("https://myblog.example.com/post/1")
      {"myblog.example.com", nil}

      iex> Berrypod.Analytics.Referrer.parse(nil)
      {nil, nil}

  """
  @spec parse(String.t() | nil) :: {String.t() | nil, String.t() | nil}
  def parse(nil), do: {nil, nil}
  def parse(""), do: {nil, nil}

  def parse(referrer) when is_binary(referrer) do
    case URI.parse(referrer) do
      %URI{host: host} when is_binary(host) and host != "" ->
        domain = strip_www(host)
        source = categorise(domain)
        {domain, source}

      _ ->
        {nil, nil}
    end
  end

  defp strip_www("www." <> rest), do: rest
  defp strip_www(host), do: host

  defp categorise(domain) do
    # Extract the base name from the domain (e.g. "google" from "google.co.uk")
    base =
      domain
      |> String.split(".")
      |> List.first()

    Map.get(@source_map, base)
  end
end
