import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useAuth } from 'react-oidc-context'
import axios from 'axios'
import { Badge, Button, Drawer, LoadingBlock, QueryErrorState, TextArea, toast } from '@/ui'
import {
  CheckIcon,
  PaperPlaneTiltIcon,
  PencilSimpleIcon,
  XCircleIcon,
  ArrowsCounterClockwiseIcon,
  RocketIcon,
  TrashIcon,
} from '@phosphor-icons/react'
import {
  isActiveSchemaDraft,
  type DictionaryDetail,
  type SchemaDraft,
  type SchemaDraftStatus,
  type SchemaDraftVerdict,
} from '@/api/client'
import { CreateSchemaDraftModal } from '@/components/workflow/CreateSchemaDraftModal'
import { useDictActiveSchemaDraft } from '@/api/queries'
import {
  useDecideSchemaDraft,
  usePublishSchemaDraft,
  useSubmitSchemaDraftForReview,
  useWithdrawSchemaDraft,
} from '@/api/mutations'
import { useCanPublishSchema, useCanReviewSchema } from '@/auth/usePermissions'
import { UserCell } from '@/lib/useUserDisplay'

type Props = {
  open: boolean
  onClose: () => void
  dictionaryName: string
  /** Current live schemaVersion — passed для publish expectedHeadVersion check. */
  currentHeadVersion: string | undefined
  /** Optional full dict detail — нужен для edit modal seeding. Если не
   * передан, edit button скрывается. */
  detail?: DictionaryDetail
}

/**
 * Right-side drawer для schema draft — full state + status-aware actions.
 *
 * <p>Загружает активный draft через {@link useDictActiveSchemaDraft}.
 * Comment textarea используется как:
 * <ul>
 *   <li>{@code review_pending} — reviewer пишет decision comment (approve/
 *       request_changes/reject).</li>
 *   <li>{@code draft / changes_requested} — maker note при submit.</li>
 *   <li>{@code approved} — publish release note.</li>
 * </ul>
 *
 * <p>Все действия идут через mutations из {@code @/api/mutations}.
 * Backend сам отрезает невалидные transitions (403 self_approve_forbidden,
 * 409 invalid_transition, 409 version_mismatch) — мы показываем error
 * toast с raw message.
 *
 * <p>Phase 1b: maker И reviewer actions показаны всем (backend гейтит).
 * Phase 1c integration RBAC из Keycloak roles claim сузит видимость.
 */
