defmodule MicrowavepropWeb.AgentSkillsController do
  @moduledoc """
  Publishes an Agent Skills Discovery (v0.2.0) index at
  `/.well-known/agent-skills/index.json` plus the referenced skill
  documents. Each document is a short markdown file describing one
  concrete task an agent can perform against this service's public
  endpoints. Digests are computed at compile time from the source files.
  """
  use MicrowavepropWeb, :controller

  @schema_url "https://agentskills.io/schemas/v0.2.0/skills.schema.json"

  @skill_sources [
    %{
      name: "fetch-contacts",
      description:
        "Retrieve every amateur-radio contact in the propagation calibration dataset as a JSON array of compact tuples.",
      path: "priv/agent-skills/fetch-contacts.md"
    },
    %{
      name: "read-algorithm",
      description:
        "Obtain the full NTMS propagation scoring algorithm documentation, including factor weights and ITU-R model references, as markdown.",
      path: "priv/agent-skills/read-algorithm.md"
    }
  ]

  for %{path: path} <- @skill_sources do
    @external_resource path
  end

  @skills Enum.map(@skill_sources, fn %{name: name, description: desc, path: path} ->
            body = File.read!(path)
            sha = :sha256 |> :crypto.hash(body) |> Base.encode16(case: :lower)
            %{name: name, description: desc, body: body, sha256: sha}
          end)

  @spec index(Plug.Conn.t(), map()) :: Plug.Conn.t()
  def index(conn, _params) do
    entries =
      Enum.map(@skills, fn s ->
        %{
          name: s.name,
          type: "text/markdown",
          description: s.description,
          url: url(conn, ~p"/.well-known/agent-skills/#{s.name}/SKILL.md"),
          sha256: s.sha256
        }
      end)

    body = Jason.encode!(%{"$schema" => @schema_url, skills: entries})

    conn
    |> put_resp_content_type("application/json")
    |> put_resp_header("cache-control", "public, max-age=3600")
    |> send_resp(200, body)
  end

  @spec skill(Plug.Conn.t(), map()) :: Plug.Conn.t()
  def skill(conn, %{"name" => name}) do
    case Enum.find(@skills, &(&1.name == name)) do
      nil ->
        send_resp(conn, 404, "")

      s ->
        conn
        |> put_resp_content_type("text/markdown", "utf-8")
        |> put_resp_header("cache-control", "public, max-age=3600")
        |> send_resp(200, s.body)
    end
  end
end
