import { useRef, useState, type FormEvent } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  Download,
  FileSpreadsheet,
  FileText,
  CheckCircle2,
  XCircle,
  Upload,
  Pencil,
  Trash2,
  Plus,
} from 'lucide-react'
import { toast } from 'sonner'
import { PageHeader } from '@/components/PageHeader'
import { DataTable, type Column } from '@/components/DataTable'
import { Button } from '@/components/ui/Button'
import { Dialog } from '@/components/ui/Dialog'
import { Input } from '@/components/ui/Input'
import { Label } from '@/components/ui/Label'
import { Select } from '@/components/ui/Select'
import { Textarea } from '@/components/ui/Textarea'
import { DynamicForm, DynamicFormPreviewError, parseFieldSpec, type DynamicFormValues } from '@/components/DynamicForm'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { type ContractTemplate, ContractTypeLabel } from '@/types/forms'

type EditState = ContractTemplate & { __new?: boolean }

const EMPTY_EDIT: EditState = {
  id: '',
  formCode: '',
  name: '',
  contractType: null,
  fileName: '',
  format: 'docx',
  fieldSpec: null,
  description: null,
  isActive: true,
  __new: true,
}

export function FormsPage() {
  const qc = useQueryClient()
  const [renderDialog, setRenderDialog] = useState<ContractTemplate | null>(null)
  const [edit, setEdit] = useState<EditState | null>(null)
  const [uploadFile, setUploadFile] = useState<File | null>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [dataJson, setDataJson] = useState<string>(`{
  "benA_tenCongTy": "Công ty TNHH Xây dựng Solutions",
  "giaTri": "150,000,000 VND",
  "ngayKy": "21/04/2026"
}`)
  const [dataMode, setDataMode] = useState<'form' | 'json'>('form')
  const [formValues, setFormValues] = useState<DynamicFormValues>({})

  const list = useQuery({
    queryKey: ['contract-templates'],
    queryFn: async () => (await api.get<ContractTemplate[]>('/forms/templates', { params: { onlyActive: false } })).data,
  })

  function useExport(endpoint: 'render' | 'export-pdf', successMsg: string) {
    return useMutation({
      mutationFn: async ({ id, data }: { id: string; data: Record<string, string | null> }) => {
        const res = await api.post(`/forms/templates/${id}/${endpoint}`, data, { responseType: 'blob' })
        const fallback = endpoint === 'export-pdf' ? 'contract.pdf' : 'render.docx'
        return {
          blob: res.data as Blob,
          filename: res.headers['content-disposition']?.match(/filename="?([^";]+)"?/)?.[1] ?? fallback,
        }
      },
      onSuccess: ({ blob, filename }) => {
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = filename
        a.click()
        URL.revokeObjectURL(url)
        toast.success(successMsg)
        setRenderDialog(null)
      },
      onError: err => toast.error(getErrorMessage(err)),
    })
  }

  const render = useExport('render', 'Đã tải file gốc')
  const exportPdf = useExport('export-pdf', 'Đã tải PDF')

  const upload = useMutation({
    mutationFn: async (params: { file: File; meta: EditState }) => {
      const form = new FormData()
      form.append('file', params.file)
      form.append('formCode', params.meta.formCode)
      form.append('name', params.meta.name)
      if (params.meta.contractType !== null) form.append('contractType', String(params.meta.contractType))
      if (params.meta.description) form.append('description', params.meta.description)
      if (params.meta.fieldSpec) form.append('fieldSpec', params.meta.fieldSpec)
      await api.post('/forms/templates', form, { headers: { 'Content-Type': 'multipart/form-data' } })
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['contract-templates'] })
      toast.success('Đã upload template mới')
      setEdit(null)
      setUploadFile(null)
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  const update = useMutation({
    mutationFn: async (meta: EditState) =>
      api.put(`/forms/templates/${meta.id}`, {
        name: meta.name,
        contractType: meta.contractType,
        description: meta.description,
        fieldSpec: meta.fieldSpec,
        isActive: meta.isActive,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['contract-templates'] })
      toast.success('Đã cập nhật template')
      setEdit(null)
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  const del = useMutation({
    mutationFn: async (id: string) => api.delete(`/forms/templates/${id}`),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['contract-templates'] })
      toast.success('Đã vô hiệu hóa template')
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  function parseJsonOrToast(): Record<string, string | null> | null {
    if (!renderDialog) return null
    // Form mode uses the dynamic-form values directly; only parse JSON when
    // the user is on the JSON tab.
    if (dataMode === 'form') return formValues
    try {
      return JSON.parse(dataJson)
    } catch {
      toast.error('JSON không hợp lệ')
      return null
    }
  }

  function handleRender() {
    const data = parseJsonOrToast()
    if (!data || !renderDialog) return
    render.mutate({ id: renderDialog.id, data })
  }

  function handleExportPdf() {
    const data = parseJsonOrToast()
    if (!data || !renderDialog) return
    exportPdf.mutate({ id: renderDialog.id, data })
  }

  function handleSaveEdit(e: FormEvent) {
    e.preventDefault()
    if (!edit) return
    if (edit.__new) {
      if (!uploadFile) {
        toast.error('Chưa chọn file template .docx/.xlsx')
        return
      }
      upload.mutate({ file: uploadFile, meta: edit })
    } else {
      update.mutate(edit)
    }
  }

  const columns: Column<ContractTemplate>[] = [
    {
      key: 'format',
      header: '',
      width: 'w-12',
      align: 'center',
      render: t =>
        t.format === 'xlsx' ? (
          <FileSpreadsheet className="mx-auto h-4 w-4 text-emerald-600" />
        ) : (
          <FileText className="mx-auto h-4 w-4 text-brand-600" />
        ),
    },
    { key: 'formCode', header: 'Form Code', render: t => <span className="font-mono text-xs">{t.formCode}</span>, width: 'w-40' },
    { key: 'name', header: 'Tên', render: t => t.name },
    {
      key: 'contractType',
      header: 'Loại HĐ',
      render: t => (t.contractType ? ContractTypeLabel[t.contractType] : '—'),
      width: 'w-40',
    },
    {
      key: 'isActive',
      header: 'Trạng thái',
      width: 'w-28',
      align: 'center',
      render: t =>
        t.isActive ? (
          <CheckCircle2 className="mx-auto h-4 w-4 text-emerald-600" />
        ) : (
          <span className="inline-flex items-center gap-1 text-xs text-amber-600">
            <XCircle className="h-3.5 w-3.5" />
            Tắt
          </span>
        ),
    },
    {
      key: 'actions',
      header: '',
      align: 'right',
      width: 'w-56',
      render: t => (
        <div className="flex justify-end gap-1">
          <button
            onClick={e => {
              e.stopPropagation()
              // Reset form values + default to Form mode when FieldSpec present
              const parsed = parseFieldSpec(t.fieldSpec)
              setFormValues({})
              setDataMode(parsed.spec && Object.keys(parsed.spec).length > 0 ? 'form' : 'json')
              setRenderDialog(t)
            }}
            disabled={!t.isActive}
            className="flex h-7 w-7 items-center justify-center rounded text-slate-500 hover:bg-slate-100 hover:text-slate-700 disabled:opacity-40"
            title="Render"
          >
            <Download className="h-3.5 w-3.5" />
          </button>
          <button
            onClick={e => {
              e.stopPropagation()
              setEdit({ ...t })
            }}
            className="flex h-7 w-7 items-center justify-center rounded text-slate-500 hover:bg-slate-100 hover:text-slate-700"
            title="Chỉnh sửa"
          >
            <Pencil className="h-3.5 w-3.5" />
          </button>
          {t.isActive && (
            <button
              onClick={e => {
                e.stopPropagation()
                if (window.confirm(`Vô hiệu hóa template "${t.name}"?`)) del.mutate(t.id)
              }}
              className="flex h-7 w-7 items-center justify-center rounded text-slate-500 hover:bg-red-50 hover:text-red-600"
              title="Xóa"
            >
              <Trash2 className="h-3.5 w-3.5" />
            </button>
          )}
        </div>
      ),
    },
  ]

  return (
    <div className="p-6">
      <PageHeader
        title="Biểu mẫu hợp đồng"
        description="Template HĐ hệ thống. Upload mới .docx/.xlsx, edit FieldSpec JSON, render để tải file điền dữ liệu."
        actions={
          <Button onClick={() => setEdit(EMPTY_EDIT)}>
            <Plus className="mr-1 h-4 w-4" />
            Upload template
          </Button>
        }
      />

      <DataTable columns={columns} rows={list.data ?? []} getRowKey={t => t.id} isLoading={list.isLoading} />

      {/* Render dialog */}
      <Dialog
        open={!!renderDialog}
        onClose={() => setRenderDialog(null)}
        title={renderDialog ? `Render: ${renderDialog.name}` : ''}
        size="lg"
        footer={
          <>
            <Button variant="outline" onClick={() => setRenderDialog(null)}>
              Hủy
            </Button>
            <Button
              variant="outline"
              onClick={handleExportPdf}
              disabled={exportPdf.isPending || render.isPending}
            >
              {exportPdf.isPending ? 'Đang export PDF…' : 'Tải PDF'}
            </Button>
            <Button onClick={handleRender} disabled={render.isPending || exportPdf.isPending}>
              {render.isPending ? 'Đang render…' : `Tải file gốc (.${renderDialog?.format ?? 'docx'})`}
            </Button>
          </>
        }
      >
        {(() => {
          const parsed = parseFieldSpec(renderDialog?.fieldSpec)
          const hasSpec = parsed.spec && Object.keys(parsed.spec).length > 0
          return (
            <div className="space-y-4">
              <div className="rounded-md bg-amber-50 px-3 py-2 text-xs text-amber-800">
                <strong>Hướng dẫn:</strong> Placeholder dạng{' '}
                <code className="rounded bg-white px-1">{'{{fieldName}}'}</code>. <strong>Tải file gốc</strong> để edit
                Word/Excel, <strong>Tải PDF</strong> để in/gửi.
              </div>
              <div className="flex items-center justify-between">
                <div className="space-y-1.5 flex-1">
                  <Label>Form Code</Label>
                  <Input value={renderDialog?.formCode ?? ''} disabled />
                </div>
                {hasSpec && (
                  <div className="ml-4 flex rounded-md border border-slate-200 bg-slate-50 p-0.5 text-xs">
                    <button
                      type="button"
                      onClick={() => setDataMode('form')}
                      className={`rounded px-3 py-1.5 font-medium transition ${
                        dataMode === 'form' ? 'bg-white text-slate-900 shadow-sm' : 'text-slate-500 hover:text-slate-700'
                      }`}
                    >
                      Form
                    </button>
                    <button
                      type="button"
                      onClick={() => setDataMode('json')}
                      className={`rounded px-3 py-1.5 font-medium transition ${
                        dataMode === 'json' ? 'bg-white text-slate-900 shadow-sm' : 'text-slate-500 hover:text-slate-700'
                      }`}
                    >
                      JSON
                    </button>
                  </div>
                )}
              </div>
              {parsed.error && <DynamicFormPreviewError error={parsed.error} />}
              {hasSpec && dataMode === 'form' ? (
                <DynamicForm
                  spec={parsed.spec!}
                  values={formValues}
                  onChange={(k, v) => setFormValues(prev => ({ ...prev, [k]: v }))}
                />
              ) : (
                <div className="space-y-1.5">
                  <Label>Data JSON (placeholder → value)</Label>
                  <Textarea
                    rows={10}
                    value={dataJson}
                    onChange={e => setDataJson(e.target.value)}
                    className="font-mono text-xs"
                  />
                  {!hasSpec && (
                    <div className="text-[11px] text-slate-400">
                      Template này chưa có FieldSpec — dùng JSON tự do. Thêm FieldSpec vào template để dùng form builder.
                    </div>
                  )}
                </div>
              )}
            </div>
          )
        })()}
      </Dialog>

      {/* Upload / Edit dialog */}
      <Dialog
        open={!!edit}
        onClose={() => {
          setEdit(null)
          setUploadFile(null)
        }}
        title={edit?.__new ? 'Upload template mới' : `Chỉnh sửa: ${edit?.name ?? ''}`}
        size="lg"
        footer={
          <>
            <Button
              variant="outline"
              onClick={() => {
                setEdit(null)
                setUploadFile(null)
              }}
            >
              Hủy
            </Button>
            <Button
              onClick={handleSaveEdit}
              disabled={upload.isPending || update.isPending}
              type="submit"
              form="template-edit-form"
            >
              {upload.isPending || update.isPending
                ? 'Đang lưu…'
                : edit?.__new
                  ? 'Upload'
                  : 'Lưu thay đổi'}
            </Button>
          </>
        }
      >
        {edit && (
          <form id="template-edit-form" onSubmit={handleSaveEdit} className="space-y-4">
            {edit.__new && (
              <div className="space-y-1.5">
                <Label htmlFor="file">File template (.docx / .xlsx)</Label>
                <input
                  id="file"
                  ref={fileInputRef}
                  type="file"
                  accept=".docx,.xlsx"
                  onChange={e => setUploadFile(e.target.files?.[0] ?? null)}
                  className="block w-full rounded-md border border-slate-300 bg-white px-3 py-1.5 text-sm file:mr-3 file:rounded file:border-0 file:bg-brand-50 file:px-3 file:py-1 file:text-sm file:font-medium file:text-brand-700 hover:file:bg-brand-100"
                />
                {uploadFile && (
                  <div className="text-xs text-slate-500">
                    {uploadFile.name} · {(uploadFile.size / 1024).toFixed(1)} KB
                  </div>
                )}
              </div>
            )}

            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1.5">
                <Label htmlFor="formCode">Form Code *</Label>
                <Input
                  id="formCode"
                  value={edit.formCode}
                  onChange={e => setEdit({ ...edit, formCode: e.target.value })}
                  disabled={!edit.__new}
                  placeholder="SOL-CCM-FO-XXX"
                  className="font-mono"
                  required
                />
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="contractType">Loại HĐ</Label>
                <Select
                  id="contractType"
                  value={edit.contractType ?? ''}
                  onChange={e =>
                    setEdit({ ...edit, contractType: e.target.value === '' ? null : Number(e.target.value) })
                  }
                >
                  <option value="">— (phụ lục / điều kiện chung)</option>
                  {Object.entries(ContractTypeLabel).map(([k, v]) => (
                    <option key={k} value={k}>
                      {v}
                    </option>
                  ))}
                </Select>
              </div>
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="name">Tên template *</Label>
              <Input
                id="name"
                value={edit.name}
                onChange={e => setEdit({ ...edit, name: e.target.value })}
                placeholder="VD: Hợp đồng Giao khoán"
                required
              />
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="description">Mô tả</Label>
              <Textarea
                id="description"
                rows={2}
                value={edit.description ?? ''}
                onChange={e => setEdit({ ...edit, description: e.target.value || null })}
              />
            </div>

            <div className="space-y-1.5">
              <Label htmlFor="fieldSpec">FieldSpec JSON (optional)</Label>
              <Textarea
                id="fieldSpec"
                rows={8}
                value={edit.fieldSpec ?? ''}
                onChange={e => setEdit({ ...edit, fieldSpec: e.target.value || null })}
                placeholder={`{\n  "benA_tenCongTy": { "label": "Tên Cty bên A", "type": "text", "required": true },\n  "giaTri": { "label": "Giá trị", "type": "currency" }\n}`}
                className="font-mono text-xs"
              />
              <div className="text-xs text-slate-400">
                Mô tả các field trong template. Future iteration sẽ render form builder từ spec này.
              </div>
            </div>

            {!edit.__new && (
              <label className="flex items-center gap-2 text-sm">
                <input
                  type="checkbox"
                  checked={edit.isActive}
                  onChange={e => setEdit({ ...edit, isActive: e.target.checked })}
                  className="h-4 w-4 accent-brand-600"
                />
                <span>Kích hoạt (hiển thị khi tạo HĐ)</span>
              </label>
            )}
          </form>
        )}
      </Dialog>

      <div className="mt-4 flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50 px-3 py-2 text-xs text-slate-500">
        <Upload className="h-3.5 w-3.5" />
        File template lưu tại <code className="rounded bg-white px-1">wwwroot/templates/</code>, placeholder cú pháp{' '}
        <code className="rounded bg-white px-1">{'{{fieldKey}}'}</code>.
      </div>
    </div>
  )
}
