import { useMemo, useState } from 'react'
import { Link } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import {
  Badge,
  Button,
  EmptyState,
  LoadingBlock,
  Panel,
  QueryErrorState,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeaderCell,
  TableRow,
} from '@/ui'
import { useMyDrafts, useMySchemaDrafts } from '@/api/queries'
import { UserCell } from '@/lib/useUserDisplay'
import type {
  DraftOperation,
  DraftResponse,
  DraftStatus,
  SchemaDraft,
  SchemaDraftStatus,
} from '@/api/client'

/**
 * "Мои" tab на /reviews — maker self-tracking. Mixed timeline записей и
 * схем (drafts) которые я создал, sorted submittedAt/createdAt DESC.
 *
 * <p>Filter chips: All / Pending / WIP / Decided. WIP применим только к
 * schemas — records у нас всегда submit'ятся через single-shot endpoint
 * (нет "в работе" состояния между created и submitted).
 *
 * <p>Status grouping:
 * <ul>
 *   <li><b>Records</b> ({@link DraftStatus}): Pending=PENDING,
 *       Decided=APPROVED+REJECTED+WITHDRAWN, no WIP.</li>
 *   <li><b>Schemas</b> ({@link SchemaDraftStatus}):
 *       Pending=review_pending+approved (awaiting publish),
 *       WIP=draft+changes_requested (maker action needed),
 *       Decided=rejected+published+withdrawn.</li>
 * </ul>
 *
 * <p>Click handler:
 * <ul>
 *   <li>Record row → callback'ом наружу (parent открывает {@code ReviewDrawer}
 *       с этим draftId — reuse того же drawer что used reviewer'ом).</li>
 *   <li>Schema row → Link на {@code /dictionaries/$name} (там dict page
 *       поднимает {@code SchemaDraftDrawer} через workflow banner; для
 *       terminal статусов draft видно в audit history).</li>
 * </ul>
 *
 * <p>Both queries имеют {@code refetchInterval: 30_000} — maker видит
 * approve/reject reviewer'а без F5.
 */
type Props = {
  /** Called когда maker кликает на record row — открывает ReviewDrawer наружу. */
  onRecordClick: (draftId: string) => void
}

export type StatusFilter = 'all' | 'pending' | 'wip' | 'decided'

type Bucket = 'pending' | 'wip' | 'decided'

type UnifiedRow =
  | { kind: 'record'; id: string; timestamp: string; bucket: Bucket; record: DraftResponse }
  | { kind: 'schema'; id: string; timestamp: string; bucket: Bucket; schema: SchemaDraft }

/**
 * Records pending bucket = PENDING only. Все остальные статусы
 * (APPROVED/REJECTED/WITHDRAWN) — это closure events, попадают в Decided.
 *
 * <p>Exported для unit-testing — buckets — load-bearing logic для filter
 * counts (eng-review pattern).
 */
export function classifyRecordStatus(s: DraftStatus): Bucket {
  return s === 'PENDING' ? 'pending' : 'decided'
}

/**
 * Schemas: pending = "что-то ждёт reviewer/maker action", WIP = "maker должен
 * что-то сделать чтобы сдвинуть draft", decided = terminal.
 *
 * <p>{@code approved} попадает в pending потому что maker должен ещё publish'нуть
 * — для него это "почти готово, осталось одна кнопка". {@code changes_requested}
 * — в WIP потому что reviewer вернул maker'у на доработку.
 *
 * <p>Exported для unit-testing.
 */
export function classifySchemaStatus(s: SchemaDraftStatus): Bucket {
  if (s === 'review_pending' || s === 'approved') return 'pending'
  if (s === 'draft' || s === 'changes_requested') return 'wip'
  return 'decided'
}

const operationVariant = (op: DraftOperation): 'info' | 'success' | 'warning' => {
  if (op === 'CREATE') return 'success'
  if (op === 'CLOSE') return 'warning'
  return 'info'
}

