defmodule MicrowavepropWeb.Components.SkewTChart do
  @moduledoc """
  Function component that renders a skew-T log-P diagram from a
  pressure-level profile (list of `%{"pres", "tmpc", "dwpc"}` maps).
  Returns empty output when the profile has fewer than three usable
  levels.
  """
  use Phoenix.Component

  alias MicrowavepropWeb.SkewT

  attr :profile, :list, required: true

  def skew_t_chart(assigns) do
    chart = SkewT.build(assigns.profile)
    usable_points = if chart, do: length(chart.t_points), else: 0
    assigns = assign(assigns, chart: chart, usable_points: usable_points)

    ~H"""
    <div :if={@chart && @usable_points >= 2} class="mt-3">
      <div class="text-xs font-semibold uppercase tracking-wider opacity-60 mb-1">
        Skew-T log-P
      </div>
      <svg
        viewBox={"0 0 #{@chart.width} #{@chart.height}"}
        class="w-full max-w-[600px] bg-base-100 rounded border border-base-300"
        role="img"
        aria-label="Skew-T log-P diagram"
      >
        <%!-- Plot background --%>
        <rect
          x={@chart.padding_left}
          y={@chart.padding_top}
          width={@chart.plot_width}
          height={@chart.plot_height}
          fill="currentColor"
          class="text-base-200/40"
        />

        <%!-- Clip background curves to the plot area so skewed lines
             don't bleed over the axes. --%>
        <defs>
          <clipPath id="skewt-clip">
            <rect
              x={@chart.padding_left}
              y={@chart.padding_top}
              width={@chart.plot_width}
              height={@chart.plot_height}
            />
          </clipPath>
        </defs>

        <g clip-path="url(#skewt-clip)">
          <%!-- Dry adiabats (orange curves) --%>
          <path
            :for={adiabat <- @chart.dry_adiabats}
            d={adiabat.path}
            fill="none"
            stroke="#f59e0b"
            stroke-width="0.6"
            stroke-opacity="0.45"
          />

          <%!-- Mixing ratio lines (dashed teal) --%>
          <path
            :for={line <- @chart.mixing_ratio_lines}
            d={line.path}
            fill="none"
            stroke="#0d9488"
            stroke-width="0.6"
            stroke-opacity="0.5"
            stroke-dasharray="2 3"
          />

          <%!-- Isotherms (gray) --%>
          <line
            :for={iso <- @chart.isotherms}
            x1={iso.x1}
            y1={iso.y1}
            x2={iso.x2}
            y2={iso.y2}
            stroke="currentColor"
            stroke-width="0.5"
            class="text-base-content/25"
          />

          <%!-- Isobars (gray, across plot) --%>
          <line
            :for={bar <- @chart.isobars}
            x1={bar.x_start}
            y1={bar.y}
            x2={bar.x_end}
            y2={bar.y}
            stroke="currentColor"
            stroke-width="0.5"
            class="text-base-content/25"
          />

          <%!-- Dewpoint trace --%>
          <path
            d={@chart.td_path}
            fill="none"
            stroke={@chart.dewpoint_color}
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
          <circle
            :for={{x, y} <- @chart.td_points}
            cx={x}
            cy={y}
            r="2"
            fill={@chart.dewpoint_color}
          />

          <%!-- Temperature trace --%>
          <path
            d={@chart.t_path}
            fill="none"
            stroke={@chart.temp_color}
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
          <circle
            :for={{x, y} <- @chart.t_points}
            cx={x}
            cy={y}
            r="2"
            fill={@chart.temp_color}
          />
        </g>

        <%!-- Pressure axis labels (left side) --%>
        <text
          :for={bar <- @chart.isobars}
          x={@chart.padding_left - 6}
          y={bar.label_y}
          font-size="10"
          text-anchor="end"
          fill="currentColor"
          class="text-base-content/60"
        >
          {bar.label}
        </text>

        <%!-- Temperature axis labels (bottom, only those inside the visible band) --%>
        <text
          :for={iso <- @chart.isotherms}
          :if={iso.label_x && iso.t_c >= -40 && iso.t_c <= 40 && rem(iso.t_c, 20) == 0}
          x={iso.label_x}
          y={iso.label_y}
          font-size="10"
          text-anchor="middle"
          fill="currentColor"
          class="text-base-content/60"
        >
          {iso.t_c}°C
        </text>

        <%!-- Legend --%>
        <g transform={"translate(#{@chart.padding_left + 8}, #{@chart.padding_top + 12})"}>
          <line x1="0" y1="0" x2="18" y2="0" stroke={@chart.temp_color} stroke-width="2" />
          <text x="22" y="3" font-size="10" fill="currentColor" class="text-base-content/70">
            Temperature
          </text>
          <line x1="0" y1="14" x2="18" y2="14" stroke={@chart.dewpoint_color} stroke-width="2" />
          <text x="22" y="17" font-size="10" fill="currentColor" class="text-base-content/70">
            Dewpoint
          </text>
        </g>
      </svg>
      <div class="text-[11px] opacity-60 mt-1">
        Orange curves: dry adiabats · dashed teal: saturation mixing ratio ·
        thin gray: isotherms and isobars
      </div>
    </div>
    """
  end
end
