import { useMemo } from 'react'
import { Link } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { ClockCounterClockwiseIcon, MapTrifoldIcon, DownloadSimpleIcon, ArrowRightIcon } from '@phosphor-icons/react'
import { useDictionaryDependents } from '@/api/queries'
import type { DataScope, DictionaryDetail, OnCloseAction, SchemaDependent } from '@/api/client'
import { cn } from '@/lib/utils'

/** Scope badge — solid scope-color bg per redesign prototype. */
const SCOPE_BADGE_CLASS: Record<DataScope, string> = {
  PUBLIC: 'bg-accent-bg text-accent',
  INTERNAL: 'bg-warn-bg text-warn',
  RESTRICTED: 'bg-pink-bg text-pink',
}

/**
 * EditorInfoPanel — left rail с dict metadata per handoff prototype Screen 2.
 *
 * <p>Содержимое (top → bottom):
 * <ul>
 *   <li>Scope badge (PUBLIC/INTERNAL/RESTRICTED)</li>
 *   <li>ОПИСАНИЕ caption + description text</li>
 *   <li>BUNDLE / ВЕРСИЯ / ЗАПИСЕЙ / ЛОКАЛИ metadata grid</li>
 *   <li>СВЯЗИ — → ссылается (outgoing FK names) + ← используют (incoming dict names)</li>
 * </ul>
 *
 * <p>Action buttons (Экспорт / Time-travel) идут в PageHeader actions slot,
 * не в info panel — handoff prototype показывает им в info panel но семантика
 * редизайна: actions около title для discoverability.
 */
export type EditorInfoPanelProps = {
  detail: DictionaryDetail
  recordCount: number
  /** Optional action buttons (Time-travel / AOI / Export) — bottom of panel
   * per redesign prototype. Toggle handlers come from route's state. */
  actions?: {
    onTimeTravel?: () => void
    timeTravelActive?: boolean
    onAoi?: () => void
    aoiActive?: boolean
    onExport?: () => void
    exportPending?: boolean
  }
  /** Optional banner slot — WorkflowBanner / status notices живут в
   * left panel per user feedback ("плашки пусть в левой панели будут").
   * Renders at top of panel before scope chip. */
  banner?: React.ReactNode
}

