/**
 * Hub view (View B из design handoff) — focused dictionary в центре + соседи
 * по обе стороны.
 *
 * Layout:
 *   ┌──────────────┬─────────────────┬──────────────┐
 *   │  → ссылается │   <current>     │ ← N использ. │
 *   │  (outgoing)  │   (focused)     │   (refBy)    │
 *   └──────────────┴─────────────────┴──────────────┘
 *
 * Outgoing FK derived from schemaJson properties[*].x-references
 * (format: "dict.field"). Incoming refBy via useDictionaryDependents.
 *
 * Click на neighbor card → navigate к его Hub view (recursion fine).
 */
import { useMemo } from 'react'
import { Link } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { Badge } from '@/ui'
import { useDictionaryDependents, useDictionaries } from '@/api/queries'
import type { DictionaryDetail, DictionaryDefinition, JsonSchema } from '@/api/client'

const SCOPE_STRIP: Record<string, string> = {
  PUBLIC: 'bg-emerald-500',
  INTERNAL: 'bg-amber-500',
  RESTRICTED: 'bg-rose-500',
}

/**
 * Walk schemaJson properties — собираем targets из x-references.
 * Format: "targetDict.targetField" → возвращаем уникальные targetDict names.
 */
const extractOutgoingFk = (schema: 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()
}

const NeighborCard = ({
  dict,
  side,
}: {
  dict: DictionaryDefinition
  side: 'left' | 'right'
}) => (
  <Link
    to="/dictionaries/$name"
    params={{ name: dict.name }}
    search={{ tab: 'relations' }}
    className={`group block bg-surface border border-line rounded-lg p-3 transition hover:shadow-hover hover:border-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 ${
      side === 'left' ? 'text-right' : 'text-left'
    }`}
  >
    <div className={`flex items-baseline gap-2 ${side === 'left' ? 'justify-end' : ''}`}>
      <span
        className={`inline-block size-1.5 rounded-full shrink-0 ${
          SCOPE_STRIP[dict.scope] ?? 'bg-ink/40'
        }`}
        aria-hidden="true"
      />
      <h4 className="font-sans text-body font-semibold text-accent truncate group-hover:underline">
        {dict.displayName ?? dict.name}
      </h4>
    </div>
    <div className="mt-0.5 text-mono text-mute truncate">
      {dict.name}
    </div>
  </Link>
)

const SectionLabel = ({
  side,
  count,
}: {
  side: 'left' | 'right'
  count: number
}) => {
  const { t } = useTranslation()
  return (
    <div
 className={`text-cap text-mute mb-2 ${
        side === 'left' ? 'text-right' : 'text-left'
      }`}
    >
      {side === 'left'
        ? t('hub.outgoing', { count, defaultValue: '→ ссылается ({{count}})' })
        : t('hub.incoming', { count, defaultValue: '← {{count}} использ.' })}
    </div>
  )
}

export function DictionaryHubView({ detail }: { detail: DictionaryDetail }) {
  const { t } = useTranslation()
  const { data: allDicts } = useDictionaries()
  const { data: refByRaw } = useDictionaryDependents(detail.name)

  // Outgoing FK targets — names derived из schemaJson.
  const outgoingNames = useMemo(
    () => extractOutgoingFk(detail.schemaJson),
    [detail.schemaJson],
  )

  // Resolve names → DictionaryDefinition (для card rendering).
  // Filter недоступные / unknown names (защита от устаревших schema refs).
  const outgoingDicts = useMemo(() => {
    if (!allDicts) return []
    const byName = new Map(allDicts.map((d) => [d.name, d]))
    return outgoingNames
      .map((name) => byName.get(name))
      .filter((d): d is DictionaryDefinition => Boolean(d))
  }, [allDicts, outgoingNames])

  // refBy: уникальные source dicts (те что ссылаются на нас) → resolve в definitions.
  const incomingDicts = useMemo(() => {
    if (!allDicts || !refByRaw) return []
    const byName = new Map(allDicts.map((d) => [d.name, d]))
    const seen = new Set<string>()
    const out: DictionaryDefinition[] = []
    for (const dep of refByRaw) {
      if (seen.has(dep.sourceDict)) continue
      seen.add(dep.sourceDict)
      const def = byName.get(dep.sourceDict)
      if (def) out.push(def)
    }
    return out
  }, [allDicts, refByRaw])

  return (
    <section
      aria-label={t('hub.heading', { defaultValue: 'Связи справочника' })}
      className="grid grid-cols-1 md:grid-cols-[1fr_minmax(280px,_360px)_1fr] gap-4 md:gap-6 items-start py-2"
    >
      {/* Left rail: outgoing FK */}
      <div className="md:order-1 order-2 space-y-2">
        <SectionLabel side="left" count={outgoingDicts.length} />
        {outgoingDicts.length === 0 ? (
          <div className="text-cell text-mute/70 text-right italic">
            {t('hub.noOutgoing', { defaultValue: 'нет исходящих ссылок' })}
          </div>
        ) : (
          <div className="space-y-2">
            {outgoingDicts.map((d) => (
              <NeighborCard key={d.id} dict={d} side="left" />
            ))}
          </div>
        )}
      </div>

      {/* Center: focused dict (large card) */}
      <div className="md:order-2 order-1 relative">
        <div
          className="relative bg-surface rounded-xl p-5 border-2 border-accent"
          style={{ boxShadow: '0 18px 36px -22px rgba(20,30,140,.5)' }}
        >
          <div className="flex items-start gap-2 mb-2 flex-wrap">
            <Badge variant="info">{detail.scope}</Badge>
            {detail.approvalRequired && (
              <Badge variant="warning">
                {t('dict.list.approval', { defaultValue: 'approval' })}
              </Badge>
            )}
            <span className="text-mono ml-auto text-mute">
              v{detail.schemaVersion}
            </span>
          </div>
          <h2 className="text-title-xl font-sans text-accent leading-tight">
            {detail.displayName ?? detail.name}
          </h2>
          <div className="text-mono text-mute mt-0.5">
            {detail.name}
          </div>
          {detail.description && (
            <p className="text-body text-ink mt-3 leading-relaxed">
              {detail.description}
            </p>
          )}
          <div className="text-cap mt-4 pt-3 border-t border-line flex items-center justify-between text-mute">
            <span>{detail.bundle}</span>
            <span>{detail.supportedLocales.join(', ')}</span>
            {typeof detail.recordCount === 'number' && (
              <span>
                {t('dict.list.recordCount', { count: detail.recordCount })}
              </span>
            )}
          </div>
        </div>
      </div>

      {/* Right rail: refBy */}
      <div className="md:order-3 order-3 space-y-2">
        <SectionLabel side="right" count={incomingDicts.length} />
        {incomingDicts.length === 0 ? (
          <div className="text-cell text-mute/70 italic">
            {t('hub.noIncoming', { defaultValue: 'никто не ссылается' })}
          </div>
        ) : (
          <div className="space-y-2">
            {incomingDicts.map((d) => (
              <NeighborCard key={d.id} dict={d} side="right" />
            ))}
          </div>
        )}
      </div>
    </section>
  )
}
