'use client'

import { useEffect, useMemo, useRef, useState } from 'react'
import { usePathname, useRouter } from 'next/navigation'

import { useI18n } from '@/components/providers/i18n-provider'
import { Button, Notice, Textarea } from '@/components/ui/controls'
import { Badge } from '@/components/ui/display'
import { api, ApiClientError } from '@/lib/api/client'
import { cn } from '@/lib/cn'

/**
 * The Copilot dock (§56–§58).
 *
 * Available everywhere and aware of where "everywhere" currently is: opened on an asset
 * page it already knows the asset, so "why is risk rising" needs no further qualification
 * and the suggested questions are the ones worth asking *here*. A context-blind assistant
 * makes the operator restate what is already on their screen, which is exactly the work
 * they wanted help with.
 *
 * It also accepts a scenario in plain language and shows what it parsed before running
 * anything (§58).
 */

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 ParsedScenario {
  events: Array<{ kind: string; label: string; labelAr: string; magnitude: number; unit: string }>
  regionCode: string | null
  durationMin: number
  unresolved: string[]
  confidence: number
  runnable: boolean
}

/** Pull an asset code out of the current path, which is the context that matters most. */
function contextFrom(pathname: string): { assetCode: string | null; area: string } {
  const asset = pathname.match(/\/assets\/([^/?]+)/)
  const area = pathname.split('/').filter(Boolean)[0] ?? 'command-center'
  return { assetCode: asset ? decodeURIComponent(asset[1]) : null, area }
}

