import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { AlertCircle, CheckCircle, KeyRound, Users, Package, Trash2, AlertTriangle, Save } from 'lucide-react'
import { AxiosError } from 'axios'
import { api } from '@/lib/api'
import { PageHeader } from '@/components/PageHeader'
import { Button } from '@/components/Button'
import { Field, TextInput, Checkbox } from '@/components/Field'

function formatError(err: unknown): string {
  if (err instanceof AxiosError) {
    const status = err.response?.status
    const body = err.response?.data as { error?: string; error_description?: string; title?: string } | undefined
    const detail = body?.error ?? body?.error_description ?? body?.title
    if (status === 404) return '404 — эндпоинт не существует. API обновлён?'
    if (status === 401) return '401 — сессия истекла, перелогинься.'
    if (status === 403) return '403 — нужна роль Admin.'
    if (status === 502 || status === 503) return `${status} — МойСклад недоступен.`
    return detail ? `${status ?? ''} ${detail}` : err.message
  }
  if (err instanceof Error) return err.message
  return String(err)
}

interface SettingsDto { hasToken: boolean; masked: string | null }
interface JobView {
  id: string
  kind: string
  status: 'Running' | 'Succeeded' | 'Failed' | 'Cancelled'
  stage: string | null
  startedAt: string
  finishedAt: string | null
  total: number; created: number; updated: number; skipped: number; deleted: number; groupsCreated: number
  message: string | null
  errors: string[]
}

function useJob(jobId: string | null) {
  return useQuery({
    queryKey: ['admin-job', jobId],
    enabled: !!jobId,
    queryFn: async () => (await api.get<JobView>(`/api/admin/jobs/${jobId}`)).data,
    refetchInterval: (q) => {
      const status = q.state.data?.status
      return status === 'Succeeded' || status === 'Failed' ? false : 1500
    },
  })
}

export function MoySkladImportPage() {
  const qc = useQueryClient()

  const settings = useQuery({
    queryKey: ['/api/admin/moysklad/settings'],
    queryFn: async () => (await api.get<SettingsDto>('/api/admin/moysklad/settings')).data,
  })

  const [tokenInput, setTokenInput] = useState('')
  const [overwrite, setOverwrite] = useState(true)

  const saveToken = useMutation({
    mutationFn: async () =>
      (await api.put<SettingsDto>('/api/admin/moysklad/settings', { token: tokenInput })).data,
    onSuccess: () => {
      setTokenInput('')
      qc.invalidateQueries({ queryKey: ['/api/admin/moysklad/settings'] })
    },
  })

  const test = useMutation({
    mutationFn: async () =>
      (await api.post<{ organization: string; inn?: string }>('/api/admin/moysklad/test', {})).data,
  })

  const [productsJobId, setProductsJobId] = useState<string | null>(null)
  const [counterpartiesJobId, setCounterpartiesJobId] = useState<string | null>(null)

  const startProducts = useMutation({
    mutationFn: async () =>
      (await api.post<{ jobId: string }>('/api/admin/moysklad/import-products', { overwriteExisting: overwrite })).data,
    onSuccess: (d) => setProductsJobId(d.jobId),
  })
  const startCounterparties = useMutation({
    mutationFn: async () =>
      (await api.post<{ jobId: string }>('/api/admin/moysklad/import-counterparties', { overwriteExisting: overwrite })).data,
    onSuccess: (d) => setCounterpartiesJobId(d.jobId),
  })

  const productsJob = useJob(productsJobId)
  const counterpartiesJob = useJob(counterpartiesJobId)

  const hasToken = settings.data?.hasToken ?? false

  return (
    <div className="h-full overflow-auto">
      <div className="p-6 max-w-3xl">
        <PageHeader
          title="Импорт из МойСклад"
          description="Перенос товаров, групп и контрагентов из учётной записи МойСклад."
        />

        <section className="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 p-5 space-y-4">
          <h2 className="text-sm font-semibold">Токен API</h2>
          {settings.data && (
            <div className="text-sm">
              {hasToken ? (
                <div className="flex items-center gap-2 text-emerald-700 dark:text-emerald-400">
                  <CheckCircle className="w-4 h-4" /> сохранён:{' '}
                  <code className="font-mono">{settings.data.masked}</code>
                </div>
              ) : (
                <div className="text-amber-700 dark:text-amber-400">Ещё не задан — импорт не сработает.</div>
              )}
            </div>
          )}
          <Field label={hasToken ? 'Заменить токен' : 'Bearer-токен MoySklad'}>
            <TextInput
              type="password"
              value={tokenInput}
              onChange={(e) => setTokenInput(e.target.value)}
              placeholder="персональный или сервисный токен"
              autoComplete="off"
              spellCheck={false}
            />
          </Field>
          <div className="flex gap-2 items-center flex-wrap">
            <Button
              onClick={() => saveToken.mutate()}
              disabled={!tokenInput || saveToken.isPending}
            >
              <Save className="w-4 h-4" />
              {saveToken.isPending ? 'Сохраняю…' : 'Сохранить токен'}
            </Button>
            <Button
              variant="secondary"
              onClick={() => test.mutate()}
              disabled={!hasToken || test.isPending}
            >
              <KeyRound className="w-4 h-4" />
              {test.isPending ? 'Проверяю…' : 'Проверить соединение'}
            </Button>
            {test.data && (
              <div className="text-sm text-emerald-700 dark:text-emerald-400 flex items-center gap-1.5">
                <CheckCircle className="w-4 h-4" /> Подключено: <strong>{test.data.organization}</strong>
                {test.data.inn && <span className="text-slate-500">(идентификатор {test.data.inn})</span>}
              </div>
            )}
            {test.error && <div className="text-sm text-red-600">{formatError(test.error)}</div>}
            {saveToken.error && <div className="text-sm text-red-600">{formatError(saveToken.error)}</div>}
          </div>
        </section>

        <section className="mt-5 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 p-5 space-y-4">
          <h2 className="text-sm font-semibold">Операции импорта</h2>
          <Checkbox
            label="Обновлять уже импортированные записи (если найдены по артикулу/имени)"
            checked={overwrite}
            onChange={setOverwrite}
          />
          <div className="flex gap-3 flex-wrap">
            <Button onClick={() => startProducts.mutate()} disabled={!hasToken || startProducts.isPending || productsJob.data?.status === 'Running'}>
              <Package className="w-4 h-4" />
              {productsJob.data?.status === 'Running' ? 'Товары импортируются…' : 'Товары + группы + цены'}
            </Button>
            <Button onClick={() => startCounterparties.mutate()} disabled={!hasToken || startCounterparties.isPending || counterpartiesJob.data?.status === 'Running'}>
              <Users className="w-4 h-4" />
              {counterpartiesJob.data?.status === 'Running' ? 'Контрагенты импортируются…' : 'Контрагенты'}
            </Button>
          </div>
        </section>

        {productsJob.data && <JobCard title="Импорт товаров" job={productsJob.data} />}
        {counterpartiesJob.data && <JobCard title="Импорт контрагентов" job={counterpartiesJob.data} />}

        <DangerZone />
      </div>
    </div>
  )
}

