'use client'

import { useState } from 'react'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { stateName } from '@/lib/domain/states'
import { getStateProvisions, hasStateSheet } from '@/lib/demo/state-info-data'
import {
  STATE_INFO_TOPIC_META,
  adjacentTopic,
  isTermList,
  topicMeta,
  topicRuleCount,
  type StateInfoSection,
  type StateInfoTopicKey,
} from '@/lib/domain/state-info'

/**
 * State information — every screen that shows it (Nash, 2026-09-25:
 * "currently the design we have on the HHA of state info is not easy to
 * navigate and read", then "apply the same thing for the freight broker
 * dashboard and for the pilot dashboard… and the updated design for the
 * mobile version").
 *
 * What changed, and why:
 *   • The six topics were a wrapping row of pills above a single paragraph.
 *     They are now a list down the side, each with what it answers and how
 *     many rules it holds, so the dispatcher can see where the answer lives
 *     before clicking.
 *   • A topic was one block of prose. It is now the shape the rules are
 *     actually written in — headed groups, and inside a group a condition and
 *     what it requires. "Over 14′ wide — 2 escorts" belongs in two columns,
 *     not in a sentence.
 *   • The numbers are the reason anyone opens this, so the condition column is
 *     set in tabular figures and never wraps away from its requirement.
 *
 *   • On a phone the rail would leave the content a sliver, so below `sm` the
 *     topics become a single scrolling row of chips and the content takes the
 *     full width. Same component, same content, one breakpoint.
 *
 * Used by the freight broker and carrier dispatch trip views, the pilot
 * company assignment view, the carrier driver app and the pilot driver app.
 */

/* ----------------------------------------------------------------- icons */

const ICON: Record<StateInfoTopicKey, React.ReactNode> = {
  travel: (
    <>
      <path d="M4 20 8 4M20 20 16 4" />
      <path d="M12 5v2M12 11v2M12 17v2" />
    </>
  ),
  escort: (
    <>
      <rect x="2" y="12" width="9" height="6" rx="1.5" />
      <rect x="14" y="9" width="8" height="9" rx="1.5" />
      <path d="M4.5 18v1.5M8.5 18v1.5M16.5 18v1.5M19.5 18v1.5" />
    </>
  ),
  permit_limits: (
    <>
      <rect x="5" y="3" width="14" height="18" rx="2" />
      <path d="M9 8h6M9 12h6M9 16h3" />
    </>
  ),
  legal_limits: (
    <>
      <path d="M12 4v16" />
      <path d="M5 8h14" />
      <path d="M5 8 3 14h4zM19 8l-2 6h4z" />
    </>
  ),
  signs: (
    <>
      <path d="M12 3 21 8v8l-9 5-9-5V8z" />
      <path d="M12 9v6" />
    </>
  ),
  superloads: (
    <>
      <circle cx="12" cy="12" r="8" />
      <path d="M12 12 16 9" />
      <path d="M12 4v1.5M20 12h-1.5M12 20v-1.5M4 12h1.5" />
    </>
  ),
}

function TopicIcon({ topic, className = '' }: { topic: StateInfoTopicKey; className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.6"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
      aria-hidden="true"
    >
      {ICON[topic]}
    </svg>
  )
}

/* ----------------------------------------------------------------- body */

function Section({ section }: { section: StateInfoSection }) {
  const twoColumn = isTermList(section)
  return (
    <section className="border-t border-neutral-100 pt-3 first:border-t-0 first:pt-0">
      {section.heading && (
        <h4 className="text-[11px] font-bold uppercase tracking-[0.09em] text-neutral-500">{section.heading}</h4>
      )}
      {section.note && <p className="mt-1.5 text-[13px] leading-relaxed text-neutral-500">{section.note}</p>}
      {twoColumn ? (
        <dl className="mt-2 space-y-1.5">
          {section.items.map((item, i) => (
            <div key={i} className="grid grid-cols-[minmax(6.5rem,10rem)_1fr] gap-x-3 gap-y-0.5 max-[420px]:grid-cols-1">
              {/* Tabular figures keep 14′ and 110,000 lined up down the column. */}
              <dt className="text-[13px] font-semibold tabular-nums text-neutral-900">{item.term}</dt>
              <dd className="text-[13px] leading-relaxed text-neutral-600">{item.detail}</dd>
            </div>
          ))}
        </dl>
      ) : (
        <ul className="mt-2 space-y-1.5">
          {section.items.map((item, i) => (
            <li key={i} className="flex gap-2 text-[13px] leading-relaxed text-neutral-600">
              <span aria-hidden="true" className="mt-[7px] h-1 w-1 shrink-0 rounded-full bg-neutral-300" />
              <span>
                {item.term && <span className="font-semibold text-neutral-900">{item.term}: </span>}
                {item.detail}
              </span>
            </li>
          ))}
        </ul>
      )}
    </section>
  )
}

