// Ticket CNTT — Phase 10.3 G-O6 (S38) + P11-D auto-assign round-robin + SLA timer (S52).
// Read-only kanban list + MaTicket + người xử lý (auto-assign dept IT) + SLA badge (đỏ khi quá hạn).
// S54: reassign cho Admin HOẶC tổ IT (BE capability /assignable-staff). fe-user MIRROR cùng logic.
// S69 re-skin: PURO chrome + Hồ sơ NS visual language (PageHeader ui + KpiCard filter-row + card-accent).
//   KHÔNG đổi logic — mọi query/mutation/endpoint/handler/state giữ NGUYÊN:
//   list ['it-tickets'] · staffQ ['it-tickets','assignable-staff'] · reassign PUT /it-tickets/{id}/assign
//   · canReassign · staff · grouped · formatSlaDue · Dialog. statusKey/breached chỉ LỌC HIỂN THỊ
//   client-side (presentation), KHÔNG gọi API mới, KHÔNG sửa cách fetch.
import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  Pencil, Ticket, Inbox, Loader2, CheckCircle2, Archive, AlarmClockOff, User,
} from 'lucide-react'
import { toast } from 'sonner'
import { PageHeader } from '@/components/ui/PageHeader'
import { KpiCard, type Accent } from '@/components/ui/KpiCard'
import { Button } from '@/components/ui/Button'
import { Dialog } from '@/components/ui/Dialog'
import { Select } from '@/components/ui/Select'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import {
  IT_TICKET_CATEGORY_LABELS, IT_TICKET_PRIORITY_BADGE, IT_TICKET_PRIORITY_LABELS,
  IT_TICKET_STATUS_LABELS, type AssignableStaffResult, type ItTicketDto, type PagedResult,
} from '@/types/workflowApps'

function formatSlaDue(iso: string): string {
  return new Date(iso).toLocaleString('vi-VN', {
    day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit',
  })
}

// ── Presentation-only filter chips (PURO KpiCard row) ─────────────────────────
// 'all' = mặc định hiện mọi cột; statusKey = chỉ hiện 1 trạng thái; 'breached' =
// chỉ hiện ticket quá hạn SLA. Đây là LỌC HIỂN THỊ client-side trên items đã fetch
// — KHÔNG đổi query, KHÔNG gọi BE. Accent map mỗi trạng thái 1 tone Hồ sơ NS.
type StatusChip = 1 | 2 | 3 | 4
type FilterKey = 'all' | StatusChip | 'breached'

const STATUS_CHIPS: { key: StatusChip; icon: typeof Ticket; accent: Accent }[] = [
  { key: 1, icon: Inbox, accent: 'violet' },        // Mới
  { key: 2, icon: Loader2, accent: 'brand' },       // Đang xử lý
  { key: 3, icon: CheckCircle2, accent: 'greenx' }, // Đã giải quyết
  { key: 4, icon: Archive, accent: 'teal' },        // Đã đóng
]

// Kanban column order (giữ nguyên thứ tự gốc 1,2,3,5,4) + tone cột để tô header.
const COLUMN_ACCENT: Record<number, Accent> = {
  1: 'violet', 2: 'brand', 3: 'greenx', 5: 'amberx', 4: 'teal',
}
const COLUMN_RAIL: Record<Accent, string> = {
  brand: 'var(--color-brand-500)',
  teal: 'var(--color-teal-500)',
  violet: 'var(--color-violet-500)',
  amberx: 'var(--color-amberx-500)',
  greenx: 'var(--color-greenx-500)',
}
const COLUMN_HEAD: Record<Accent, string> = {
  brand: 'text-brand-700', teal: 'text-teal-700', violet: 'text-violet-700',
  amberx: 'text-amberx-700', greenx: 'text-greenx-700',
}

