defmodule ToweropsWeb.Plugs.SecurityHeaders do
  @moduledoc """
  Adds security headers to all responses in production.

  Headers added:
  - Content-Security-Policy: Restricts resource loading to prevent XSS
  - X-Frame-Options: Prevents clickjacking attacks
  - X-Content-Type-Options: Prevents MIME type sniffing
  - Referrer-Policy: Controls referrer information leakage

  These headers are only applied in production to avoid interfering with
  development tools like LiveReload.
  """

  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    if Application.get_env(:towerops, :env) == :prod do
      conn
      |> put_resp_header("content-security-policy", csp_header())
      |> put_resp_header("x-frame-options", "SAMEORIGIN")
      |> put_resp_header("x-content-type-options", "nosniff")
      |> put_resp_header("referrer-policy", "strict-origin-when-cross-origin")
    else
      conn
    end
  end

  # Content Security Policy
  # - default-src 'self': Only load resources from same origin by default
  # - script-src: Allow inline scripts (needed for LiveView), eval, and self
  # - style-src: Allow inline styles (needed for Tailwind), unsafe-hashes, and self
  # - img-src: Allow images from self, data URIs, and https
  # - font-src: Allow fonts from self and data URIs
  # - connect-src: Allow WebSocket connections for LiveView
  # - frame-ancestors: Same as X-Frame-Options (SAMEORIGIN)
  defp csp_header do
    Enum.join(
      [
        "default-src 'self'",
        "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
        "style-src 'self' 'unsafe-inline' 'unsafe-hashes'",
        "img-src 'self' data: https:",
        "font-src 'self' data:",
        "connect-src 'self' ws: wss:",
        "frame-ancestors 'self'"
      ],
      "; "
    )
  end
end