export function MyDraftsPanel({ onRecordClick }: Props) {
  const { t } = useTranslation()
  const recordsQ = useMyDrafts(0, 50)
  const schemasQ = useMySchemaDrafts(0, 50)
  const [filter, setFilter] = useState<StatusFilter>('all')

  const rows: UnifiedRow[] = useMemo(() => {
    const records: UnifiedRow[] = (recordsQ.data?.items ?? []).map((r) => ({
      kind: 'record',
      id: r.id,
      timestamp: r.submittedAt,
      bucket: classifyRecordStatus(r.status),
      record: r,
    }))
    const schemas: UnifiedRow[] = (schemasQ.data?.items ?? []).map((s) => ({
      kind: 'schema',
      id: s.draftId,
      // SchemaDraft может быть pre-submit (draft без submittedAt) — берём
      // createdAt в fallback чтобы row не уехал в самый низ с пустым timestamp.
      timestamp: s.submittedAt ?? s.createdAt,
      bucket: classifySchemaStatus(s.status),
      schema: s,
    }))
    return [...records, ...schemas].sort((a, b) => b.timestamp.localeCompare(a.timestamp))
  }, [recordsQ.data, schemasQ.data])

  const counts: Record<StatusFilter, number> = useMemo(
    () => ({
      all: rows.length,
      pending: rows.filter((r) => r.bucket === 'pending').length,
      wip: rows.filter((r) => r.bucket === 'wip').length,
      decided: rows.filter((r) => r.bucket === 'decided').length,
    }),
    [rows],
  )

  const filtered = useMemo(
    () => (filter === 'all' ? rows : rows.filter((r) => r.bucket === filter)),
    [rows, filter],
  )

  if (recordsQ.isLoading || schemasQ.isLoading) {
    return <LoadingBlock size="md" label={t('loading')} />
  }
  if (recordsQ.error) {
    return <QueryErrorState error={recordsQ.error} onRetry={() => recordsQ.refetch()} />
  }
  if (schemasQ.error) {
    return <QueryErrorState error={schemasQ.error} onRetry={() => schemasQ.refetch()} />
  }

  if (rows.length === 0) {
    return (
      <EmptyState
        title={t('reviews.mine.empty', {
          defaultValue: 'У вас пока нет черновиков',
        })}
        description={t('reviews.mine.emptyDescription', {
          defaultValue:
            'Черновики появятся здесь, когда вы отправите изменения записи или схемы на ревью.',
        })}
      />
    )
  }

  return (
    <Panel>
      <FilterChips filter={filter} setFilter={setFilter} counts={counts} />
      <Table>
        <TableHead>
          <TableRow>
            <TableHeaderCell>
              {t('reviews.mine.col.type', { defaultValue: 'Тип' })}
            </TableHeaderCell>
            <TableHeaderCell>
              {t('reviews.mine.col.target', { defaultValue: 'Объект' })}
            </TableHeaderCell>
            <TableHeaderCell>
              {t('reviews.mine.col.op', { defaultValue: 'Операция' })}
            </TableHeaderCell>
            <TableHeaderCell>
              {t('reviews.mine.col.status', { defaultValue: 'Статус' })}
            </TableHeaderCell>
            <TableHeaderCell>
              {t('reviews.mine.col.reviewer', { defaultValue: 'Ревьюер' })}
            </TableHeaderCell>
            <TableHeaderCell>
              {t('reviews.mine.col.submitted', { defaultValue: 'Создан' })}
            </TableHeaderCell>
            <TableHeaderCell align="right">
              {t('reviews.mine.col.action', { defaultValue: 'Действие' })}
            </TableHeaderCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {filtered.map((row) =>
            row.kind === 'record' ? (
              <RecordRow
                key={`r-${row.id}`}
                draft={row.record}
                onClick={() => onRecordClick(row.id)}
              />
            ) : (
              <SchemaRow key={`s-${row.id}`} draft={row.schema} />
            ),
          )}
        </TableBody>
      </Table>
      {filtered.length === 0 && (
        <div className="py-8 text-center text-cell text-mute">
          {t('reviews.mine.emptyFilter', {
            defaultValue: 'В этой категории черновиков нет',
          })}
        </div>
      )}
    </Panel>
  )
}

function FilterChips({
  filter,
  setFilter,
  counts,
}: {
  filter: StatusFilter
  setFilter: (f: StatusFilter) => void
  counts: Record<StatusFilter, number>
}) {
  const { t } = useTranslation()
  const chips: { key: StatusFilter; label: string }[] = [
    { key: 'all', label: t('reviews.mine.filter.all', { defaultValue: 'Все' }) },
    {
      key: 'pending',
      label: t('reviews.mine.filter.pending', { defaultValue: 'На ревью' }),
    },
    { key: 'wip', label: t('reviews.mine.filter.wip', { defaultValue: 'В работе' }) },
    {
      key: 'decided',
      label: t('reviews.mine.filter.decided', { defaultValue: 'Закрыты' }),
    },
  ]
  return (
    <div className="flex flex-wrap items-center gap-2 mb-3">
      {chips.map((c) => {
        const active = filter === c.key
        return (
          <button
            key={c.key}
            type="button"
            onClick={() => setFilter(c.key)}
            aria-pressed={active}
            className={
              'px-2.5 py-1 text-cell rounded-sm border transition-colors ' +
              (active
                ? 'border-accent text-accent bg-accent/10'
                : 'border-line text-ink-2 hover:bg-line/30')
            }
          >
            {c.label}
            {counts[c.key] > 0 && (
              <span className="ml-1.5 text-mute tabular-nums">({counts[c.key]})</span>
            )}
          </button>
        )
      })}
    </div>
  )
}