/* ------------------------------------------------------------- the view */

export function StateInfoView({
  code,
  /** `compact` is a narrow slide-in; `full` is everywhere else. */
  variant = 'full',
  /**
   * `auto` switches on the viewport: chips on a phone, the rail from `sm` up.
   * `stacked` keeps the chips at every width — for the driver apps, which draw
   * a 420px phone frame even on a desktop, where a viewport-width breakpoint
   * would put the rail inside a column too narrow to hold it.
   */
  layout = 'auto',
}: {
  code: string
  variant?: 'compact' | 'full'
  layout?: 'auto' | 'stacked'
}) {
  const [topic, setTopic] = useState<StateInfoTopicKey>('travel')
  const provisions = getStateProvisions(code)
  const meta = topicMeta(topic)
  const sections = provisions[topic] ?? []
  const prev = adjacentTopic(topic, -1)
  const next = adjacentTopic(topic, 1)
  const wide = variant === 'full'
  const stacked = layout === 'stacked'

  return (
    <div className={`flex min-h-0 flex-1 flex-col overflow-hidden ${stacked ? '' : 'sm:flex-row'}`}>
      {/* Phone: one scrolling row of chips. A 172px rail beside 200px of
          content is unreadable, and the driver apps are phone-first. */}
      <nav
        aria-label="State information topics"
        className={`flex shrink-0 gap-1.5 overflow-x-auto border-b bg-neutral-50/70 px-2 py-2 ${stacked ? '' : 'sm:hidden'}`}
      >
        {STATE_INFO_TOPIC_META.map((t) => {
          const active = t.key === topic
          const count = topicRuleCount(provisions[t.key])
          return (
            <button
              key={t.key}
              type="button"
              onClick={() => setTopic(t.key)}
              aria-current={active ? 'true' : undefined}
              className={`flex shrink-0 items-center gap-1.5 rounded-full border px-3 py-1.5 text-[12px] font-semibold transition ${
                active ? 'border-[#0f1b2d] bg-[#0f1b2d] text-white' : 'border-neutral-200 bg-white text-neutral-600'
              }`}
            >
              <TopicIcon topic={t.key} className={`h-3.5 w-3.5 ${active ? 'text-[#f5a623]' : 'text-neutral-400'}`} />
              {t.label}
              <span className={`tabular-nums ${active ? 'text-neutral-400' : 'text-neutral-300'}`}>{count}</span>
            </button>
          )
        })}
      </nav>

      {/* Tablet and up: the rail, with what each topic answers. */}
      <nav
        aria-label="State information topics"
        className={`hidden shrink-0 flex-col gap-0.5 overflow-y-auto border-r bg-neutral-50/70 p-1.5 ${stacked ? '' : 'sm:flex'} ${wide ? 'w-[172px]' : 'w-[126px]'}`}
      >
        {STATE_INFO_TOPIC_META.map((t) => {
          const active = t.key === topic
          const count = topicRuleCount(provisions[t.key])
          return (
            <button
              key={t.key}
              type="button"
              onClick={() => setTopic(t.key)}
              aria-current={active ? 'true' : undefined}
              className={`group flex items-start gap-2 rounded-lg px-2 py-2 text-left transition ${
                active ? 'bg-[#0f1b2d] text-white' : 'text-neutral-600 hover:bg-white hover:text-neutral-900'
              }`}
            >
              <TopicIcon
                topic={t.key}
                className={`mt-px h-4 w-4 shrink-0 ${active ? 'text-[#f5a623]' : 'text-neutral-400 group-hover:text-neutral-600'}`}
              />
              <span className="min-w-0">
                <span className="block text-[12px] font-semibold leading-tight">{t.label}</span>
                {wide && (
                  <span className={`mt-0.5 block text-[10.5px] leading-snug ${active ? 'text-neutral-300' : 'text-neutral-400'}`}>
                    {t.blurb}
                  </span>
                )}
                <span className={`mt-0.5 block text-[10px] tabular-nums ${active ? 'text-neutral-400' : 'text-neutral-400'}`}>
                  {count} {count === 1 ? 'rule' : 'rules'}
                </span>
              </span>
            </button>
          )
        })}
      </nav>

      <div className="flex min-h-0 min-w-0 flex-1 flex-col">
        <div className="min-h-0 flex-1 overflow-y-auto px-4 py-3">
          <div className="flex items-baseline gap-2">
            <h3 className="text-[15px] font-bold text-neutral-900">{meta.label}</h3>
            <p className="text-[11px] text-neutral-400">{meta.blurb}</p>
          </div>
          <div className="mt-3 space-y-3">
            {sections.length === 0 ? (
              <p className="text-[13px] text-neutral-500">Nothing published for this topic yet.</p>
            ) : (
              sections.map((s, i) => <Section key={i} section={s} />)
            )}
          </div>
          <p className="mt-4 border-t border-neutral-100 pt-3 text-[11px] leading-relaxed text-neutral-400">
            {hasStateSheet(code)
              ? `${stateName(code)} state information as published by the permit provider. The permit issued for this load is still the controlling document.`
              : 'General guidance until this state’s information is connected. The permit issued for this load is the controlling document.'}
          </p>
        </div>

        {/* Reading the six in order is the common path, so it gets a button. */}
        <div className="flex items-center justify-between gap-2 border-t bg-white px-3 py-2">
          <button
            type="button"
            disabled={!prev}
            onClick={() => prev && setTopic(prev)}
            className="rounded-lg border px-2.5 py-1.5 text-[11px] font-semibold text-neutral-700 transition hover:bg-neutral-50 disabled:opacity-40"
          >
            ← {prev ? topicMeta(prev).label : 'Back'}
          </button>
          <button
            type="button"
            disabled={!next}
            onClick={() => next && setTopic(next)}
            className="rounded-lg bg-[#0f1b2d] px-2.5 py-1.5 text-[11px] font-bold text-white transition hover:bg-[#1c2d47] disabled:opacity-40"
          >
            {next ? topicMeta(next).label : 'End'} →
          </button>
        </div>
      </div>
    </div>
  )
}