export function EditorInfoPanel({ detail, recordCount, actions, banner }: EditorInfoPanelProps) {
  const { t } = useTranslation()
  const { data: refByRaw } = useDictionaryDependents(detail.name)

  const outgoingNames = useMemo(() => extractOutgoingFk(detail.schemaJson), [detail.schemaJson])
  const incomingDeps: SchemaDependent[] = useMemo(() => refByRaw ?? [], [refByRaw])

  return (
    // Flex-col panel — stretches to full grid row height (no self-start).
    // Actions block при наличии actions получает `mt-auto` чтобы прижаться к
    // нижнему краю panel — per user feedback "всегда одной высоты".
    <aside className="flex flex-col space-y-4 rounded-lg border border-line bg-surface p-4 min-h-full min-w-0 overflow-hidden">
      {/* Banner slot — WorkflowBanner status notice (if any). */}
      {banner}

      {/* Scope badge — top of panel */}
      <span
        className={cn(
          'inline-flex items-center px-2.5 py-1 rounded-md text-cap tracking-[0.16em] font-semibold uppercase',
          SCOPE_BADGE_CLASS[detail.scope],
        )}
      >
        {detail.scope}
      </span>

      {/* Description — break-words нужен потому что описания могут быть
        * без spaces (slash-separated lists типа "LZW/Deflate/JPEG2000") и
        * вылезают за границы narrow panel'а. `break-words` breaks при
        * необходимости anywhere; `overflow-hidden` clip'нет если что-то
        * unbreakable. */}
      {detail.description && (
        <Section label={t('editor.info.description', { defaultValue: 'Описание' })}>
          <p className="text-body text-ink-2 leading-relaxed break-words overflow-hidden">{detail.description}</p>
        </Section>
      )}

      {/* Metadata grid */}
      <div className="grid grid-cols-2 gap-x-3 gap-y-3">
        <MetaCell label={t('editor.info.bundle', { defaultValue: 'Bundle' })}>
          <span className="text-mono text-ink-2">{detail.bundle}</span>
        </MetaCell>
        <MetaCell label={t('editor.info.version', { defaultValue: 'Версия' })}>
          <span className="text-mono text-ink-2">v{detail.schemaVersion}</span>
        </MetaCell>
        <MetaCell label={t('editor.info.records', { defaultValue: 'Записей' })}>
          <span className="text-mono text-ink-2 tabular-nums">{recordCount}</span>
        </MetaCell>
        <MetaCell label={t('editor.info.locales', { defaultValue: 'Локали' })}>
          <span className="text-mono text-ink-2">{detail.supportedLocales.join(', ')}</span>
        </MetaCell>
      </div>

      {/* Relations — merged inline DictionaryDependentsPanel в InfoPanel.
        * → ссылается: outgoing FK targets (имя dict, links).
        * ← используют: incoming FK rows с field path + active count + policy chip
        *   (BLOCK / WARN / CASCADE). Это replaces standalone reverse-FK card
        *   which раньше висел над records table. */}
      {(outgoingNames.length > 0 || incomingDeps.length > 0) && (
        <Section
          label={t('editor.info.relations', {
            defaultValue: 'Связи',
            count: outgoingNames.length + incomingDeps.length,
          })}
        >
          {outgoingNames.length > 0 && (
            <div className="space-y-1.5 mb-3">
              {/* Per prototype: section subhead "→ ссылается" — plain body
                * font Inter mute, lowercase (НЕ Tektur uppercase cap). */}
              <div className="text-body text-mute">
                → {t('editor.info.outgoing', { defaultValue: 'ссылается' })}
              </div>
              <ul className="space-y-0.5">
                {outgoingNames.map((name) => (
                  <li key={name}>
                    <Link
                      to="/dictionaries/$name"
                      params={{ name }}
                      className="text-mono text-accent hover:underline"
                    >
                      {name}
                    </Link>
                  </li>
                ))}
              </ul>
            </div>
          )}
          {incomingDeps.length > 0 && (
            <div className="space-y-1.5">
              <div className="text-body text-mute">
                ← {t('editor.info.incoming', { defaultValue: 'используют' })}
              </div>
              <ul className="space-y-2">
                {incomingDeps.map((d) => (
                  <li
                    key={`${d.sourceDict}.${d.sourceField}`}
                    className="rounded-md border border-line bg-surface px-2.5 py-2 space-y-1.5"
                  >
                    <Link
                      to="/dictionaries/$name"
                      params={{ name: d.sourceDict }}
                      className="text-body text-accent hover:underline font-medium truncate block"
                      title={d.sourceDisplayName ?? d.sourceDict}
                    >
                      {d.sourceDisplayName ?? d.sourceDict}
                    </Link>
                    <div className="flex items-center gap-1 text-mono text-ink-2 min-w-0">
                      <span className="truncate">.{d.sourceField}</span>
                      <ArrowRightIcon weight="bold" size={10} className="text-mute shrink-0" />
                      <span className="truncate">{d.targetField}</span>
                    </div>
                    <div className="flex items-center gap-1.5 flex-wrap">
                      {d.activeRecordsInSourceDict > 0 && (
                        <span className="text-cap text-mute tabular-nums">
                          {t('lineage.usedBy.activeCount', {
                            count: d.activeRecordsInSourceDict,
                            defaultValue: `${d.activeRecordsInSourceDict} записей`,
                          })}
                        </span>
                      )}
                      <span className={cn(
                        'text-cap font-semibold tracking-wider px-1.5 py-0.5 rounded-sm',
                        ON_CLOSE_CLASS[d.onClose],
                      )}>
                        {d.onClose}
                      </span>
                    </div>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </Section>
      )}

      {/* Actions — bottom buttons per redesign prototype: Экспорт + Time-travel
        * + AOI. После Relations block чтобы не разрывать info → meta → relations
        * мыслительный поток info-panel'а. */}
      {actions && (
        <div className="space-y-2 pt-3 mt-auto border-t border-line-2">
          {actions.onExport && (
            <button
              type="button"
              onClick={actions.onExport}
              disabled={actions.exportPending}
              className="w-full h-8 rounded-md border border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2 disabled:opacity-50 disabled:cursor-not-allowed text-cell flex items-center justify-center gap-1.5 transition-colors"
            >
              <DownloadSimpleIcon weight="regular" size={14} />
              {actions.exportPending
                ? t('export.pending', { defaultValue: 'Экспорт…' })
                : t('export.button', { defaultValue: '↓ Экспорт…' })}
            </button>
          )}
          {actions.onTimeTravel && (
            <button
              type="button"
              onClick={actions.onTimeTravel}
              aria-pressed={actions.timeTravelActive}
              className={cn(
                'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
                actions.timeTravelActive
                  ? 'border-accent bg-accent-bg text-accent'
                  : 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
              )}
            >
              <ClockCounterClockwiseIcon weight="regular" size={14} />
              {t('timeTravel.button', { defaultValue: 'Time-travel…' })}
            </button>
          )}
          {actions.onAoi && (
            <button
              type="button"
              onClick={actions.onAoi}
              aria-pressed={actions.aoiActive}
              className={cn(
                'w-full h-8 rounded-md border text-cell flex items-center justify-center gap-1.5 transition-colors',
                actions.aoiActive
                  ? 'border-accent bg-accent-bg text-accent'
                  : 'border-line bg-surface text-ink-2 hover:border-line-2 hover:bg-surface-2',
              )}
            >
              <MapTrifoldIcon weight="regular" size={14} />
              {t('aoi.button', { defaultValue: 'AOI фильтр…' })}
            </button>
          )}
        </div>
      )}
    </aside>
  )
}

function Section({
  label,
  children,
}: {
  label: React.ReactNode
  children: React.ReactNode
}) {
  return (
    <div className="space-y-1.5">
      <div className="text-cap text-mute">{label}</div>
      {children}
    </div>
  )
}

function MetaCell({
  label,
  children,
}: {
  label: React.ReactNode
  children: React.ReactNode
}) {
  return (
    <div className="space-y-1">
      <div className="text-cap text-mute">{label}</div>
      <div>{children}</div>
    </div>
  )
}

/** Visual variant for FK onClose policy chip — BLOCK = warn, WARN = amber,
 *  CASCADE = error red. Используется в InfoPanel ← используют rows. */
const ON_CLOSE_CLASS: Record<OnCloseAction, string> = {
  BLOCK: 'bg-pink-bg text-pink',
  WARN: 'bg-warn-bg text-warn',
  CASCADE: 'bg-warn-bg text-warn',
}

const extractOutgoingFk = (
  schema: import('@/api/client').JsonSchema | undefined,
): string[] => {
  if (!schema?.properties) return []
  const targets = new Set<string>()
  for (const prop of Object.values(schema.properties)) {
    const ref = prop['x-references']
    if (typeof ref === 'string' && ref.length > 0) {
      const [target] = ref.split('.')
      if (target) targets.add(target)
    }
  }
  return Array.from(targets).sort()
}