function JobCard({ title, job }: { title: string; job: JobView }) {
  const done = job.status === 'Succeeded' || job.status === 'Failed'
  const color = job.status === 'Succeeded' ? 'text-emerald-600'
    : job.status === 'Failed' ? 'text-red-600' : 'text-slate-500'
  return (
    <section className="mt-5 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 p-5">
      <h3 className="text-sm font-semibold mb-3 flex items-center gap-2">
        {job.status === 'Succeeded'
          ? <CheckCircle className="w-4 h-4 text-emerald-600" />
          : job.status === 'Failed'
          ? <AlertCircle className="w-4 h-4 text-red-600" />
          : <span className="inline-block w-3 h-3 rounded-full bg-emerald-500 animate-pulse" />}
        {title}
        <span className={`text-xs font-normal ${color}`}>
          {job.status === 'Running' ? (job.stage ?? 'идёт…') : job.status}
        </span>
      </h3>
      <dl className="grid grid-cols-5 gap-3 text-sm">
        <Stat label="Всего" value={job.total} />
        <Stat label="Создано" value={job.created} accent="green" />
        <Stat label="Обновлено" value={job.updated} />
        <Stat label="Пропущено" value={job.skipped} />
        <Stat label="Групп" value={job.groupsCreated} />
      </dl>
      {done && job.message && (
        <div className={`mt-3 text-sm ${color}`}>{job.message}</div>
      )}
      {job.errors.length > 0 && (
        <details className="mt-3">
          <summary className="text-xs text-red-600 cursor-pointer">Ошибок: {job.errors.length}</summary>
          <ul className="mt-2 text-[11px] font-mono bg-red-50 dark:bg-red-950/30 p-3 rounded space-y-0.5 max-h-60 overflow-auto">
            {job.errors.map((e, i) => <li key={i}>{e}</li>)}
          </ul>
        </details>
      )}
    </section>
  )
}