/**
 * "View state info" on the driver apps, the pilot assignment view, and any
 * trip view too narrow for the panel. `code` null = closed.
 *
 * `inAppFrame` is for the two driver apps: they draw a 420px phone with a
 * bezel and stay that width on a desktop, so the dialog matches the phone
 * rather than spilling past its edges (Nash, 2026-09-25: "make sure that
 * popup model is not going to be wider than the actual driver app edges").
 */
export function StateInfoDialog({
  code,
  onClose,
  inAppFrame = false,
}: {
  code: string | null
  onClose: () => void
  inAppFrame?: boolean
}) {
  return (
    <Dialog open={!!code} onOpenChange={(open) => !open && onClose()}>
      <DialogContent
        className={`flex h-[88vh] max-h-[88vh] flex-col overflow-hidden p-0 ${inAppFrame ? 'w-[calc(100%-2rem)] sm:max-w-[420px]' : 'sm:max-w-2xl'}`}
      >
        <DialogHeader className="border-b px-4 py-3">
          <DialogTitle className="text-base">
            {code ? stateName(code) || code : ''}{' '}
            <span className="text-sm font-normal text-neutral-400">state information</span>
          </DialogTitle>
        </DialogHeader>
        {code && <StateInfoView code={code} layout={inAppFrame ? 'stacked' : 'auto'} />}
      </DialogContent>
    </Dialog>
  )
}
