/* eslint-disable react-refresh/only-export-components */
import { useEffect, useRef, useState } from 'react'
import {
  ChevronLeft,
  ChevronRight,
  RefreshCw,
  Search,
  Settings2,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Input } from '@/components/ui/input'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { ConfigDrawer } from '@/components/config-drawer'
import { Header } from '@/components/layout/header'
import { Main } from '@/components/layout/main'
import { ProfileDropdown } from '@/components/profile-dropdown'
import { ThemeSwitch } from '@/components/theme-switch'

export interface PageData<T> {
  items: T[]
  page: number
  page_size: number
  total: number
  total_pages: number
}

export type Column<T> = {
  key: string
  label: string
  className?: string
  mobile?: boolean
  render: (item: T) => React.ReactNode
}

export function formatDate(value?: string | null) {
  return value
    ? new Intl.DateTimeFormat('zh-CN', {
        timeZone: 'Asia/Shanghai',
        dateStyle: 'short',
        timeStyle: 'medium',
      }).format(new Date(value))
    : '-'
}

export function formatBytes(value: number) {
  if (value < 1024) return `${value} B`
  if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`
  if (value < 1024 * 1024 * 1024)
    return `${(value / 1024 / 1024).toFixed(1)} MB`
  return `${(value / 1024 / 1024 / 1024).toFixed(2)} GB`
}

export function formatCompactNumber(value: number) {
  const absolute = Math.abs(value)
  if (absolute < 1_000) return new Intl.NumberFormat('zh-CN').format(value)

  const divisor = absolute >= 1_000_000 ? 1_000_000 : 1_000
  const suffix = divisor === 1_000_000 ? 'M' : 'K'
  const scaled = value / divisor
  const maximumFractionDigits =
    Math.abs(scaled) >= 100 ? 0 : Math.abs(scaled) >= 10 ? 1 : 2

  return `${new Intl.NumberFormat('en-US', {
    maximumFractionDigits,
  }).format(scaled)}${suffix}`
}

export function useUrlFilters(defaults: Record<string, string> = {}) {
  const defaultsRef = useRef(defaults)
  const [filters, setFilters] = useState<Record<string, string>>(() => {
    const values = { ...defaults }
    const search = new URLSearchParams(window.location.search)
    search.forEach((value, key) => {
      values[key] = value
    })
    return values
  })

  useEffect(() => {
    const search = new URLSearchParams()
    Object.entries(filters).forEach(([key, value]) => {
      if (value && value !== defaultsRef.current[key]) search.set(key, value)
    })
    const suffix = search.toString()
    window.history.replaceState(
      null,
      '',
      `${window.location.pathname}${suffix ? `?${suffix}` : ''}`
    )
  }, [filters])

  const update = (key: string, value: string) => {
    setFilters((current) => ({
      ...current,
      [key]: value,
      ...(key === 'page' ? {} : { page: '1' }),
    }))
  }
  return { filters, update, setFilters }
}

export function GovernanceShell({
  title,
  description,
  actions,
  children,
}: {
  title: string
  description: string
  actions?: React.ReactNode
  children: React.ReactNode
}) {
  return (
    <>
      <Header fixed>
        <div className='ms-auto flex items-center gap-3'>
          <ThemeSwitch />
          <ConfigDrawer />
          <ProfileDropdown />
        </div>
      </Header>
      <Main className='flex flex-1 flex-col gap-5'>
        <div className='flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between'>
          <div>
            <h1 className='text-2xl font-semibold'>{title}</h1>
            <p className='mt-1 text-sm text-muted-foreground'>{description}</p>
          </div>
          {actions}
        </div>
        {children}
      </Main>
    </>
  )
}

export function FilterBar({
  value,
  placeholder,
  onChange,
  onRefresh,
  children,
  refreshing,
}: {
  value: string
  placeholder: string
  onChange: (value: string) => void
  onRefresh: () => void
  refreshing?: boolean
  children?: React.ReactNode
}) {
  return (
    <div className='flex flex-col gap-2 border-y py-3 md:flex-row md:items-center'>
      <div className='relative min-w-0 flex-1 md:max-w-sm'>
        <Search className='absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground' />
        <Input
          value={value}
          onChange={(event) => onChange(event.target.value)}
          placeholder={placeholder}
          className='pl-9'
        />
      </div>
      {children}
      <Button
        variant='outline'
        size='icon'
        title='刷新'
        aria-label='刷新列表'
        onClick={onRefresh}
      >
        <RefreshCw className={cn('size-4', refreshing && 'animate-spin')} />
      </Button>
    </div>
  )
}

export function GovernanceTable<T extends { id: string | number }>({
  data,
  columns,
  selected,
  onSelectedChange,
  onRowClick,
  loading,
  emptyText = '没有符合条件的数据',
}: {
  data: T[]
  columns: Column<T>[]
  selected?: Array<string | number>
  onSelectedChange?: (ids: Array<string | number>) => void
  onRowClick?: (item: T) => void
  loading?: boolean
  emptyText?: string
}) {
  const [hiddenColumns, setHiddenColumns] = useState<string[]>([])
  const selectedSet = new Set(selected)
  const selectable = Boolean(onSelectedChange)
  const allSelected =
    data.length > 0 && data.every((item) => selectedSet.has(item.id))
  const visibleColumns = columns.filter(
    (column) => !hiddenColumns.includes(column.key)
  )
  return (
    <div className='min-w-0 border-b'>
      <div className='flex justify-end border-b py-2'>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant='ghost' size='sm'>
              <Settings2 />列
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align='end'>
            <DropdownMenuLabel>显示列</DropdownMenuLabel>
            {columns.map((column) => {
              const visible = !hiddenColumns.includes(column.key)
              return (
                <DropdownMenuCheckboxItem
                  key={column.key}
                  checked={visible}
                  disabled={visible && visibleColumns.length === 1}
                  onCheckedChange={() =>
                    setHiddenColumns((current) =>
                      visible
                        ? [...current, column.key]
                        : current.filter((key) => key !== column.key)
                    )
                  }
                >
                  {column.label || '操作'}
                </DropdownMenuCheckboxItem>
              )
            })}
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
      <div className='min-w-0 overflow-x-auto'>
        <Table className='min-w-[860px]'>
          <TableHeader className='sticky top-0 z-10 bg-background'>
            <TableRow>
              {selectable && (
                <TableHead className='w-11'>
                  <Checkbox
                    checked={allSelected}
                    aria-label='选择当前页'
                    onCheckedChange={() =>
                      onSelectedChange?.(
                        allSelected
                          ? (selected ?? []).filter(
                              (id) => !data.some((item) => item.id === id)
                            )
                          : [
                              ...(selected ?? []),
                              ...data
                                .map((item) => item.id)
                                .filter((id) => !selectedSet.has(id)),
                            ]
                      )
                    }
                  />
                </TableHead>
              )}
              {visibleColumns.map((column) => (
                <TableHead
                  key={column.key}
                  className={cn(
                    !column.mobile && 'hidden md:table-cell',
                    column.className
                  )}
                >
                  {column.label}
                </TableHead>
              ))}
            </TableRow>
          </TableHeader>
          <TableBody>
            {loading && (
              <TableRow>
                <TableCell
                  colSpan={visibleColumns.length + (selectable ? 1 : 0)}
                  className='h-32 text-center text-muted-foreground'
                >
                  正在加载...
                </TableCell>
              </TableRow>
            )}
            {!loading && data.length === 0 && (
              <TableRow>
                <TableCell
                  colSpan={visibleColumns.length + (selectable ? 1 : 0)}
                  className='h-32 text-center text-muted-foreground'
                >
                  {emptyText}
                </TableCell>
              </TableRow>
            )}
            {data.map((item) => (
              <TableRow
                key={item.id}
                className={cn(onRowClick && 'cursor-pointer')}
                onClick={() => onRowClick?.(item)}
              >
                {selectable && (
                  <TableCell onClick={(event) => event.stopPropagation()}>
                    <Checkbox
                      checked={selectedSet.has(item.id)}
                      aria-label={`选择 ${item.id}`}
                      onCheckedChange={() =>
                        onSelectedChange?.(
                          selectedSet.has(item.id)
                            ? (selected ?? []).filter((id) => id !== item.id)
                            : [...(selected ?? []), item.id]
                        )
                      }
                    />
                  </TableCell>
                )}
                {visibleColumns.map((column) => (
                  <TableCell
                    key={column.key}
                    className={cn(
                      !column.mobile && 'hidden md:table-cell',
                      column.className
                    )}
                  >
                    {column.render(item)}
                  </TableCell>
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </div>
    </div>
  )
}

export function Pagination({
  page,
  pageSize,
  total,
  totalPages,
  onPage,
}: {
  page: number
  pageSize: number
  total: number
  totalPages: number
  onPage: (page: number) => void
}) {
  return (
    <div className='flex items-center justify-between gap-3 py-3 text-sm'>
      <span className='text-muted-foreground'>
        共 {total} 项，第 {Math.min(page, Math.max(totalPages, 1))}/
        {Math.max(totalPages, 1)} 页，每页 {pageSize} 项
      </span>
      <div className='flex gap-2'>
        <Button
          size='icon'
          variant='outline'
          title='上一页'
          disabled={page <= 1}
          onClick={() => onPage(page - 1)}
        >
          <ChevronLeft />
        </Button>
        <Button
          size='icon'
          variant='outline'
          title='下一页'
          disabled={page >= totalPages}
          onClick={() => onPage(page + 1)}
        >
          <ChevronRight />
        </Button>
      </div>
    </div>
  )
}
