'use client'

import { useState } from 'react'

import { Badge, Panel, PanelBody, PanelHeader } from '@/components/ui/display'
import { useI18n } from '@/components/providers/i18n-provider'
import { formatNumber } from '@/lib/i18n/translate'
import { cn } from '@/lib/cn'

/**
 * The uncertainty display (§15, §16, §17).
 *
 * Replaces "failure in 43 minutes" with the shape of the belief: how likely, how soon,
 * how wide the window, and how confident — with the four confidences kept apart because
 * they degrade for different reasons and call for different responses.
 *
 * The window is drawn as a band with the estimate marked inside it rather than as a gauge.
 * A gauge implies a single value is being measured; a band says what it means, which is
 * that the answer is a range.
 */

export interface UncertaintyView {
  probability: number
  expectedMinutes: number | null
  windowLowMinutes: number | null
  windowHighMinutes: number | null
  predictionConfidence: number
  dataConfidence: number
  modelConfidence: number
  physicsConfidence: number
  twinFidelity: number
  rawConfidence: number
  degradedBy: number
  degradeReason: string
  degradeReasonAr: string
  components: Array<{ key: string; value: number; weight: number; label: string; labelAr: string }>
}

function band(value: number): 'normal' | 'watch' | 'warning' | 'critical' {
  if (value >= 80) return 'normal'
  if (value >= 65) return 'watch'
  if (value >= 45) return 'warning'
  return 'critical'
}

const TONE: Record<string, string> = {
  normal: 'text-normal',
  watch: 'text-watch',
  warning: 'text-warning',
  critical: 'text-critical',
}

const BAR: Record<string, string> = {
  normal: 'bg-normal',
  watch: 'bg-watch',
  warning: 'bg-warning',
  critical: 'bg-critical',
}