export function SchemaDraftDrawer({
  open,
  onClose,
  dictionaryName,
  currentHeadVersion,
  detail,
}: Props) {
  const { t } = useTranslation()
  const [comment, setComment] = useState('')
  const [editOpen, setEditOpen] = useState(false)
  const { data: draft, isLoading, error, refetch } = useDictActiveSchemaDraft(
    open ? dictionaryName : undefined,
  )

  const submitMut = useSubmitSchemaDraftForReview(dictionaryName)
  const decideMut = useDecideSchemaDraft(dictionaryName)
  const publishMut = usePublishSchemaDraft(dictionaryName)
  const withdrawMut = useWithdrawSchemaDraft(dictionaryName)

  const handleError = (err: unknown, fallback: string) => {
    let msg = fallback
    if (axios.isAxiosError(err)) {
      const body = err.response?.data
      if (body && typeof body === 'object') {
        const code = (body as { code?: string }).code
        const message = (body as { message?: string }).message
        msg = message ?? code ?? fallback
      }
    }
    toast.error(msg)
  }

  const onSubmitReview = () => {
    if (!draft) return
    submitMut.mutate(
      { draftId: draft.draftId, body: { note: comment || null } },
      {
        onSuccess: () => {
          toast.success(
            t('workflow.schemaDraft.toast.submitted', {
              defaultValue: 'Отправлено на ревью',
            }),
          )
          setComment('')
        },
        onError: (e) =>
          handleError(e, t('workflow.schemaDraft.toast.submitFailed', {
            defaultValue: 'Не удалось отправить на ревью',
          })),
      },
    )
  }

  const onDecide = (verdict: SchemaDraftVerdict) => {
    if (!draft) return
    decideMut.mutate(
      { draftId: draft.draftId, body: { decision: verdict, comment: comment || undefined } },
      {
        onSuccess: () => {
          toast.success(
            t(`workflow.schemaDraft.toast.${verdict.toLowerCase()}`, {
              defaultValue: verdictSuccessFallback(verdict),
            }),
          )
          setComment('')
        },
        onError: (e) =>
          handleError(e, t('workflow.schemaDraft.toast.decideFailed', {
            defaultValue: 'Не удалось зафиксировать решение',
          })),
      },
    )
  }

  const onPublish = () => {
    if (!draft || !currentHeadVersion) return
    publishMut.mutate(
      {
        draftId: draft.draftId,
        body: {
          expectedHeadVersion: currentHeadVersion,
          publishNote: comment || undefined,
        },
      },
      {
        onSuccess: (res) => {
          toast.success(
            t('workflow.schemaDraft.toast.published', {
              version: res.newVersion,
              defaultValue: `Опубликовано v${res.newVersion}`,
            }),
          )
          setComment('')
          onClose()
        },
        onError: (e) =>
          handleError(e, t('workflow.schemaDraft.toast.publishFailed', {
            defaultValue: 'Не удалось опубликовать',
          })),
      },
    )
  }

  const onWithdraw = () => {
    if (!draft) return
    const ok = window.confirm(
      t('workflow.schemaDraft.confirmWithdraw', {
        defaultValue: 'Отозвать черновик? Действие нельзя отменить.',
      }) as string,
    )
    if (!ok) return
    withdrawMut.mutate(draft.draftId, {
      onSuccess: () => {
        toast.success(
          t('workflow.schemaDraft.toast.withdrawn', {
            defaultValue: 'Черновик отозван',
          }),
        )
        onClose()
      },
      onError: (e) =>
        handleError(e, t('workflow.schemaDraft.toast.withdrawFailed', {
          defaultValue: 'Не удалось отозвать',
        })),
    })
  }

  const anyPending =
    submitMut.isPending ||
    decideMut.isPending ||
    publishMut.isPending ||
    withdrawMut.isPending

  return (
    <Drawer
      isOpen={open}
      onClose={onClose}
      side="right"
      widthClassName="w-full max-w-xl"
      title={t('workflow.schemaDraft.drawerTitle', {
        defaultValue: 'Черновик схемы',
      })}
    >
      <div className="space-y-4">
        {isLoading && <LoadingBlock size="md" label={t('loading')} />}
        {error && <QueryErrorState error={error} onRetry={() => refetch()} />}
        {!isLoading && !draft && (
          <p className="text-body text-mute">
            {t('workflow.schemaDraft.empty', {
              defaultValue: 'Активного черновика схемы нет.',
            })}
          </p>
        )}

        {draft && (
          <>
            <DraftHeader draft={draft} />
            <DraftMeta draft={draft} />

            {/* Read-only proposed schema. Edit flow (CreateModal) — отдельный
                cliff в Phase 1c. Здесь просто видим что предлагается. */}
            <ProposedSchemaPane data={draft.proposedSchema} />

            {/* Comment textarea. Один текстовое поле, semantics зависит от
                status'а (см. drawer-level JSDoc). */}
            <div>
              <label className="block text-cap text-mute font-display uppercase tracking-wider mb-1">
                {commentLabel(draft.status, t)}
              </label>
              <TextArea
                value={comment}
                onChange={(e) => setComment(e.target.value)}
                placeholder={commentPlaceholder(draft.status, t)}
                rows={3}
                disabled={anyPending}
              />
            </div>

            {/* Action bar — status-aware. Bottom-sticky визуально, но рендерим
                inline т.к. Drawer sheet flow-based. */}
            <DraftActions
              status={draft.status}
              makerId={draft.makerId}
              onSubmitReview={onSubmitReview}
              onDecide={onDecide}
              onPublish={onPublish}
              onWithdraw={onWithdraw}
              onEdit={detail ? () => setEditOpen(true) : undefined}
              disabled={anyPending}
              hasCurrentVersion={Boolean(currentHeadVersion)}
            />
            {detail && (
              <CreateSchemaDraftModal
                open={editOpen}
                onClose={() => setEditOpen(false)}
                detail={detail}
                editDraft={draft}
              />
            )}
          </>
        )}
      </div>
    </Drawer>
  )
}

function DraftHeader({ draft }: { draft: SchemaDraft }) {
  const { t } = useTranslation()
  return (
    <div className="flex flex-wrap items-baseline gap-2">
      <span className="text-mono text-cell text-mute">
        {draft.draftId.slice(0, 8)}
      </span>
      <StatusBadge status={draft.status} />
      {!isActiveSchemaDraft(draft.status) && (
        <Badge variant="outline">
          {t('workflow.schemaDraft.terminal', { defaultValue: 'terminal' })}
        </Badge>
      )}
    </div>
  )
}

