// Admin page (Session 20 Mig 27): Ẩn/Hiện + Đổi tên hiển thị menu cho fe-user
// (eOffice). Admin sidebar fe-admin LUÔN render Label gốc — page này KHÔNG đụng
// admin nav. User Q2=b chốt "edit hiển thị bên ngoài, chỉ của eOffice thôi".
//
// Pattern table inline edit per-row + Save button khi dirty. Reuse api `/menus`
// list + PATCH `/menus/{key}` từ MenusController.
import { useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { Eye, EyeOff, RotateCcw, Save, Search } from 'lucide-react'
import { PageHeader } from '@/components/PageHeader'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'
import { api } from '@/lib/api'
import { getErrorMessage } from '@/lib/apiError'
import { cn } from '@/lib/cn'
import type { MenuItem } from '@/types/menu'

type DraftMap = Record<string, { isVisible: boolean; displayLabel: string }>

export function MenuVisibilityPage() {
  const qc = useQueryClient()
  const [search, setSearch] = useState('')
  const [draft, setDraft] = useState<DraftMap>({})

  const menus = useQuery({
    queryKey: ['menus', 'all'],
    queryFn: async () => (await api.get<MenuItem[]>('/menus')).data,
  })

  const update = useMutation({
    mutationFn: async (p: { key: string; isVisible: boolean; displayLabel: string | null }) => {
      await api.patch(`/menus/${encodeURIComponent(p.key)}`, {
        isVisible: p.isVisible,
        displayLabel: p.displayLabel,
      })
    },
    onSuccess: (_, vars) => {
      toast.success(`Đã lưu menu "${vars.key}".`)
      qc.invalidateQueries({ queryKey: ['menus', 'all'] })
      qc.invalidateQueries({ queryKey: ['my-menu'] })
      setDraft(prev => {
        const next = { ...prev }
        delete next[vars.key]
        return next
      })
    },
    onError: err => toast.error(getErrorMessage(err)),
  })

  const filteredMenus = useMemo(() => {
    const all = menus.data ?? []
    if (!search.trim()) return all
    const q = search.toLowerCase()
    return all.filter(m =>
      m.label.toLowerCase().includes(q)
      || m.key.toLowerCase().includes(q)
      || (m.displayLabel?.toLowerCase().includes(q) ?? false),
    )
  }, [menus.data, search])

  const stats = useMemo(() => {
    const total = menus.data?.length ?? 0
    const hidden = (menus.data ?? []).filter(m => !m.isVisible).length
    const renamed = (menus.data ?? []).filter(m => m.displayLabel != null && m.displayLabel !== m.label).length
    return { total, hidden, visible: total - hidden, renamed }
  }, [menus.data])

  // Current effective draft (merge BE data + local edits)
  function getCurrent(m: MenuItem) {
    const d = draft[m.key]
    return {
      isVisible: d?.isVisible ?? m.isVisible,
      displayLabel: d?.displayLabel ?? (m.displayLabel ?? ''),
    }
  }

  function isDirty(m: MenuItem) {
    const d = draft[m.key]
    if (!d) return false
    return d.isVisible !== m.isVisible || d.displayLabel !== (m.displayLabel ?? '')
  }

  function setDraftField(key: string, patch: Partial<DraftMap[string]>) {
    setDraft(prev => {
      const current = prev[key] ?? {
        isVisible: menus.data?.find(m => m.key === key)?.isVisible ?? true,
        displayLabel: menus.data?.find(m => m.key === key)?.displayLabel ?? '',
      }
      return { ...prev, [key]: { ...current, ...patch } }
    })
  }

  function save(m: MenuItem) {
    const cur = getCurrent(m)
    update.mutate({
      key: m.key,
      isVisible: cur.isVisible,
      displayLabel: cur.displayLabel.trim() === '' ? null : cur.displayLabel.trim(),
    })
  }

  function resetDefault(m: MenuItem) {
    // Khôi phục: isVisible=true + displayLabel=null (xóa override)
    update.mutate({ key: m.key, isVisible: true, displayLabel: null })
  }

  return (
    <div className="space-y-4">
      <PageHeader
        title="Menu eOffice — Ẩn/Hiện + Đổi tên"
        description='Quản lý hiển thị menu cho fe-user (eOffice). Admin sidebar luôn dùng Tên gốc, KHÔNG bị ảnh hưởng.'
      />

      <div className="grid grid-cols-1 gap-3 md:grid-cols-4">
        <StatCard title="Tổng menu" value={stats.total} tone="slate" />
        <StatCard title="Hiển thị (eOffice)" value={stats.visible} tone="emerald" />
        <StatCard title="Đã ẩn" value={stats.hidden} tone="amber" />
        <StatCard title="Đã đổi tên" value={stats.renamed} tone="brand" />
      </div>

      <div className="flex items-center gap-2">
        <div className="relative max-w-sm flex-1">
          <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
          <Input
            value={search}
            onChange={e => setSearch(e.target.value)}
            placeholder="Tìm theo key / label / tên hiển thị..."
            className="pl-9"
          />
        </div>
        <span className="text-xs text-slate-500">{filteredMenus.length}/{stats.total}</span>
      </div>

      {menus.isLoading ? (
        <div className="rounded border border-slate-200 bg-white p-6 text-center text-sm text-slate-500">
          Đang tải...
        </div>
      ) : (
        <div className="overflow-x-auto rounded-lg border border-slate-200 bg-white">
          <table className="min-w-full text-xs">
            <thead className="bg-slate-50 text-slate-600">
              <tr>
                <th className="border-b border-slate-200 px-3 py-2 text-left">Key</th>
                <th className="border-b border-slate-200 px-3 py-2 text-left">Tên gốc</th>
                <th className="border-b border-slate-200 px-3 py-2 text-left">Tên hiển thị cho eOffice</th>
                <th className="border-b border-slate-200 px-3 py-2 text-center">Hiển thị eOffice</th>
                <th className="border-b border-slate-200 px-3 py-2 text-right">Hành động</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-slate-100">
              {filteredMenus.map(m => {
                const cur = getCurrent(m)
                const dirty = isDirty(m)
                const customLabel = cur.displayLabel.trim() !== ''
                const hidden = !cur.isVisible
                return (
                  <tr key={m.key} className={cn(hidden && 'bg-amber-50/40')}>
                    <td className="px-3 py-2">
                      <div className="font-mono text-[11px] text-slate-700">{m.key}</div>
                      {m.parentKey && (
                        <div className="text-[10px] text-slate-400">↳ {m.parentKey}</div>
                      )}
                    </td>
                    <td className="px-3 py-2 text-slate-700">{m.label}</td>
                    <td className="px-3 py-2">
                      <Input
                        value={cur.displayLabel}
                        onChange={e => setDraftField(m.key, { displayLabel: e.target.value })}
                        placeholder={`Mặc định: ${m.label}`}
                        maxLength={200}
                        className={cn(
                          'h-8 text-xs',
                          customLabel && 'border-brand-300 bg-brand-50/40',
                        )}
                      />
                    </td>
                    <td className="px-3 py-2 text-center">
                      <button
                        type="button"
                        onClick={() => setDraftField(m.key, { isVisible: !cur.isVisible })}
                        className={cn(
                          'inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-[11px] font-medium transition',
                          cur.isVisible
                            ? 'border-emerald-300 bg-emerald-50 text-emerald-700 hover:bg-emerald-100'
                            : 'border-amber-300 bg-amber-100 text-amber-700 hover:bg-amber-200',
                        )}
                        title={cur.isVisible ? 'Click để ẩn khỏi eOffice' : 'Click để hiện trên eOffice'}
                      >
                        {cur.isVisible ? <Eye className="h-3 w-3" /> : <EyeOff className="h-3 w-3" />}
                        {cur.isVisible ? 'Hiển thị' : 'Đã ẩn'}
                      </button>
                    </td>
                    <td className="px-3 py-2 text-right">
                      <div className="inline-flex items-center gap-1">
                        {dirty && (
                          <Button
                            onClick={() => save(m)}
                            disabled={update.isPending}
                            className="h-7 gap-1 px-2 text-[11px]"
                          >
                            <Save className="h-3 w-3" /> Lưu
                          </Button>
                        )}
                        {(hidden || customLabel) && !dirty && (
                          <button
                            type="button"
                            onClick={() => resetDefault(m)}
                            disabled={update.isPending}
                            className="inline-flex items-center gap-1 rounded border border-slate-200 px-2 py-1 text-[11px] text-slate-500 hover:bg-slate-100 hover:text-slate-700"
                            title="Khôi phục mặc định: hiển thị + dùng Tên gốc"
                          >
                            <RotateCcw className="h-3 w-3" /> Khôi phục
                          </button>
                        )}
                      </div>
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </div>
      )}

      <p className="text-[11px] text-slate-500">
        💡 Thay đổi áp dụng cho eOffice (fe-user) — user sẽ thấy menu Ẩn/Hiện hoặc tên đổi sau khi reload.
        Sidebar trang Admin này luôn dùng <strong>Tên gốc</strong> để tránh nhầm lẫn khi quản trị.
      </p>
    </div>
  )
}

function StatCard({ title, value, tone }: { title: string; value: number; tone: 'slate' | 'emerald' | 'amber' | 'brand' }) {
  const toneClass = {
    slate: 'border-slate-200 bg-slate-50 text-slate-700',
    emerald: 'border-emerald-200 bg-emerald-50 text-emerald-700',
    amber: 'border-amber-200 bg-amber-50 text-amber-700',
    brand: 'border-brand-200 bg-brand-50 text-brand-700',
  }[tone]
  return (
    <div className={cn('rounded-lg border px-4 py-3', toneClass)}>
      <div className="text-[11px] uppercase tracking-wide opacity-70">{title}</div>
      <div className="mt-0.5 text-2xl font-semibold">{value}</div>
    </div>
  )
}
