import { useEffect, useRef, useState, type ChangeEvent, type DragEvent } from 'react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { AlertTriangle, Download, FileSpreadsheet, Loader2, Upload } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/Button'
import { Dialog } from '@/components/ui/Dialog'
import { Input } from '@/components/ui/Input'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import { SupplierTypeLabel, type SupplierStatus, type SupplierType } from '@/types/master'

// ============================================================================
// Supplier Phase B — Import Excel "Database NCC" (Approach A, layout-locked).
// 2 bước: preview (parse + phân loại, KHÔNG ghi DB) → confirm (ALL-OR-NOTHING).
// Round-trip preview.rows verbatim sang confirm (BE bind { rows: [...] }).
// Field camelCase mirror SupplierImportDtos.cs (30 field + classify).
// ============================================================================

export const RowImportStatus = {
  New: 0,
  Update: 1,
  Skip: 2,
  Error: 3,
} as const
export type RowImportStatus = typeof RowImportStatus[keyof typeof RowImportStatus]

export type SupplierImportRow = {
  rowIndex: number
  packageCategory: string | null
  type: SupplierType
  code: string | null
  name: string | null
  address: string | null
  officeAddress: string | null
  phone: string | null
  fax: string | null
  bankAccount: string | null
  secondaryBankAccount: string | null
  taxCode: string | null
  legalRepresentative: string | null
  legalRepTitle: string | null
  authorizationNote: string | null
  linkGuq: string | null
  linkGpkd: string | null
  linkHsnl: string | null
  contactPerson: string | null
  contactTitle: string | null
  contactPhone: string | null
  email: string | null
  mailingAddress: string | null
  mailRecipient: string | null
  referralSource: string | null
  ownerPmh: string | null
  supplierStatus: SupplierStatus | null
  note: string | null
  sourceUpdatedAt: string | null
  sourceUpdatedBy: string | null
  status: RowImportStatus
  messages: string[]
  existingSupplierId: string | null
  // Thiếu MST → cảnh báo mềm (không kiểm được trùng), KHÔNG chặn nhập (S113)
  mstMissing: boolean
}

export type SupplierImportPreview = {
  rows: SupplierImportRow[]
  newCount: number
  updateCount: number
  skipCount: number
  errorCount: number
  warnings: string[]
  layoutValid: boolean
}

export type SupplierImportResult = {
  inserted: number
  updated: number
  skipped: number
  errors: string[]
  committed: boolean
}

// Full class literal (Pattern 14 — Tailwind JIT không purge dynamic string).
const STATUS_META: Record<RowImportStatus, { label: string; cls: string }> = {
  [RowImportStatus.New]: { label: 'Thêm mới', cls: 'bg-emerald-100 text-emerald-700 ring-emerald-600/20' },
  [RowImportStatus.Update]: { label: 'Cập nhật', cls: 'bg-blue-100 text-blue-700 ring-blue-600/20' },
  [RowImportStatus.Skip]: { label: 'Bỏ qua', cls: 'bg-slate-100 text-slate-600 ring-slate-500/20' },
  [RowImportStatus.Error]: { label: 'Lỗi', cls: 'bg-red-100 text-red-700 ring-red-600/20' },
}

function StatusBadge({ status }: { status: RowImportStatus }) {
  const meta = STATUS_META[status] ?? STATUS_META[RowImportStatus.Skip]
  return (
    <span className={cn('inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-semibold ring-1 ring-inset', meta.cls)}>
      {meta.label}
    </span>
  )
}