export function ItTicketsPage() {
  const qc = useQueryClient()
  const list = useQuery({
    queryKey: ['it-tickets'],
    queryFn: async () => (await api.get<PagedResult<ItTicketDto>>('/it-tickets', { params: { pageSize: 100 } })).data,
  })

  // Reassign Dialog state. `target` = ticket đang gán lại; `pick` = userId đã chọn.
  const [target, setTarget] = useState<ItTicketDto | null>(null)
  const [pick, setPick] = useState('')

  // Presentation-only: chip lọc hiển thị (KHÔNG ảnh hưởng fetch).
  const [filter, setFilter] = useState<FilterKey>('all')

  // BE capability: /assignable-staff trả { canReassign, staff } — canReassign quyết hiện nút
  // trên MỌI card, nên fetch on mount (KHÔNG gate enabled theo dialog). User thường → canReassign=false, staff=[].
  const staffQ = useQuery({
    queryKey: ['it-tickets', 'assignable-staff'],
    queryFn: async () => (await api.get<AssignableStaffResult>('/it-tickets/assignable-staff')).data,
  })
  const canReassign = staffQ.data?.canReassign ?? false
  const staff = staffQ.data?.staff ?? []

  const reassign = useMutation({
    // 204 NoContent — không đọc JSON body.
    mutationFn: (input: { id: string; assignedToUserId: string }) =>
      api.put(`/it-tickets/${input.id}/assign`, { assignedToUserId: input.assignedToUserId }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['it-tickets'] })
      toast.success('Đã gán lại người xử lý')
      closeDialog()
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  function openDialog(t: ItTicketDto) {
    setTarget(t)
    setPick(t.assignedToUserId ?? '') // preselect người xử lý hiện tại
  }
  function closeDialog() {
    setTarget(null)
    setPick('')
  }

  const items = list.data?.items ?? []

  // Group by status for kanban-ish display
  const grouped: Record<number, ItTicketDto[]> = { 1: [], 2: [], 3: [], 4: [], 5: [] }
  items.forEach((t) => {
    if (grouped[t.status]) grouped[t.status].push(t)
  })

  // Presentation-only derive: số ticket quá hạn SLA (cho KpiCard "Quá hạn SLA").
  const breachedCount = items.filter(t => t.slaBreached).length

  // Cột nào hiển thị theo chip lọc (presentation). 'all' = mọi cột; statusKey = 1 cột;
  // 'breached' = mọi cột nhưng chỉ giữ ticket quá hạn (cardMatch lọc bên trong).
  const ORDER = [1, 2, 3, 5, 4]
  const visibleColumns =
    filter === 'all' || filter === 'breached'
      ? ORDER
      : ORDER.filter(s => s === filter)
  const cardMatch = (t: ItTicketDto) => (filter === 'breached' ? t.slaBreached : true)

  return (
    <div className="space-y-5">
      <PageHeader
        eyebrow="Văn phòng số"
        title="Ticket CNTT"
        subtitle="Helpdesk — báo lỗi và yêu cầu hỗ trợ kỹ thuật"
        icon={<Ticket className="h-5 w-5" />}
        accent="violet"
      />

      {/* ── KpiCard filter-row (PURO) — thay status tabs. value = count, onClick =
          set filter hiển thị. Bấm lại chip đang chọn → bỏ lọc (về 'all'). ── */}
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5">
        {STATUS_CHIPS.map(({ key, icon: Icon, accent }) => (
          <KpiCard
            key={key}
            label={IT_TICKET_STATUS_LABELS[key]}
            value={grouped[key].length}
            icon={<Icon className="h-4 w-4" />}
            accent={accent}
            active={filter === key}
            onClick={() => setFilter(prev => (prev === key ? 'all' : key))}
          />
        ))}
        <KpiCard
          label="Quá hạn SLA"
          value={breachedCount}
          icon={<AlarmClockOff className="h-4 w-4" />}
          accent="amberx"
          active={filter === 'breached'}
          onClick={() => setFilter(prev => (prev === 'breached' ? 'all' : 'breached'))}
        />
      </div>

      {/* ── Kanban columns — Hồ sơ NS chrome: card-accent rail + header tinted ── */}
      <div className="grid grid-cols-1 gap-4 md:grid-cols-3 lg:grid-cols-5">
        {visibleColumns.map((statusKey) => {
          const accent = COLUMN_ACCENT[statusKey]
          const cards = grouped[statusKey].filter(cardMatch)
          return (
            <section
              key={statusKey}
              className="card-accent flex min-w-0 flex-col overflow-hidden"
              style={{ ['--accent' as string]: COLUMN_RAIL[accent] }}
            >
              <header className="flex items-center justify-between gap-2 border-b border-slate-100 px-3.5 py-2.5 pl-4">
                <h3 className={cn('text-sm font-semibold tracking-tight', COLUMN_HEAD[accent])}>
                  {IT_TICKET_STATUS_LABELS[statusKey]}
                </h3>
                <span className="rounded-full bg-slate-100 px-1.5 py-0.5 text-[10px] font-semibold tabular-nums text-slate-500">
                  {cards.length}
                </span>
              </header>
              <div className="space-y-2 p-3 pl-4">
                {list.isLoading && <div className="text-xs text-slate-400">Đang tải...</div>}
                {!list.isLoading && cards.length === 0 && (
                  <div className="py-4 text-center text-xs italic text-slate-400">Trống</div>
                )}
                {cards.map((t) => (
                  <div key={t.id} className="space-y-1 rounded-lg border border-slate-200 bg-white p-2.5 text-xs shadow-sm transition hover:border-slate-300 hover:shadow">
                    <div className="flex items-center justify-between">
                      <span className="font-mono text-[10px] text-slate-400">{t.maTicket ?? '—'}</span>
                      <span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium', IT_TICKET_PRIORITY_BADGE[t.priority])}>
                        {IT_TICKET_PRIORITY_LABELS[t.priority]}
                      </span>
                    </div>
                    <div className="truncate font-semibold text-slate-900">{t.title}</div>
                    <div className="text-slate-500">
                      {IT_TICKET_CATEGORY_LABELS[t.category]} · {t.requesterFullName}
                    </div>
                    <div className="flex items-center justify-between gap-1 pt-0.5">
                      <span className="flex min-w-0 items-center gap-1 text-slate-500">
                        <span className="flex min-w-0 items-center gap-1 truncate" title={t.assignedToFullName ?? undefined}>
                          <User className="h-3 w-3 shrink-0 text-slate-400" />
                          {t.assignedToFullName ?? <span className="italic">Chưa giao</span>}
                        </span>
                        {/* Reassign Admin OR tổ IT (BE capability canReassign). Nút nhỏ cạnh người xử lý → mở Dialog gán lại. */}
                        {canReassign && (
                          <button
                            type="button"
                            onClick={() => openDialog(t)}
                            className="shrink-0 rounded p-0.5 text-slate-400 transition hover:bg-violet-50 hover:text-violet-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-500"
                            title="Đổi người xử lý"
                          >
                            <Pencil className="h-3 w-3" />
                          </button>
                        )}
                      </span>
                      {t.slaDueAt && (
                        <span
                          className={cn(
                            'whitespace-nowrap rounded px-1.5 py-0.5 text-[10px]',
                            t.slaBreached ? 'bg-red-100 font-medium text-red-700' : 'bg-slate-100 text-slate-600',
                          )}
                          title={`Hạn xử lý SLA: ${formatSlaDue(t.slaDueAt)}`}
                        >
                          {t.slaBreached ? 'Quá hạn SLA' : `SLA ${formatSlaDue(t.slaDueAt)}`}
                        </span>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            </section>
          )
        })}
      </div>

      {!list.isLoading && items.length === 0 && (
        <div className="card-accent p-8 text-center text-slate-500" style={{ ['--accent' as string]: COLUMN_RAIL.violet }}>
          <span
            className="icon-chip mx-auto mb-3"
            style={{ ['--chip-bg' as string]: 'var(--color-violet-50)', ['--chip-fg' as string]: 'var(--color-violet-700)' }}
            aria-hidden
          >
            <Ticket className="h-5 w-5" />
          </span>
          <p className="text-sm">Chưa có ticket nào.</p>
        </div>
      )}

      {/* Reassign Dialog — Admin OR tổ IT (BE gác quyền + assignee phải thuộc tổ IT). Select danh sách /assignable-staff. */}
      <Dialog
        open={target !== null}
        onClose={closeDialog}
        title="Gán lại người xử lý"
        size="sm"
        footer={
          <>
            <Button variant="outline" onClick={closeDialog}>Hủy</Button>
            <Button
              onClick={() => target && pick && reassign.mutate({ id: target.id, assignedToUserId: pick })}
              disabled={!pick || reassign.isPending}
            >
              {reassign.isPending ? 'Đang lưu…' : 'Lưu'}
            </Button>
          </>
        }
      >
        {target && (
          <div className="space-y-3 text-sm">
            <div className="rounded-lg bg-slate-50 px-3 py-2 text-xs text-slate-500">
              Ticket <span className="font-mono text-slate-700">{target.maTicket ?? '—'}</span> · {target.title}
            </div>
            <div className="space-y-1">
              <label className="text-[11px] font-semibold uppercase tracking-wide text-violet-700">Người xử lý</label>
              <Select value={pick} onChange={e => setPick(e.target.value)} disabled={staffQ.isLoading}>
                <option value="">— Chọn người xử lý —</option>
                {staff.map(u => (
                  <option key={u.id} value={u.id}>{u.fullName}</option>
                ))}
              </Select>
              {staffQ.isLoading && <div className="text-xs text-slate-400">Đang tải danh sách…</div>}
            </div>
          </div>
        )}
      </Dialog>
    </div>
  )
}