export function CopilotDock({ canSimulate }: { canSimulate: boolean }) {
  const { t, locale } = useI18n()
  const ar = locale === 'ar'
  const pathname = usePathname()
  const router = useRouter()

  const [open, setOpen] = useState(false)
  const [question, setQuestion] = useState('')
  const [answer, setAnswer] = useState<CopilotAnswer | null>(null)
  const [parsed, setParsed] = useState<ParsedScenario | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const panelRef = useRef<HTMLDivElement>(null)

  const context = useMemo(() => contextFrom(pathname), [pathname])

  // Suggestions follow the context: on an asset page they name the asset, elsewhere they
  // ask the questions that page is for.
  const suggestions = useMemo(() => {
    const code = context.assetCode
    if (code) {
      return [
        t('copilotDock.suggest.whyRisk', { asset: code }),
        t('copilotDock.suggest.future', { asset: code }),
        t('copilotDock.suggest.minimum', { asset: code }),
        t('copilotDock.suggest.cascade', { asset: code }),
      ]
    }
    return [
      t('copilotDock.suggest.riskiest'),
      t('copilotDock.suggest.weakest'),
      t('copilotDock.suggest.compare'),
      t('copilotDock.suggest.worst'),
    ]
  }, [context.assetCode, t])

  useEffect(() => {
    if (!open) return
    const onKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') setOpen(false)
    }
    const onPointerDown = (event: MouseEvent) => {
      if (!panelRef.current?.contains(event.target as Node)) setOpen(false)
    }
    document.addEventListener('keydown', onKeyDown)
    document.addEventListener('mousedown', onPointerDown)
    return () => {
      document.removeEventListener('keydown', onKeyDown)
      document.removeEventListener('mousedown', onPointerDown)
    }
  }, [open])

  const ask = async (text: string) => {
    const value = text.trim()
    if (!value) return
    setBusy(true)
    setError(null)
    setParsed(null)
    setAnswer(null)
    try {
      // A sentence that starts with "simulate" is a scenario, not a question. Routing on
      // the verb keeps one input box for both without making the operator choose a mode.
      if (/^(simulate|run|حاكي|شغّل|شغل)/i.test(value) && canSimulate) {
        const preview = await api.post<ParsedScenario>('/api/copilot/scenario', { text: value })
        setParsed(preview)
      } else {
        setAnswer(await api.post<CopilotAnswer>('/api/copilot', { question: value }))
      }
    } catch (cause) {
      setError(
        cause instanceof ApiClientError ? (ar ? cause.failure.messageAr : cause.failure.message) : String(cause),
      )
    } finally {
      setBusy(false)
    }
  }

  const runParsed = () => {
    if (!parsed || !parsed.runnable) return
    const payload = encodeURIComponent(JSON.stringify(parsed.events))
    setOpen(false)
    router.push(`/digital-twin?panel=scenario&events=${payload}`)
  }

  return (
    <>
      <button
        type="button"
        onClick={() => setOpen((current) => !current)}
        aria-expanded={open}
        aria-label={t('copilotDock.title')}
        className={cn(
          'fixed bottom-5 z-40 flex size-12 items-center justify-center rounded-full border shadow-lg transition-colors',
          open
            ? 'border-brand bg-brand text-[#052012]'
            : 'border-brand/40 bg-surface text-brand hover:border-brand hover:bg-surface-2',
        )}
        style={{ insetInlineEnd: '1.25rem' }}
      >
        <svg viewBox="0 0 24 24" className="size-5" fill="none" stroke="currentColor" strokeWidth="1.7" aria-hidden>
          <path d="M12 3.5a8.5 8.5 0 0 0-7.2 13l-.8 3.7 3.8-.8A8.5 8.5 0 1 0 12 3.5Z" strokeLinejoin="round" />
          <path d="M9 11h6M9 14h4" strokeLinecap="round" />
        </svg>
      </button>

      {open ? (
        <div
          ref={panelRef}
          role="dialog"
          aria-label={t('copilotDock.title')}
          className="nabdh-enter nabdh-glass fixed bottom-20 z-40 flex max-h-[70vh] w-[min(24rem,calc(100vw-2rem))] flex-col overflow-hidden rounded-[--radius-panel] border shadow-2xl"
          style={{ insetInlineEnd: '1.25rem' }}
        >
          <div className="flex items-center justify-between gap-2 border-b border-border px-4 py-2.5">
            <div className="min-w-0">
              <p className="text-xs font-semibold text-text">{t('copilotDock.title')}</p>
              <p className="truncate text-[10px] text-text-faint">
                {context.assetCode
                  ? t('copilotDock.contextAsset', { asset: context.assetCode })
                  : t(`copilotDock.contextArea`, { area: t(`palette.area.${context.area}`) })}
              </p>
            </div>
            <Badge tone="muted">{t('copilotDock.local')}</Badge>
          </div>

          <div className="min-h-0 flex-1 overflow-y-auto px-4 py-3">
            {!answer && !parsed && !error ? (
              <>
                <p className="text-[11px] leading-relaxed text-text-muted">{t('copilotDock.intro')}</p>
                <ul className="mt-3 space-y-1.5">
                  {suggestions.map((suggestion) => (
                    <li key={suggestion}>
                      <button
                        type="button"
                        onClick={() => {
                          setQuestion(suggestion)
                          void ask(suggestion)
                        }}
                        className="w-full rounded-lg border border-border bg-surface-2/60 px-3 py-2 text-start text-[11px] text-text-muted transition-colors hover:border-brand/40 hover:text-text"
                      >
                        {suggestion}
                      </button>
                    </li>
                  ))}
                </ul>
              </>
            ) : null}

            {error ? <Notice tone="danger">{error}</Notice> : null}

            {answer ? (
              <div className="space-y-3">
                <p className="text-xs leading-relaxed text-text">{answer.answer}</p>
                {answer.facts.length > 0 ? (
                  <ul className="space-y-1">
                    {answer.facts.slice(0, 6).map((fact, index) => (
                      <li
                        key={`${fact.label}-${index}`}
                        className="flex items-baseline justify-between gap-3 text-[11px]"
                      >
                        <span className="text-text-muted">{fact.label}</span>
                        <span
                          className={cn(
                            'tnum font-medium',
                            fact.tone === 'critical'
                              ? 'text-critical'
                              : fact.tone === 'warning'
                                ? 'text-watch'
                                : 'text-text',
                          )}
                        >
                          {fact.value}
                        </span>
                      </li>
                    ))}
                  </ul>
                ) : null}
                {answer.links.length > 0 ? (
                  <div className="flex flex-wrap gap-2">
                    {answer.links.map((link) => (
                      <button
                        key={link.href}
                        type="button"
                        onClick={() => {
                          setOpen(false)
                          router.push(link.href)
                        }}
                        className="rounded-lg border border-border px-2 py-1 text-[10px] text-brand transition-colors hover:border-brand/50"
                      >
                        {link.label}
                      </button>
                    ))}
                  </div>
                ) : null}
                <p className="border-t border-border/60 pt-2 text-[10px] text-text-faint">
                  {t('copilotDock.basedOn')}: {answer.basedOn}
                </p>
              </div>
            ) : null}

            {parsed ? (
              <div className="space-y-3">
                <p className="text-[11px] font-medium text-text">{t('copilotDock.parsed')}</p>
                {parsed.events.length === 0 ? (
                  <p className="text-[11px] text-text-muted">{t('copilotDock.notParsed')}</p>
                ) : (
                  <ul className="space-y-1.5">
                    {parsed.events.map((event, index) => (
                      <li
                        key={`${event.kind}-${index}`}
                        className="rounded-lg border border-simulation/30 bg-simulation/8 px-2.5 py-1.5 text-[11px] text-simulation"
                      >
                        {ar ? event.labelAr : event.label}
                      </li>
                    ))}
                  </ul>
                )}
                {parsed.unresolved.length > 0 ? (
                  <p className="text-[10px] text-watch">
                    {t('copilotDock.unresolved')}: {parsed.unresolved.join(' · ')}
                  </p>
                ) : null}
                <div className="flex items-center justify-between gap-2">
                  <span className="tnum text-[10px] text-text-faint">
                    {t('confidence.title')} {Math.round(parsed.confidence)}%
                  </span>
                  <Button size="sm" onClick={runParsed} disabled={!parsed.runnable}>
                    {t('copilotDock.runScenario')}
                  </Button>
                </div>
              </div>
            ) : null}
          </div>

          <div className="border-t border-border p-3">
            <Textarea
              rows={2}
              value={question}
              onChange={(event) => setQuestion(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === 'Enter' && !event.shiftKey) {
                  event.preventDefault()
                  void ask(question)
                }
              }}
              placeholder={canSimulate ? t('copilotDock.placeholderSimulate') : t('copilotDock.placeholder')}
              aria-label={t('copilotDock.title')}
            />
            <div className="mt-2 flex items-center justify-between gap-2">
              <p className="text-[10px] text-text-faint">{t('copilotDock.hint')}</p>
              <Button size="sm" onClick={() => ask(question)} loading={busy}>
                {t('copilotDock.ask')}
              </Button>
            </div>
          </div>
        </div>
      ) : null}
    </>
  )
}
