import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Alert, Badge, Button, LoadingBlock, Modal, TextInput } from '@/ui'
import { WarningIcon, XCircleIcon } from '@phosphor-icons/react'
import { useCascadePreview } from '@/api/queries'
import { useCascadeCloseRecord } from '@/api/mutations'
import type { CascadeEntry, OnCloseAction } from '@/api/client'

/**
 * Cascade close confirmation dialog — Phase 3 dict-relationships-v2.
 *
 * <p>Поток:
 * <ol>
 *   <li>Открывается из existing close flow когда DELETE возвращает 409
 *       (x_references_blocked_by_dependents или x_references_cascade_required).</li>
 *   <li>Загружает preview через {@code GET /cascade-preview}.</li>
 *   <li>Если есть BLOCKERS — показывает их + объясняет что resolve first;
 *       confirm button disabled.</li>
 *   <li>Если есть только CASCADE/WARN — показывает per-source breakdown +
 *       sample 3 records per source, plus "Type CONFIRM" guard если N {@literal >} 50.</li>
 *   <li>Confirm → {@code POST /cascade-close?confirmed=true} → success message.</li>
 *   <li>Cancel → close dialog без изменений.</li>
 * </ol>
 *
 * <p>UX guards:
 * <ul>
 *   <li>"Type CONFIRM" gate когда total &gt; 50 (защита от accidental cascade).</li>
 *   <li>Reason field — optional; пустой = backend audit fields пустые.</li>
 * </ul>
 */
type Props = {
  open: boolean
  onClose: () => void
  /** Called after successful cascade close. */
  onSuccess: () => void
  dictionaryName: string
  businessKey: string | undefined
}

const onCloseVariant = (
  a: OnCloseAction,
): 'neutral' | 'warning' | 'error' => {
  if (a === 'CASCADE') return 'error'
  if (a === 'WARN') return 'warning'
  return 'neutral'
}

const SAMPLE_PER_SOURCE = 3
const CONFIRM_GATE_THRESHOLD = 50

