import { Link, NavLink, Outlet } from 'react-router-dom'
import { ChevronDown, Circle, type LucideIcon } from 'lucide-react'
import * as Icons from 'lucide-react'
import { useState } from 'react'
import { useAuth } from '@/contexts/AuthContext'
import { TopBar } from '@/components/TopBar'
import type { MenuNode } from '@/types/menu'
import { cn } from '@/lib/cn'

function getIcon(name: string | null): LucideIcon {
  if (!name) return Circle
  const candidate = (Icons as unknown as Record<string, LucideIcon>)[name]
  return candidate ?? Circle
}

// Map contract type code → ContractType int enum value (mirrors
// Domain/Contracts/ContractType.cs for URL filter).
const TYPE_CODE_TO_INT: Record<string, number> = {
  ThauPhu: 1,
  GiaoKhoan: 2,
  NhaCungCap: 3,
  DichVu: 4,
  MuaBan: 5,
  NguyenTacNcc: 6,
  NguyenTacDv: 7,
}

// Resolve menu key → route. Static map for top-level items, pattern for
// Ct_<Type>_<Action> sub-menu entries.
function resolvePath(key: string): string | null {
  const staticMap: Record<string, string> = {
    Dashboard: '/dashboard',
    Suppliers: '/master/suppliers',
    Projects: '/master/projects',
    Departments: '/master/departments',
    Contracts: '/contracts',
    Forms: '/forms',
    Reports: '/reports',
    Users: '/system/users',
    Roles: '/system/roles',
    Permissions: '/system/permissions',
    Workflows: '/system/workflows',
  }
  if (staticMap[key]) return staticMap[key]

  const match = key.match(/^Ct_([^_]+)_(List|Create|Pending)$/)
  if (match) {
    const [, code, action] = match
    const typeInt = TYPE_CODE_TO_INT[code]
    if (!typeInt) return null
    if (action === 'List') return `/contracts?type=${typeInt}`
    if (action === 'Create') return `/contracts/new?type=${typeInt}`
    if (action === 'Pending') return `/contracts?type=${typeInt}&pendingMe=1`
  }

  // Workflow admin per ContractType: Wf_<Code> → /system/workflows/<code>
  const wfMatch = key.match(/^Wf_(.+)$/)
  if (wfMatch) {
    const code = wfMatch[1]
    if (TYPE_CODE_TO_INT[code]) return `/system/workflows/${code}`
  }

  return null
}

// Admin side: hide the per-ContractType contract submenu (Ct_*) — that's a
// user-app concern. Keep Wf_* workflow-admin leaves.
function isAdminHidden(key: string): boolean {
  return key.startsWith('Ct_')
}

function filterForAdmin(nodes: MenuNode[]): MenuNode[] {
  return nodes
    .filter(n => !isAdminHidden(n.key))
    .map(n => ({ ...n, children: filterForAdmin(n.children) }))
}

function MenuNodeRenderer({ node, depth = 0 }: { node: MenuNode; depth?: number }) {
  const hasChildren = node.children.length > 0
  if (hasChildren) return <MenuGroup node={node} depth={depth} />
  return <MenuLeaf node={node} depth={depth} />
}

function MenuGroup({ node, depth }: { node: MenuNode; depth: number }) {
  // Top-level groups expanded by default, nested ones collapsed to reduce noise
  const [open, setOpen] = useState(depth === 0)
  const Icon = getIcon(node.icon)
  const isTopLevel = depth === 0

  return (
    <div>
      <button
        onClick={() => setOpen(o => !o)}
        className={cn(
          'flex w-full items-center justify-between rounded-md transition',
          isTopLevel
            ? 'px-3 py-2 text-xs font-semibold uppercase tracking-wider text-slate-500 hover:bg-slate-100'
            : 'px-3 py-1.5 text-[13px] font-medium text-slate-600 hover:bg-slate-100 hover:text-slate-900',
        )}
      >
        <span className="flex items-center gap-2">
          <Icon className="h-4 w-4" />
          {node.label}
        </span>
        <ChevronDown className={cn('h-3.5 w-3.5 text-slate-400 transition', !open && '-rotate-90')} />
      </button>
      {open && (
        <div className={cn(
          'mt-0.5 space-y-0.5',
          depth === 0 ? 'pl-2' : 'ml-3 mt-1 border-l border-slate-100 pl-3',
        )}>
          {node.children.map(c => (
            <MenuNodeRenderer key={c.key} node={c} depth={depth + 1} />
          ))}
        </div>
      )}
    </div>
  )
}

function MenuLeaf({ node, depth }: { node: MenuNode; depth: number }) {
  const Icon = getIcon(node.icon)
  const path = resolvePath(node.key)
  if (!path) return null
  const isDeep = depth >= 2

  return (
    <NavLink
      to={path}
      // NavLink's default "startsWith" match causes /contracts?type=1 and
      // /contracts to both highlight. Use `end` for query-param variants.
      end={path.includes('?')}
      className={({ isActive }) =>
        cn(
          'flex items-center gap-2.5 rounded-md transition',
          isDeep ? 'px-3 py-1 text-[12px]' : 'px-3 py-2 text-sm font-medium',
          isActive
            ? 'bg-brand-50 text-brand-700'
            : 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
        )
      }
    >
      <Icon className={cn(isDeep ? 'h-3.5 w-3.5' : 'h-4 w-4')} />
      {node.label}
    </NavLink>
  )
}

export function Layout() {
  const { menu } = useAuth()

  return (
    <div className="flex h-screen">
      <aside className="flex w-64 flex-col border-r border-slate-200 bg-white">
        <div className="flex h-16 items-center border-b border-slate-200 px-5">
          <Link to="/dashboard" className="flex items-center gap-2.5">
            <img src="/logo.png" alt="Solutions" className="h-8 w-auto" />
            <span className="text-[11px] font-semibold uppercase tracking-wider text-slate-400">Admin</span>
          </Link>
        </div>
        <nav className="flex-1 space-y-1 overflow-y-auto p-3">
          {filterForAdmin(menu).map(n => (
            <MenuNodeRenderer key={n.key} node={n} depth={0} />
          ))}
        </nav>
      </aside>
      <div className="flex flex-1 flex-col overflow-hidden">
        <TopBar />
        <main className="flex-1 overflow-auto">
          <Outlet />
        </main>
      </div>
    </div>
  )
}
