'use client'

import { useEffect, useRef, useState, type FormEvent } from 'react'
import Link from 'next/link'

import { useI18n } from '@/components/providers/i18n-provider'
import { Button, Input, Notice } from '@/components/ui/controls'
import { Badge, EmptyState, Panel, PanelBody, PanelHeader } from '@/components/ui/display'
import { IconCopilot } from '@/components/ui/icons'
import { ApiClientError, api, failureMessage } from '@/lib/api/client'
import { cn } from '@/lib/cn'

interface CopilotFact {
  label: string
  value: string
  tone?: 'normal' | 'warning' | 'critical'
}

interface CopilotAnswer {
  intent: string
  answer: string
  facts: CopilotFact[]
  links: Array<{ label: string; href: string }>
  basedOn: string
  permissionDenied?: boolean
}

interface Turn {
  id: number
  question: string
  answer: CopilotAnswer | null
  error?: string
}

const EXAMPLE_KEYS = [
  'riskiest',
  'whyRiyadh',
  'twoHours',
  'whatIf',
  'reduce',
  'critical',
  'compare',
  'heatwave',
] as const

/**
 * The Copilot conversation.
 *
 * Every answer carries a "based on" line naming the engine that produced it. That is
 * deliberate: an assistant that cannot show its source in a control room is a liability,
 * and this one always can, because it only ever reports the output of a computation.
 */
export function CopilotChat() {
  const { t, locale } = useI18n()

  const [question, setQuestion] = useState('')
  const [turns, setTurns] = useState<Turn[]>([])
  const [busy, setBusy] = useState(false)
  const endRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    endRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })
  }, [turns])

  const ask = async (text: string) => {
    const trimmed = text.trim()
    if (trimmed.length < 2 || busy) return

    const id = Date.now()
    setTurns((current) => [...current, { id, question: trimmed, answer: null }])
    setQuestion('')
    setBusy(true)

    try {
      const answer = await api.post<CopilotAnswer>('/api/copilot', { question: trimmed })
      setTurns((current) => current.map((turn) => (turn.id === id ? { ...turn, answer } : turn)))
    } catch (caught) {
      const message =
        caught instanceof ApiClientError
          ? failureMessage(caught.failure, locale)
          : t('common.serverError')
      setTurns((current) =>
        current.map((turn) => (turn.id === id ? { ...turn, error: message } : turn)),
      )
    } finally {
      setBusy(false)
    }
  }

  const onSubmit = (event: FormEvent) => {
    event.preventDefault()
    void ask(question)
  }

  return (
    <div className="grid gap-6 xl:grid-cols-[1fr_300px]">
      <Panel className="flex min-h-[560px] flex-col">
        <PanelHeader
          title={t('copilot.title')}
          subtitle={t('copilot.subtitle')}
          icon={<IconCopilot className="size-4" />}
          action={
            turns.length > 0 ? (
              <Button size="sm" variant="ghost" onClick={() => setTurns([])}>
                {t('copilot.clear')}
              </Button>
            ) : null
          }
        />

        <div className="flex-1 space-y-4 overflow-y-auto p-4 sm:p-5">
          {turns.length === 0 ? (
            <EmptyState title={t('copilot.empty')} body={t('copilot.scopeNote')} />
          ) : (
            turns.map((turn) => (
              <div key={turn.id} className="space-y-3">
                <div className="flex justify-end">
                  <p className="max-w-[85%] rounded-2xl rounded-ee-sm border border-brand/30 bg-brand/10 px-4 py-2.5 text-sm text-text">
                    {turn.question}
                  </p>
                </div>

                {turn.error ? (
                  <Notice tone="danger">{turn.error}</Notice>
                ) : turn.answer ? (
                  <div className="nabdh-enter max-w-[92%] rounded-2xl rounded-es-sm border border-border bg-surface-2/60 px-4 py-3.5">
                    {turn.answer.permissionDenied ? (
                      <Badge tone="neutral" className="mb-2">
                        {t('common.permissionDenied')}
                      </Badge>
                    ) : null}

                    <p className="text-sm leading-relaxed text-text">{turn.answer.answer}</p>

                    {turn.answer.facts.length > 0 ? (
                      <dl className="mt-3 grid gap-1.5 sm:grid-cols-2">
                        {turn.answer.facts.map((fact, index) => (
                          <div
                            key={`${fact.label}-${index}`}
                            className="flex items-baseline justify-between gap-3 rounded-lg border border-border bg-surface/50 px-2.5 py-1.5"
                          >
                            <dt className="truncate text-[11px] text-text-muted">{fact.label}</dt>
                            <dd
                              className={cn(
                                'tnum shrink-0 text-xs font-medium',
                                fact.tone === 'critical'
                                  ? 'text-critical'
                                  : fact.tone === 'warning'
                                    ? 'text-warning'
                                    : 'text-text',
                              )}
                            >
                              {fact.value}
                            </dd>
                          </div>
                        ))}
                      </dl>
                    ) : null}

                    <div className="mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 border-t border-border/60 pt-2.5">
                      <span className="text-[10px] text-text-faint">
                        {t('copilot.basedOn')}: {turn.answer.basedOn}
                      </span>
                      {turn.answer.links.map((link) => (
                        <Link
                          key={link.href}
                          href={link.href}
                          className="text-[11px] font-medium text-brand hover:underline"
                        >
                          {link.label} →
                        </Link>
                      ))}
                    </div>
                  </div>
                ) : (
                  <div className="flex items-center gap-2 text-xs text-text-muted">
                    <span className="size-3 animate-spin rounded-full border-2 border-brand border-t-transparent" />
                    {t('copilot.thinking')}
                  </div>
                )}
              </div>
            ))
          )}
          <div ref={endRef} />
        </div>

        <form onSubmit={onSubmit} className="flex gap-2 border-t border-border p-4">
          <Input
            value={question}
            onChange={(event) => setQuestion(event.target.value)}
            placeholder={t('copilot.placeholder')}
            aria-label={t('copilot.placeholder')}
            disabled={busy}
          />
          <Button type="submit" loading={busy} disabled={question.trim().length < 2}>
            {t('copilot.send')}
          </Button>
        </form>
      </Panel>

      <Panel className="self-start">
        <PanelHeader title={t('copilot.suggestions')} />
        <PanelBody className="space-y-1.5">
          {EXAMPLE_KEYS.map((key) => (
            <button
              key={key}
              type="button"
              onClick={() => ask(t(`copilot.examples.${key}`))}
              disabled={busy}
              className="w-full rounded-lg border border-border bg-surface-2/40 px-3 py-2.5 text-start text-xs leading-relaxed text-text-muted transition-colors hover:border-brand/40 hover:text-text disabled:opacity-50"
            >
              {t(`copilot.examples.${key}`)}
            </button>
          ))}

          <p className="mt-4 border-t border-border pt-4 text-[11px] leading-relaxed text-text-faint">
            {t('copilot.scopeNote')}
          </p>
        </PanelBody>
      </Panel>
    </div>
  )
}