export const CascadeConfirmDialog = ({
  open,
  onClose,
  onSuccess,
  dictionaryName,
  businessKey,
}: Props) => {
  const { t } = useTranslation()
  const preview = useCascadePreview(dictionaryName, open ? businessKey : undefined)
  const cascadeMut = useCascadeCloseRecord(dictionaryName)
  // TanStack Query гарантирует что `reset` / `mutate` стабильны между
  // renders, а сам wrapper object — нет. Экстрактим reset чтобы не
  // включать unstable mutation object в useEffect deps (infinite loop:
  // mutationObject identity → effect fires → reset → store update → render).
  const cascadeReset = cascadeMut.reset
  const [reason, setReason] = useState('')
  const [confirmText, setConfirmText] = useState('')

  // Reset state каждый раз когда dialog открывается с новой target.
  useEffect(() => {
    if (!open) {
      setReason('')
      setConfirmText('')
      cascadeReset()
    }
  }, [open, businessKey, cascadeReset])

  const plan = preview.data
  const hasBlockers = (plan?.blockers.length ?? 0) > 0
  const totalToClose = 1 + (plan?.cascade.length ?? 0)
  const requiresGate = totalToClose > CONFIRM_GATE_THRESHOLD
  const gatePassed = !requiresGate || confirmText.trim().toUpperCase() === 'CONFIRM'

  // Group cascade entries by source dict для compact display.
  const cascadeBySource = useMemo(() => {
    const map = new Map<string, CascadeEntry[]>()
    for (const e of plan?.cascade ?? []) {
      const key = `${e.sourceDict}.${e.sourceField}`
      if (!map.has(key)) map.set(key, [])
      map.get(key)!.push(e)
    }
    return Array.from(map.entries())
  }, [plan?.cascade])

  const handleConfirm = () => {
    if (!businessKey) return
    cascadeMut.mutate(
      { businessKey, reason: reason.trim() || undefined, confirmed: true },
      {
        onSuccess: () => {
          onSuccess()
          onClose()
        },
      },
    )
  }

  return (
    <Modal
      isOpen={open}
      onClose={onClose}
      title={t('cascade.title')}
      maxWidth="max-w-2xl"
    >
      <div className="space-y-4">
        {preview.isLoading && <LoadingBlock size="md" label={t('loading')} />}

        {preview.error && (
          <Alert variant="error" title={t('error.failed')}>
            {String(preview.error)}
          </Alert>
        )}

        {plan && (
          <>
            {/* Header summary */}
            <p className="text-body text-ink">
              {hasBlockers
                ? t('cascade.summary.blocked', {
                    blockers: plan.blockers.length,
                    target: businessKey,
                  })
                : t('cascade.summary.willClose', {
                    total: totalToClose,
                    target: businessKey,
                  })}
            </p>

            {/* BLOCKERS section — non-resolvable. */}
            {plan.blockers.length > 0 && (
              <Alert
                variant="error"
                title={t('cascade.blockers.title', { count: plan.blockers.length })}
              >
                <ul className="space-y-1.5 mt-2 text-cell">
                  {plan.blockers.slice(0, 5).map((b) => (
                    <li key={b.recordId} className="flex items-center gap-2">
                      <XCircleIcon weight="bold" size={12} className="text-aurora shrink-0" />
                      <span className="font-mono">
                        {b.sourceDict}/{b.businessKey}
                      </span>
                      <span className="text-mute">.{b.sourceField}</span>
                    </li>
                  ))}
                  {plan.blockers.length > 5 && (
                    <li className="text-mute">
                      {t('cascade.blockers.more', { count: plan.blockers.length - 5 })}
                    </li>
                  )}
                </ul>
                <p className="mt-2 text-cell text-ink-2">
                  {t('cascade.blockers.resolveFirst')}
                </p>
              </Alert>
            )}

            {/* CASCADE section — preview per-source. */}
            {!hasBlockers && plan.cascade.length > 0 && (
              <section className="space-y-2">
                <div className="flex items-center gap-2">
                  <WarningIcon weight="bold" size={14} className="text-horizon" />
                  <h4 className="text-body font-sans">
                    {t('cascade.cascade.title', { count: plan.cascade.length })}
                  </h4>
                </div>
                <ul className="space-y-2">
                  {cascadeBySource.map(([key, entries]) => {
                    const first = entries[0]
                    const sample = entries.slice(0, SAMPLE_PER_SOURCE)
                    const overflow = entries.length - sample.length
                    return (
                      <li
                        key={key}
                        className="border border-line rounded-sm px-3 py-2 text-cell"
                      >
                        <div className="flex items-center gap-2 mb-1">
                          <span className="font-mono text-accent">
                            {first.sourceDisplayName ?? first.sourceDict}
                          </span>
                          <span className="font-mono text-ink-2">
                            .{first.sourceField}
                          </span>
                          <Badge variant={onCloseVariant(first.onClose)}>
                            {t(`lineage.onClose.${first.onClose}`)}
                          </Badge>
                          <Badge variant="neutral">{entries.length}</Badge>
                        </div>
                        <ul className="text-cell text-ink-2 ml-1 space-y-0.5">
                          {sample.map((e) => (
                            <li key={e.recordId} className="font-mono">
                              · {e.businessKey}
                            </li>
                          ))}
                          {overflow > 0 && (
                            <li className="text-mute">
                              {t('cascade.cascade.more', { count: overflow })}
                            </li>
                          )}
                        </ul>
                      </li>
                    )
                  })}
                </ul>
              </section>
            )}

            {/* WARNINGS section — proceed but emit warnings. */}
            {!hasBlockers && plan.warnings.length > 0 && (
              <Alert
                variant="warning"
                title={t('cascade.warnings.title', { count: plan.warnings.length })}
              >
                <p className="text-cell">{t('cascade.warnings.note')}</p>
              </Alert>
            )}

            {/* Reason input — only when going to proceed. */}
            {!hasBlockers && (plan.cascade.length > 0 || plan.warnings.length > 0) && (
              <div>
                <label
                  htmlFor="cascade-reason"
                  className="text-cap text-ink-2"
                >
                  {t('cascade.reason.label')}
                </label>
                <TextInput
                  id="cascade-reason"
                  value={reason}
                  onChange={(e) => setReason(e.target.value)}
                  placeholder={t('cascade.reason.placeholder')}
                />
              </div>
            )}

            {/* Type CONFIRM gate when N > 50. */}
            {!hasBlockers && requiresGate && (
              <div>
                <label
                  htmlFor="cascade-confirm"
                  className="text-cap text-ink-2"
                >
                  {t('cascade.confirmGate.label', { word: 'CONFIRM' })}
                </label>
                <TextInput
                  id="cascade-confirm"
                  value={confirmText}
                  onChange={(e) => setConfirmText(e.target.value)}
                  placeholder="CONFIRM"
                />
              </div>
            )}

            {cascadeMut.error && (
              <Alert variant="error" title={t('error.failed')}>
                {String(cascadeMut.error)}
              </Alert>
            )}
          </>
        )}

        {/* Footer actions */}
        <div className="flex items-center justify-end gap-2 pt-2 border-t border-line">
          <Button
            variant="secondary"
            onClick={onClose}
            disabled={cascadeMut.isPending}
          >
            {t('cascade.action.cancel')}
          </Button>
          {!hasBlockers && plan && (plan.cascade.length > 0 || plan.warnings.length > 0) && (
            <Button
              variant="danger"
              onClick={handleConfirm}
              disabled={cascadeMut.isPending || !gatePassed}
              loading={cascadeMut.isPending}
            >
              {t('cascade.action.confirm', { count: totalToClose })}
            </Button>
          )}
        </div>
      </div>
    </Modal>
  )
}