function StatusBadge({ status }: { status: SchemaDraftStatus }) {
  const { t } = useTranslation()
  const variant: 'default' | 'success' | 'warning' | 'danger' | 'info' | 'primary' = (() => {
    switch (status) {
      case 'draft':
      case 'changes_requested':
        return 'warning'
      case 'review_pending':
        return 'info'
      case 'approved':
        return 'success'
      case 'rejected':
      case 'withdrawn':
        return 'danger'
      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>
  )
}

function DraftMeta({ draft }: { draft: SchemaDraft }) {
  const { t } = useTranslation()
  return (
    <dl className="grid grid-cols-[120px_1fr] gap-y-1 gap-x-3 text-cell">
      <Row label={t('workflow.schemaDraft.maker', { defaultValue: 'Автор' })}>
        <UserCell uuid={draft.makerId} />
      </Row>
      <Row label={t('workflow.schemaDraft.from', { defaultValue: 'От версии' })}>
        v{draft.branchedFromVersion}
      </Row>
      <Row label={t('workflow.schemaDraft.createdAt', { defaultValue: 'Создан' })}>
        <span className="tabular-nums">
          {new Date(draft.createdAt).toLocaleString()}
        </span>
      </Row>
      {draft.submittedAt && (
        <Row label={t('workflow.schemaDraft.submittedAt', { defaultValue: 'На ревью с' })}>
          <span className="tabular-nums">
            {new Date(draft.submittedAt).toLocaleString()}
          </span>
        </Row>
      )}
      {draft.decisionAt && (
        <Row label={t('workflow.schemaDraft.decisionAt', { defaultValue: 'Решение' })}>
          <span className="tabular-nums">
            {new Date(draft.decisionAt).toLocaleString()}
          </span>
        </Row>
      )}
      {draft.reason && (
        <Row label={t('workflow.schemaDraft.reason', { defaultValue: 'Причина' })}>
          <span className="italic">{draft.reason}</span>
        </Row>
      )}
      {draft.decisionComment && (
        <Row label={t('workflow.schemaDraft.decisionComment', {
          defaultValue: 'Комментарий',
        })}>
          <span className="italic">{draft.decisionComment}</span>
        </Row>
      )}
    </dl>
  )
}

function Row({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <>
      <dt className="text-mute font-display uppercase tracking-wider text-cap">{label}</dt>
      <dd className="text-ink">{children}</dd>
    </>
  )
}

function ProposedSchemaPane({ data }: { data: unknown }) {
  const { t } = useTranslation()
  return (
    <div className="rounded-lg border border-line bg-surface overflow-hidden">
      <div className="px-3 py-2 border-b border-line text-cap font-semibold uppercase tracking-wider text-mute">
        {t('workflow.schemaDraft.proposed', {
          defaultValue: 'Предложенная схема',
        })}
      </div>
      <pre className="text-mono text-cell p-3 overflow-auto max-h-[40vh] bg-[#0c0a23] text-[#f0eaff]">
        {JSON.stringify(data, null, 2)}
      </pre>
    </div>
  )
}

function DraftActions({
  status,
  onSubmitReview,
  onDecide,
  onPublish,
  onWithdraw,
  onEdit,
  disabled,
  hasCurrentVersion,
  makerId,
}: {
  status: SchemaDraftStatus
  onSubmitReview: () => void
  onDecide: (v: SchemaDraftVerdict) => void
  onPublish: () => void
  onWithdraw: () => void
  onEdit?: () => void
  disabled: boolean
  hasCurrentVersion: boolean
  /** UUID maker'а draft'а — для gate "Отозвать" (только сам автор может). */
  makerId: string
}) {
  const { t } = useTranslation()
  const auth = useAuth()
  // Phase 1c RBAC stub: для review_pending reviewer-only действия скрываем
  // если нет approve role. Publish — отдельная role. Backend всё равно
  // защищает. Phase 1d intergrate'нет Keycloak realm_access.roles.
  const canReview = useCanReviewSchema()
  const canPublish = useCanPublishSchema()
  // "Отозвать" — maker-only action (withdraw own draft). Backend всё равно
  // 403'нет non-maker call, но скрытие на UI level убирает confusion:
  // reviewer видел кнопку которая всегда fail'ила. Сравниваем JWT sub с makerId.
  const currentSub = auth.user?.profile?.sub
  const isMaker = Boolean(currentSub) && currentSub === makerId

  if (!isActiveSchemaDraft(status)) {
    return (
      <p className="text-cell text-mute italic">
        {t('workflow.schemaDraft.terminalHint', {
          defaultValue: 'Терминальный статус — действия недоступны.',
        })}
      </p>
    )
  }

  return (
    <div className="flex flex-wrap items-center gap-2 pt-2 border-t border-line">
      {(status === 'draft' || status === 'changes_requested') && (
        <>
          {onEdit && (
            <Button
              variant="ghost"
              size="sm"
              onClick={onEdit}
              disabled={disabled}
              leftIcon={<PencilSimpleIcon weight="regular" size={14} />}
            >
              {t('workflow.schemaDraft.actions.edit', {
                defaultValue: 'Редактировать',
              })}
            </Button>
          )}
          <Button
            variant="primary"
            size="sm"
            onClick={onSubmitReview}
            disabled={disabled}
            leftIcon={<PaperPlaneTiltIcon weight="regular" size={14} />}
          >
            {status === 'draft'
              ? t('workflow.schemaDraft.actions.submit', {
                  defaultValue: 'Отправить на ревью',
                })
              : t('workflow.schemaDraft.actions.resubmit', {
                  defaultValue: 'Доработать и отправить',
                })}
          </Button>
        </>
      )}
      {status === 'review_pending' && canReview && (
        <>
          <Button
            variant="primary"
            size="sm"
            onClick={() => onDecide('APPROVE')}
            disabled={disabled}
            leftIcon={<CheckIcon weight="regular" size={14} />}
          >
            {t('workflow.schemaDraft.actions.approve', { defaultValue: 'Approve' })}
          </Button>
          <Button
            variant="secondary"
            size="sm"
            onClick={() => onDecide('REQUEST_CHANGES')}
            disabled={disabled}
            leftIcon={<ArrowsCounterClockwiseIcon weight="regular" size={14} />}
          >
            {t('workflow.schemaDraft.actions.requestChanges', {
              defaultValue: 'Запросить правки',
            })}
          </Button>
          <Button
            variant="ghost"
            size="sm"
            onClick={() => onDecide('REJECT')}
            disabled={disabled}
            leftIcon={<XCircleIcon weight="regular" size={14} />}
          >
            {t('workflow.schemaDraft.actions.reject', { defaultValue: 'Отклонить' })}
          </Button>
        </>
      )}
      {status === 'approved' && canPublish && (
        <Button
          variant="primary"
          size="sm"
          onClick={onPublish}
          disabled={disabled || !hasCurrentVersion}
          leftIcon={<RocketIcon weight="regular" size={14} />}
        >
          {t('workflow.schemaDraft.actions.publish', { defaultValue: 'Опубликовать' })}
        </Button>
      )}
      {isMaker && (
        <Button
          variant="ghost"
          size="sm"
          onClick={onWithdraw}
          disabled={disabled}
          className="text-danger hover:text-danger"
          leftIcon={<TrashIcon weight="regular" size={14} />}
        >
          {t('workflow.schemaDraft.actions.withdraw', { defaultValue: 'Отозвать' })}
        </Button>
      )}
    </div>
  )
}

function commentLabel(status: SchemaDraftStatus, t: (k: string, o?: { defaultValue?: string }) => string): string {
  switch (status) {
    case 'review_pending':
      return t('workflow.schemaDraft.comment.decision', {
        defaultValue: 'Комментарий ревьюера',
      })
    case 'approved':
      return t('workflow.schemaDraft.comment.publish', {
        defaultValue: 'Release note',
      })
    case 'draft':
    case 'changes_requested':
      return t('workflow.schemaDraft.comment.note', {
        defaultValue: 'Комментарий автора',
      })
    default:
      return t('workflow.schemaDraft.comment.note', { defaultValue: 'Комментарий' })
  }
}

function commentPlaceholder(status: SchemaDraftStatus, t: (k: string, o?: { defaultValue?: string }) => string): string {
  switch (status) {
    case 'review_pending':
      return t('workflow.schemaDraft.comment.decisionPlaceholder', {
        defaultValue: 'Краткое обоснование решения (опционально)',
      })
    case 'approved':
      return t('workflow.schemaDraft.comment.publishPlaceholder', {
        defaultValue: 'Что меняется в этой версии (попадёт в changelog)',
      })
    default:
      return t('workflow.schemaDraft.comment.notePlaceholder', {
        defaultValue: 'На что обратить внимание ревьюеру',
      })
  }
}

function verdictSuccessFallback(v: SchemaDraftVerdict): string {
  switch (v) {
    case 'APPROVE':
      return 'Черновик одобрен'
    case 'REQUEST_CHANGES':
      return 'Запрошены правки'
    case 'REJECT':
      return 'Черновик отклонён'
  }
}
