defmodule Berrypod.Analytics.UAParser do
  @moduledoc """
  Lightweight user agent parsing — extracts browser and OS names.

  No external dependencies. Handles 95%+ of real-world traffic correctly.
  Order matters: more specific checks (Edge before Chrome, iOS before macOS) come first.
  """

  @doc """
  Returns `{browser, os}` tuple from a user agent string.

      iex> Berrypod.Analytics.UAParser.parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
      {"Chrome", "macOS"}

  """
  @spec parse(String.t()) :: {String.t(), String.t()}
  def parse(ua) when is_binary(ua) do
    {parse_browser(ua), parse_os(ua)}
  end

  def parse(_), do: {"Other", "Other"}

  defp parse_browser(ua) do
    cond do
      String.contains?(ua, "bot") or String.contains?(ua, "Bot") or
        String.contains?(ua, "crawl") or String.contains?(ua, "Crawl") or
        String.contains?(ua, "spider") or String.contains?(ua, "Spider") ->
        "Bot"

      String.contains?(ua, "Firefox/") ->
        "Firefox"

      String.contains?(ua, "Edg/") ->
        "Edge"

      String.contains?(ua, "OPR/") or String.contains?(ua, "Opera") ->
        "Opera"

      String.contains?(ua, "Chrome/") ->
        "Chrome"

      String.contains?(ua, "Safari/") ->
        "Safari"

      true ->
        "Other"
    end
  end

  defp parse_os(ua) do
    cond do
      String.contains?(ua, "iPhone") or String.contains?(ua, "iPad") or
          String.contains?(ua, "iPod") ->
        "iOS"

      String.contains?(ua, "Android") ->
        "Android"

      String.contains?(ua, "Mac OS X") or String.contains?(ua, "Macintosh") ->
        "macOS"

      String.contains?(ua, "Windows") ->
        "Windows"

      String.contains?(ua, "Linux") ->
        "Linux"

      String.contains?(ua, "CrOS") ->
        "ChromeOS"

      true ->
        "Other"
    end
  end
end