function Stat({ label, value, accent }: { label: string; value: number; accent?: 'green' }) {
  const bg = accent === 'green' ? 'bg-emerald-50 dark:bg-emerald-950/30' : 'bg-slate-50 dark:bg-slate-800/50'
  const fg = accent === 'green' ? 'text-emerald-700 dark:text-emerald-400' : ''
  return (
    <div className={`rounded-lg ${bg} p-3`}>
      <dt className={`text-xs uppercase ${accent === 'green' ? fg : 'text-slate-500'}`}>{label}</dt>
      <dd className={`text-lg font-semibold mt-1 ${fg}`}>{value.toLocaleString('ru')}</dd>
    </div>
  )
}

interface CleanupStats {
  counterparties: number; products: number; productGroups: number
  productBarcodes: number; productPrices: number; supplies: number
  retailSales: number; stocks: number; stockMovements: number
}

function DangerZone() {
  const qc = useQueryClient()

  const stats = useQuery({
    queryKey: ['/api/admin/cleanup/stats'],
    queryFn: async () => (await api.get<CleanupStats>('/api/admin/cleanup/stats')).data,
    refetchOnMount: 'always',
  })

  const [wipeJobId, setWipeJobId] = useState<string | null>(null)
  const wipeJob = useJob(wipeJobId)

  const startWipe = useMutation({
    mutationFn: async () => (await api.post<{ jobId: string }>('/api/admin/cleanup/all/async')).data,
    onSuccess: (d) => {
      setWipeJobId(d.jobId)
      qc.invalidateQueries({ queryKey: ['/api/admin/cleanup/stats'] })
    },
  })

  const confirmAndRun = (label: string, run: () => void) => {
    const word = prompt(`Введи УДАЛИТЬ чтобы подтвердить: ${label}`)
    if (word?.trim().toUpperCase() === 'УДАЛИТЬ') run()
  }

  const s = stats.data

  return (
    <section className="mt-8 rounded-xl border-2 border-red-200 dark:border-red-900/50 bg-red-50/40 dark:bg-red-950/20 p-5">
      <h2 className="text-sm font-semibold text-red-900 dark:text-red-300 flex items-center gap-2 mb-1.5">
        <AlertTriangle className="w-4 h-4" /> Опасная зона — полная очистка данных
      </h2>
      <p className="text-xs text-red-900/80 dark:text-red-300/80 mb-4">
        Удаляет товары, группы, контрагентов, документы и остатки. Справочники, пользователи, склады и организация сохраняются.
      </p>
      {s && (
        <dl className="grid grid-cols-3 md:grid-cols-5 gap-2 text-xs mb-4">
          <Tile label="Контрагенты" value={s.counterparties} />
          <Tile label="Товары" value={s.products} />
          <Tile label="Группы" value={s.productGroups} />
          <Tile label="Штрихкоды" value={s.productBarcodes} />
          <Tile label="Цены" value={s.productPrices} />
          <Tile label="Поставки" value={s.supplies} />
          <Tile label="Чеки" value={s.retailSales} />
          <Tile label="Остатки" value={s.stocks} />
          <Tile label="Движения" value={s.stockMovements} />
        </dl>
      )}
      <Button
        variant="danger"
        onClick={() => confirmAndRun(
          'ВСЕ данные организации',
          () => startWipe.mutate(),
        )}
        disabled={startWipe.isPending || wipeJob.data?.status === 'Running'}
      >
        <Trash2 className="w-4 h-4" />
        {wipeJob.data?.status === 'Running' ? 'Очищаю…' : 'Очистить все данные'}
      </Button>
      {wipeJob.data && (
        <div className="mt-4 rounded-lg bg-white dark:bg-slate-900 border border-red-200 dark:border-red-900/50 p-3 text-sm">
          <div className="flex items-center gap-2 mb-2">
            {wipeJob.data.status === 'Succeeded' && <CheckCircle className="w-4 h-4 text-emerald-600" />}
            {wipeJob.data.status === 'Failed' && <AlertCircle className="w-4 h-4 text-red-600" />}
            {wipeJob.data.status === 'Running' && <span className="inline-block w-3 h-3 rounded-full bg-red-500 animate-pulse" />}
            <strong>{wipeJob.data.stage ?? wipeJob.data.status}</strong>
            <span className="text-xs text-slate-500">удалено записей: {wipeJob.data.deleted.toLocaleString('ru')}</span>
          </div>
          {wipeJob.data.message && <div className="text-xs text-slate-600">{wipeJob.data.message}</div>}
        </div>
      )}
    </section>
  )
}

function Tile({ label, value }: { label: string; value: number }) {
  return (
    <div className="rounded bg-white dark:bg-slate-900 border border-red-200 dark:border-red-900/50 px-2 py-1.5">
      <dt className="text-[10px] uppercase text-slate-500">{label}</dt>
      <dd className="font-mono font-semibold">{value.toLocaleString('ru')}</dd>
    </div>
  )
}