function RecordRow({
  draft,
  onClick,
}: {
  draft: DraftResponse
  onClick: () => void
}) {
  const { t } = useTranslation()
  return (
    <TableRow>
      <TableCell>
        <Badge variant="info">
          {t('reviews.mine.type.record', { defaultValue: 'Запись' })}
        </Badge>
      </TableCell>
      <TableCell>
        <Link
          to="/dictionaries/$name"
          params={{ name: draft.dictionaryId }}
          className="text-mono text-accent hover:underline"
        >
          <span className="text-mute">{draft.dictionaryId.slice(0, 8)}…</span>
          <span className="mx-1 text-mute">/</span>
          <span>{draft.businessKey}</span>
        </Link>
      </TableCell>
      <TableCell>
        <Badge variant={operationVariant(draft.operation)}>{draft.operation}</Badge>
      </TableCell>
      <TableCell>
        <RecordStatusBadge status={draft.status} />
      </TableCell>
      <TableCell>
        {draft.reviewerId ? <UserCell uuid={draft.reviewerId} /> : <span className="text-mute">—</span>}
      </TableCell>
      <TableCell className="text-cell text-ink-2 tabular-nums">
        {new Date(draft.submittedAt).toLocaleString()}
      </TableCell>
      <TableCell align="right">
        <Button variant="secondary" size="sm" onClick={onClick}>
          {t('reviews.mine.action.open', { defaultValue: 'Открыть' })}
        </Button>
      </TableCell>
    </TableRow>
  )
}

function SchemaRow({ draft }: { draft: SchemaDraft }) {
  const { t } = useTranslation()
  const timestamp = draft.submittedAt ?? draft.createdAt
  return (
    <TableRow>
      <TableCell>
        <Badge variant="warning">
          {t('reviews.mine.type.schema', { defaultValue: 'Схема' })}
        </Badge>
      </TableCell>
      <TableCell>
        <Link
          to="/dictionaries/$name"
          params={{ name: draft.dictionaryName }}
          className="text-mono text-accent hover:underline"
        >
          {draft.dictionaryName}
        </Link>
        <span className="ml-2 text-cell text-mute tabular-nums">
          {t('reviews.mine.fromVersion', { defaultValue: 'от v' })}
          {draft.branchedFromVersion}
        </span>
      </TableCell>
      <TableCell className="text-mute">—</TableCell>
      <TableCell>
        <SchemaStatusBadge status={draft.status} />
      </TableCell>
      <TableCell>
        {draft.decisionUserId ? (
          <UserCell uuid={draft.decisionUserId} />
        ) : (
          <span className="text-mute">—</span>
        )}
      </TableCell>
      <TableCell className="text-cell text-ink-2 tabular-nums">
        {new Date(timestamp).toLocaleString()}
      </TableCell>
      <TableCell align="right">
        <Link
          to="/dictionaries/$name"
          params={{ name: draft.dictionaryName }}
          className="text-accent hover:underline text-cell"
        >
          {t('reviews.mine.action.openSchema', { defaultValue: 'Открыть' })} →
        </Link>
      </TableCell>
    </TableRow>
  )
}

function RecordStatusBadge({ status }: { status: DraftStatus }) {
  const { t } = useTranslation()
  const variant: 'info' | 'success' | 'danger' | 'default' = (() => {
    switch (status) {
      case 'PENDING':
        return 'info'
      case 'APPROVED':
        return 'success'
      case 'REJECTED':
        return 'danger'
      case 'WITHDRAWN':
        return 'default'
    }
  })()
  const fallback: Record<DraftStatus, string> = {
    PENDING: 'На ревью',
    APPROVED: 'Одобрено',
    REJECTED: 'Отклонён',
    WITHDRAWN: 'Отозван',
  }
  return (
    <Badge variant={variant}>
      {t(`reviews.mine.recordStatus.${status}`, { defaultValue: fallback[status] })}
    </Badge>
  )
}

function SchemaStatusBadge({ status }: { status: SchemaDraftStatus }) {
  const { t } = useTranslation()
  const variant: 'info' | 'success' | 'warning' | 'danger' | 'primary' | 'default' = (() => {
    switch (status) {
      case 'draft':
      case 'changes_requested':
        return 'warning'
      case 'review_pending':
        return 'info'
      case 'approved':
        return 'success'
      case 'rejected':
        return 'danger'
      case 'withdrawn':
        return 'default'
      case 'published':
        return 'primary'
    }
  })()
  const fallback: Record<SchemaDraftStatus, string> = {
    draft: 'Черновик',
    review_pending: 'На ревью',
    approved: 'Одобрено',
    changes_requested: 'Запрошены правки',
    rejected: 'Отклонён',
    published: 'Опубликован',
    withdrawn: 'Отозван',
  }
  return (
    <Badge variant={variant}>
      {t(`workflow.schemaDraft.statusBadge.${status}`, {
        defaultValue: fallback[status],
      })}
    </Badge>
  )
}