export function SupplierImportDialog({ open, onClose }: { open: boolean; onClose: () => void }) {
  const qc = useQueryClient()
  const inputRef = useRef<HTMLInputElement>(null)
  const [dragging, setDragging] = useState(false)
  const [fileName, setFileName] = useState('')
  const [preview, setPreview] = useState<SupplierImportPreview | null>(null)
  const [result, setResult] = useState<SupplierImportResult | null>(null)

  // Reset toàn bộ state mỗi lần mở dialog (tránh giữ preview cũ từ lần import trước).
  useEffect(() => {
    if (open) {
      setFileName('')
      setPreview(null)
      setResult(null)
      setDragging(false)
    }
  }, [open])

  const previewMut = useMutation({
    mutationFn: async (file: File) => {
      const fd = new FormData()
      fd.append('file', file)
      const res = await api.post<SupplierImportPreview>('/suppliers/import/preview', fd, {
        headers: { 'Content-Type': 'multipart/form-data' },
      })
      return res.data
    },
    onSuccess: data => setPreview(data),
    onError: err => {
      setPreview(null)
      toast.error(getErrorMessage(err))
    },
  })

  const confirmMut = useMutation({
    mutationFn: async (rows: SupplierImportRow[]) => {
      const res = await api.post<SupplierImportResult>('/suppliers/import/confirm', { rows })
      return res.data
    },
    onSuccess: data => {
      setResult(data)
      if (data.committed) {
        qc.invalidateQueries({ queryKey: ['suppliers'] })
        toast.success(`Đã nhập: ${data.inserted} mới, ${data.updated} cập nhật, ${data.skipped} bỏ qua`)
        onClose()
      }
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  // Tải file mẫu .xlsx trống (BE dựng bằng ClosedXML — single-source layout, 0 drift).
  const templateMut = useMutation({
    mutationFn: async () => {
      const res = await api.get('/suppliers/import/template', { responseType: 'blob' })
      const url = window.URL.createObjectURL(res.data as Blob)
      const a = document.createElement('a')
      a.href = url
      a.download = 'Mau-Database-NCC.xlsx'
      a.click()
      window.URL.revokeObjectURL(url)
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  // Sửa Mã NCC per-dòng ngay trên lưới preview (round-trip verbatim sang confirm).
  function updateRow(rowIndex: number, patch: Partial<SupplierImportRow>) {
    setPreview(p =>
      p ? { ...p, rows: p.rows.map(x => (x.rowIndex === rowIndex ? { ...x, ...patch } : x)) } : p,
    )
  }

  function pickFile(files: FileList | null) {
    const file = files?.[0]
    if (!file) return
    setFileName(file.name)
    setPreview(null)
    setResult(null)
    previewMut.mutate(file)
  }

  function onDrop(e: DragEvent<HTMLDivElement>) {
    e.preventDefault()
    setDragging(false)
    pickFile(e.dataTransfer.files)
  }

  function onPick(e: ChangeEvent<HTMLInputElement>) {
    pickFile(e.target.files)
    e.target.value = '' // reset để chọn lại cùng file nếu cần
  }

  const counts = preview
    ? [
        { label: 'Thêm mới', value: preview.newCount, cls: 'bg-emerald-100 text-emerald-700' },
        { label: 'Cập nhật', value: preview.updateCount, cls: 'bg-blue-100 text-blue-700' },
        { label: 'Bỏ qua', value: preview.skipCount, cls: 'bg-slate-100 text-slate-600' },
        { label: 'Lỗi', value: preview.errorCount, cls: 'bg-red-100 text-red-700' },
      ]
    : []

  return (
    <Dialog
      open={open}
      onClose={onClose}
      title="Import Excel — Database NCC"
      size="lg"
      footer={
        <>
          <Button variant="outline" onClick={onClose}>
            Đóng
          </Button>
          {preview && preview.layoutValid && (
            <Button
              onClick={() => confirmMut.mutate(preview.rows)}
              disabled={preview.errorCount > 0 || confirmMut.isPending}
            >
              {confirmMut.isPending ? 'Đang nhập…' : 'Xác nhận nhập'}
            </Button>
          )}
        </>
      }
    >
      <div className="space-y-4">
        {/* Vùng chọn / kéo-thả file .xlsx */}
        <div
          onDragOver={e => {
            e.preventDefault()
            setDragging(true)
          }}
          onDragLeave={() => setDragging(false)}
          onDrop={onDrop}
          onClick={() => inputRef.current?.click()}
          className={cn(
            'cursor-pointer rounded-lg border-2 border-dashed px-4 py-6 text-center transition',
            dragging ? 'border-brand-500 bg-brand-50' : 'border-slate-300 bg-slate-50/50 hover:bg-slate-50',
          )}
        >
          <FileSpreadsheet className="mx-auto h-6 w-6 text-slate-400" />
          <div className="mt-2 text-sm font-medium text-slate-600">
            {fileName ? (
              <span className="inline-flex items-center gap-1.5 text-brand-600">
                <Upload className="h-3.5 w-3.5" />
                {fileName}
              </span>
            ) : (
              <>
                Kéo thả file Excel vào đây hoặc <span className="text-brand-600">chọn file</span>
              </>
            )}
          </div>
          <div className="mt-0.5 text-xs text-slate-400">Chỉ nhận file .xlsx đúng layout "Database NCC"</div>
          <input ref={inputRef} type="file" accept=".xlsx" onChange={onPick} className="hidden" />
        </div>

        {/* Tải file mẫu — lấy layout chuẩn trước khi nhập */}
        <div className="flex items-center justify-between gap-3 rounded-lg bg-slate-50 px-3 py-2">
          <p className="text-xs text-slate-500">Chưa có file? Tải mẫu chuẩn rồi điền dữ liệu NCC theo đúng cột.</p>
          <Button
            variant="outline"
            size="sm"
            onClick={() => templateMut.mutate()}
            disabled={templateMut.isPending}
            className="shrink-0"
          >
            <Download className="h-3.5 w-3.5" />
            {templateMut.isPending ? 'Đang tải…' : 'Tải file mẫu'}
          </Button>
        </div>

        {/* Đang phân tích */}
        {previewMut.isPending && (
          <div className="flex items-center justify-center gap-2 py-6 text-sm text-slate-500">
            <Loader2 className="h-4 w-4 animate-spin" />
            Đang phân tích file…
          </div>
        )}

        {/* Sai layout → từ chối, ẩn nút xác nhận */}
        {preview && !preview.layoutValid && (
          <div className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700">
            <div className="flex items-center gap-2 font-semibold">
              <AlertTriangle className="h-4 w-4 shrink-0" />
              Sai layout file Excel — không nhập được
            </div>
            {preview.warnings.length > 0 && (
              <ul className="mt-2 list-disc space-y-0.5 pl-5 text-xs">
                {preview.warnings.map((w, i) => (
                  <li key={i}>{w}</li>
                ))}
              </ul>
            )}
          </div>
        )}

        {/* Layout hợp lệ → tóm tắt + cảnh báo + bảng */}
        {preview && preview.layoutValid && (
          <>
            <div className="flex flex-wrap gap-2">
              {counts.map(c => (
                <span
                  key={c.label}
                  className={cn('inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-semibold', c.cls)}
                >
                  {c.label}: {c.value}
                </span>
              ))}
            </div>

            {preview.warnings.length > 0 && (
              <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-xs text-amber-700">
                <div className="mb-1 flex items-center gap-1.5 font-semibold">
                  <AlertTriangle className="h-3.5 w-3.5 shrink-0" />
                  Cảnh báo
                </div>
                <ul className="list-disc space-y-0.5 pl-5">
                  {preview.warnings.map((w, i) => (
                    <li key={i}>{w}</li>
                  ))}
                </ul>
              </div>
            )}

            <p className="rounded-lg bg-blue-50 px-3 py-2 text-xs text-blue-700">
              Nhập <b>Mã NCC</b> cho từng dòng ở cột "Mã". NCC chưa nhập Mã NCC sẽ lưu ở trạng thái{' '}
              <b>Nháp (ẩn)</b>, chưa hiển thị ra ngoài.
            </p>

            <div className="max-h-[380px] overflow-auto rounded-lg border border-slate-200">
              <table className="w-full border-collapse text-xs">
                <thead className="sticky top-0 z-10 bg-slate-50 text-slate-500">
                  <tr>
                    <th className="w-12 px-2 py-1.5 text-left font-medium">Dòng</th>
                    <th className="w-24 px-2 py-1.5 text-left font-medium">Trạng thái</th>
                    <th className="w-32 px-2 py-1.5 text-left font-medium">Mã</th>
                    <th className="px-2 py-1.5 text-left font-medium">Tên NCC</th>
                    <th className="w-36 px-2 py-1.5 text-left font-medium">Loại</th>
                    <th className="px-2 py-1.5 text-left font-medium">Thông báo</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-100">
                  {preview.rows.map(r => (
                    <tr key={r.rowIndex} className="align-top">
                      <td className="px-2 py-1.5 font-mono text-slate-400">{r.rowIndex}</td>
                      <td className="px-2 py-1.5">
                        <StatusBadge status={r.status} />
                      </td>
                      <td className="px-2 py-1.5">
                        <Input
                          value={r.code ?? ''}
                          onChange={e => updateRow(r.rowIndex, { code: e.target.value })}
                          placeholder="Mã NCC"
                          className="h-7 font-mono text-xs"
                        />
                      </td>
                      <td className="px-2 py-1.5 text-slate-700">{r.name || '—'}</td>
                      <td className="px-2 py-1.5 text-slate-600">{SupplierTypeLabel[r.type] ?? '—'}</td>
                      <td
                        className={cn(
                          'space-y-0.5 px-2 py-1.5',
                          r.status === RowImportStatus.Error ? 'text-red-600' : 'text-amber-600',
                        )}
                      >
                        {r.mstMissing && <div className="text-amber-600">⚠️ Chưa có MST, có thể bị trùng</div>}
                        {r.messages.length > 0 && <div>{r.messages.join('; ')}</div>}
                      </td>
                    </tr>
                  ))}
                  {preview.rows.length === 0 && (
                    <tr>
                      <td colSpan={6} className="px-2 py-4 text-center text-slate-400">
                        Không có dòng dữ liệu nào trong file.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>

            {preview.errorCount > 0 && (
              <div className="text-xs text-red-600">
                Còn {preview.errorCount} dòng lỗi — sửa file Excel rồi tải lại trước khi nhập.
              </div>
            )}
          </>
        )}

        {/* Confirm trả hard-error → ALL-OR-NOTHING, chưa lưu gì */}
        {result && !result.committed && (
          <div className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700">
            <div className="flex items-center gap-2 font-semibold">
              <AlertTriangle className="h-4 w-4 shrink-0" />
              Không thể nhập — chưa có dữ liệu nào được lưu
            </div>
            {result.errors.length > 0 && (
              <ul className="mt-2 list-disc space-y-0.5 pl-5 text-xs">
                {result.errors.map((e, i) => (
                  <li key={i}>{e}</li>
                ))}
              </ul>
            )}
          </div>
        )}
      </div>
    </Dialog>
  )
}