export function UncertaintyPanel({ view }: { view: UncertaintyView }) {
  const { t, locale } = useI18n()
  const [open, setOpen] = useState(false)
  const num = (value: number, digits = 0) =>
    formatNumber(locale, value, { maximumFractionDigits: digits })

  const hasWindow =
    view.expectedMinutes !== null &&
    view.windowLowMinutes !== null &&
    view.windowHighMinutes !== null

  // Where the estimate sits inside its own window, as a share. Guarded because a window
  // of zero width would otherwise divide by nothing.
  const span = hasWindow ? view.windowHighMinutes! - view.windowLowMinutes! : 0
  const markerPct = span > 0 ? ((view.expectedMinutes! - view.windowLowMinutes!) / span) * 100 : 50

  return (
    <Panel>
      <PanelHeader
        title={t('uncertainty.title')}
        subtitle={t('uncertainty.subtitle')}
        action={
          <Badge tone={view.degradedBy > 0 ? 'accent' : 'brand'} dot>
            {view.degradedBy > 0 ? t('uncertainty.degraded') : t('uncertainty.nominal')}
          </Badge>
        }
      />
      <PanelBody className="space-y-4">
        {/* ── The headline: probability, then the window ───────────────────── */}
        <div className="grid gap-3 sm:grid-cols-2">
          <div className="min-w-0 rounded-lg border border-border bg-surface-2/60 p-3">
            <p className="text-[11px] text-text-muted">{t('uncertainty.probability')}</p>
            <p className="mt-1 font-mono text-2xl font-semibold tabular-nums">
              {num(view.probability)}%
            </p>
          </div>
          <div className="min-w-0 rounded-lg border border-border bg-surface-2/60 p-3">
            <p className="text-[11px] text-text-muted">{t('uncertainty.expected')}</p>
            <p className="mt-1 font-mono text-2xl font-semibold tabular-nums">
              {hasWindow ? `~${num(view.expectedMinutes!)} ${t('common.minShort')}` : '—'}
            </p>
          </div>
        </div>

        {hasWindow ? (
          <div>
            <div className="flex items-baseline justify-between gap-2 text-[11px] text-text-muted">
              <span>{t('uncertainty.window')}</span>
              <span className="font-mono tabular-nums">
                {num(view.windowLowMinutes!)}–{num(view.windowHighMinutes!)} {t('common.minShort')}
              </span>
            </div>
            {/* The band, with the estimate marked inside it. */}
            <div className="relative mt-2 h-3 rounded-full border border-border bg-surface-3">
              <div className="absolute inset-y-0 inset-x-0 rounded-full bg-ai/25" />
              <div
                className="absolute top-1/2 h-4 w-0.5 -translate-y-1/2 rounded-full bg-ai"
                style={{ insetInlineStart: `${Math.min(98, Math.max(2, markerPct))}%` }}
                aria-hidden
              />
            </div>
            <p className="mt-1.5 text-[11px] text-text-faint">{t('uncertainty.windowNote')}</p>
          </div>
        ) : (
          <p className="rounded-lg border border-border bg-surface-2/40 px-3 py-2 text-[11px] leading-relaxed text-text-muted">
            {t('uncertainty.noCrossing')}
          </p>
        )}

        {/* ── The four confidences, kept apart ─────────────────────────────── */}
        <div className="grid gap-2 sm:grid-cols-2">
          {(
            [
              ['uncertainty.predictionConfidence', view.predictionConfidence],
              ['uncertainty.dataConfidence', view.dataConfidence],
              ['uncertainty.modelConfidence', view.modelConfidence],
              ['uncertainty.twinFidelity', view.twinFidelity],
            ] as const
          ).map(([key, value]) => (
            <div key={key} className="min-w-0">
              <div className="flex items-baseline justify-between gap-2 text-[11px]">
                <span className="truncate text-text-muted">{t(key)}</span>
                <span className={cn('font-mono tabular-nums', TONE[band(value)])}>
                  {num(value)}%
                </span>
              </div>
              <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-surface-3">
                <div
                  className={cn('h-full rounded-full', BAR[band(value)])}
                  style={{ width: `${Math.max(2, Math.min(100, value))}%` }}
                />
              </div>
            </div>
          ))}
        </div>

        {/* ── Degradation, when there is any (§17) ─────────────────────────── */}
        {view.degradedBy > 0 ? (
          <div className="rounded-lg border border-warning/30 bg-warning/8 px-3 py-2">
            <p className="text-[11px] font-medium text-warning">
              {t('uncertainty.reducedFrom')} {num(view.rawConfidence)}% →{' '}
              {num(view.predictionConfidence)}%
            </p>
            <p className="mt-0.5 text-[11px] leading-relaxed text-text-muted">
              {locale === 'ar' ? view.degradeReasonAr : view.degradeReason}
            </p>
          </div>
        ) : null}

        {/* ── Why this confidence? (§16) ───────────────────────────────────── */}
        <div>
          <button
            type="button"
            onClick={() => setOpen((value) => !value)}
            aria-expanded={open}
            className="w-full rounded-lg border border-border bg-surface-2/60 px-3 py-2 text-start text-[11px] font-medium text-text transition-colors hover:bg-surface-3"
          >
            {open ? t('uncertainty.hideWhy') : t('uncertainty.why')}
          </button>

          {open ? (
            <ul className="mt-2 space-y-1.5">
              {[...view.components]
                .sort((a, b) => b.weight - a.weight)
                .map((component) => (
                  <li key={component.key} className="flex items-center gap-2 text-[11px]">
                    <span className="min-w-0 flex-1 truncate text-text-muted">
                      {locale === 'ar' ? component.labelAr : component.label}
                    </span>
                    <span className="shrink-0 font-mono tabular-nums text-text-faint">
                      ×{formatNumber(locale, component.weight, { maximumFractionDigits: 2 })}
                    </span>
                    <span
                      className={cn(
                        'w-12 shrink-0 text-end font-mono tabular-nums',
                        TONE[band(component.value)],
                      )}
                    >
                      {num(component.value)}%
                    </span>
                  </li>
                ))}
            </ul>
          ) : null}
        </div>
      </PanelBody>
    </Panel>
  )
}
