import { useQuery } from '@tanstack/react-query'
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'
import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table'
import { useEffect, useMemo, useState } from 'react'
import { z } from 'zod'
import { orpc } from '@/client/orpc'
import type { BatteryInfo } from '@/domain/battery'

const sortOptions = ['createdAtDesc', 'createdAtAsc', 'powerDesc', 'powerAsc'] as const
type BatteryListSort = (typeof sortOptions)[number]

const powerStatusOptions = [0, 1, 2] as const
type PowerStatusFilter = (typeof powerStatusOptions)[number]

const pageSizeOptions = [20, 50, 100] as const
type PageSizeOption = (typeof pageSizeOptions)[number]
const firstPageCursor = '__FIRST_PAGE__'

const searchFilterSchema = z.preprocess(
  (value) => (typeof value === 'string' ? value.trim() || undefined : value),
  z.string().min(1).max(100).optional(),
)

const cursorSchema = z.preprocess(
  (value) => (typeof value === 'string' ? value.trim() || undefined : value),
  z.string().min(1).max(1024).optional(),
)

const searchSchema = z.object({
  search: searchFilterSchema,
  lowPower: z.boolean().optional(),
  powerStatus: z.union([z.literal(0), z.literal(1), z.literal(2)]).optional(),
  sort: z.enum(sortOptions).optional().default('createdAtDesc'),
  pageSize: z.coerce
    .number()
    .pipe(z.union([z.literal(20), z.literal(50), z.literal(100)]))
    .optional()
    .default(50),
  cursor: cursorSchema,
  cursors: z.array(z.string().min(1).max(1024)).max(100).optional().default([]),
})

export const Route = createFileRoute('/batteries')({
  validateSearch: (search) => searchSchema.parse(search),
  component: BatteriesPage,
  errorComponent: () => (
    <main className="flex min-h-screen items-center justify-center bg-[#09090B]">
      <div className="text-center">
        <p className="text-lg text-red-400">数据加载失败</p>
        <p className="mt-2 text-sm text-zinc-500">请检查筛选条件后重试。</p>
      </div>
    </main>
  ),
})

const powerStatusLabel: Record<0 | 1 | 2, string> = {
  0: '未充电',
  1: '充电中',
  2: '已充满',
}

const powerStatusColor: Record<0 | 1 | 2, string> = {
  0: 'text-zinc-400',
  1: 'text-teal-400',
  2: 'text-emerald-400',
}

function powerBarColor(power: number, isLowPower: boolean): string {
  if (isLowPower || power <= 20) return 'bg-red-500'
  if (power <= 50) return 'bg-amber-500'
  return 'bg-teal-500'
}

const columnHelper = createColumnHelper<BatteryInfo>()

function parseSort(value: string): BatteryListSort {
  return sortOptions.find((option) => option === value) ?? 'createdAtDesc'
}

function parsePowerStatus(value: string): PowerStatusFilter | undefined {
  const parsed = Number(value)

  return powerStatusOptions.find((option) => option === parsed)
}

function parsePageSize(value: string): PageSizeOption {
  const parsed = Number(value)

  return pageSizeOptions.find((option) => option === parsed) ?? 50
}

function BatteriesPage() {
  const search = Route.useSearch()
  const navigate = useNavigate({ from: Route.fullPath })
  const [localSearch, setLocalSearch] = useState(search.search || '')

  useEffect(() => {
    setLocalSearch(search.search ?? '')
  }, [search.search])

  useEffect(() => {
    const timer = setTimeout(() => {
      const trimmedSearch = localSearch.trim()
      const nextSearch = trimmedSearch || undefined

      if (nextSearch !== search.search) {
        navigate({
          search: (prev) => ({ ...prev, search: nextSearch, cursor: undefined, cursors: [] }),
        })
      }
    }, 500)
    return () => clearTimeout(timer)
  }, [localSearch, navigate, search.search])

  const { data, error, isPending, isPlaceholderData } = useQuery(
    orpc.battery.batteries.queryOptions({
      input: {
        search: search.search,
        lowPower: search.lowPower,
        powerStatus: search.powerStatus,
        sort: search.sort,
        pageSize: search.pageSize,
        cursor: search.cursor,
      },
      refetchInterval: 30_000,
      placeholderData: (prev) => prev,
    }),
  )

  const columns = useMemo(
    () => [
      columnHelper.accessor('devName', {
        header: '设备名称',
        cell: (info) => (
          <div className="flex flex-col">
            <span className="font-medium text-zinc-100">{info.getValue()}</span>
            <span className="text-[10px] text-zinc-500 tabular-nums">{info.row.original.mac}</span>
          </div>
        ),
      }),
      columnHelper.accessor('devModel', {
        header: '型号',
        cell: (info) => <span className="text-zinc-400">{info.getValue()}</span>,
      }),
      columnHelper.accessor('power', {
        header: '电量',
        cell: (info) => {
          const power = info.getValue()
          const isLow = info.row.original.isLowPower
          return (
            <div className="flex items-center gap-3">
              <span className="w-8 text-right tabular-nums font-medium">{power}%</span>
              <div className="h-1.5 w-16 overflow-hidden rounded-full bg-zinc-800">
                <div className={`h-full ${powerBarColor(power, isLow)}`} style={{ width: `${power}%` }} />
              </div>
            </div>
          )
        },
      }),
      columnHelper.accessor('powerStatus', {
        header: '状态',
        cell: (info) => {
          const status = info.getValue()
          return <span className={`text-xs ${powerStatusColor[status]}`}>{powerStatusLabel[status]}</span>
        },
      }),
      columnHelper.accessor('createTime', {
        header: '最后更新',
        cell: (info) => (
          <span className="text-zinc-500 tabular-nums">{new Date(info.getValue()).toLocaleString('zh-CN')}</span>
        ),
      }),
    ],
    [],
  )

  const table = useReactTable({
    data: data?.items ?? [],
    columns,
    getCoreRowModel: getCoreRowModel(),
  })

  const handleNextPage = () => {
    if (!isPlaceholderData && data?.nextCursor) {
      const nextCursor = data.nextCursor
      navigate({
        search: (prev) => ({
          ...prev,
          cursor: nextCursor,
          cursors: [...(prev.cursors || []), prev.cursor || firstPageCursor],
        }),
      })
    }
  }

  const handlePrevPage = () => {
    const newCursors = [...(search.cursors || [])]
    const lastCursor = newCursors.pop()
    navigate({
      search: (prev) => ({
        ...prev,
        cursor: lastCursor === firstPageCursor ? undefined : lastCursor,
        cursors: newCursors,
      }),
    })
  }

  if (error) {
    return (
      <main className="flex min-h-screen items-center justify-center bg-[#09090B]">
        <div className="text-center">
          <p className="text-lg text-red-400">数据加载失败</p>
          <p className="mt-2 text-sm text-zinc-500">请稍后重试，或联系管理员检查数据源连接。</p>
        </div>
      </main>
    )
  }

  return (
    <main className="min-h-screen bg-[#09090B] text-zinc-100">
      {/* Background gradient */}
      <div className="pointer-events-none fixed inset-0 z-0 flex justify-center">
        <div className="h-[600px] w-[1000px] -translate-y-1/2 rounded-full bg-teal-900/5 blur-[100px]" />
      </div>

      <div className="relative z-10 mx-auto max-w-7xl px-6 py-8">
        <header>
          <div className="flex items-end justify-between">
            <div>
              <h1 className="font-light text-3xl tracking-tight">设备电池实时状态</h1>
              <p className="mt-1 text-sm text-zinc-500">
                {data ? `更新于 ${new Date(data.updatedAt).toLocaleString('zh-CN')}` : '加载中…'}
              </p>
            </div>
            <nav className="text-xs">
              <Link to="/" className="text-zinc-500 hover:text-teal-400 transition-colors">
                ← 返回 SoH 看板
              </Link>
            </nav>
          </div>

          <dl className="mt-8 grid grid-cols-1 gap-4 sm:grid-cols-3">
            <div className="rounded-xl border border-white/5 bg-white/[0.02] p-5">
              <dt className="text-xs font-medium text-zinc-500">设备总数</dt>
              <dd className="mt-2 font-light text-3xl tabular-nums">{data?.total ?? '-'}</dd>
            </div>
            <div className="rounded-xl border border-white/5 bg-white/[0.02] p-5">
              <dt className="text-xs font-medium text-zinc-500">低电量</dt>
              <dd className="mt-2 font-light text-3xl tabular-nums text-red-400">{data?.lowPower ?? '-'}</dd>
            </div>
            <div className="rounded-xl border border-white/5 bg-white/[0.02] p-5">
              <dt className="text-xs font-medium text-zinc-500">充电中</dt>
              <dd className="mt-2 font-light text-3xl tabular-nums text-teal-400">{data?.charging ?? '-'}</dd>
            </div>
          </dl>
        </header>

        <section className="mt-10">
          {/* Controls */}
          <div className="mb-6 flex flex-wrap items-center gap-4">
            <div className="relative flex-1 min-w-[240px]">
              <input
                type="text"
                placeholder="搜索设备名称或 MAC..."
                maxLength={100}
                className="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-2 text-sm focus:border-teal-500/50 focus:outline-none focus:ring-1 focus:ring-teal-500/50"
                value={localSearch}
                onChange={(e) => setLocalSearch(e.target.value)}
              />
            </div>

            <select
              className="rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm focus:outline-none"
              value={search.powerStatus ?? ''}
              onChange={(e) => {
                navigate({
                  search: (prev) => ({
                    ...prev,
                    powerStatus: parsePowerStatus(e.target.value),
                    cursor: undefined,
                    cursors: [],
                  }),
                })
              }}
            >
              <option value="">所有充电状态</option>
              <option value="0">未充电</option>
              <option value="1">充电中</option>
              <option value="2">已充满</option>
            </select>

            <label className="flex items-center gap-2 text-sm text-zinc-400 cursor-pointer">
              <input
                type="checkbox"
                className="rounded border-white/10 bg-white/5 text-teal-500 focus:ring-teal-500/50"
                checked={search.lowPower ?? false}
                onChange={(e) =>
                  navigate({
                    search: (prev) => ({
                      ...prev,
                      lowPower: e.target.checked || undefined,
                      cursor: undefined,
                      cursors: [],
                    }),
                  })
                }
              />
              仅看低电量
            </label>

            <div className="flex-1" />

            <select
              className="rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm focus:outline-none"
              value={search.sort}
              onChange={(e) => {
                navigate({
                  search: (prev) => ({
                    ...prev,
                    sort: parseSort(e.target.value),
                    cursor: undefined,
                    cursors: [],
                  }),
                })
              }}
            >
              <option value="createdAtDesc">最新更新</option>
              <option value="createdAtAsc">最早更新</option>
              <option value="powerDesc">电量从高到低</option>
              <option value="powerAsc">电量从低到高</option>
            </select>

            <select
              className="rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm focus:outline-none"
              value={search.pageSize}
              onChange={(e) => {
                navigate({
                  search: (prev) => ({
                    ...prev,
                    pageSize: parsePageSize(e.target.value),
                    cursor: undefined,
                    cursors: [],
                  }),
                })
              }}
            >
              <option value="20">20 条/页</option>
              <option value="50">50 条/页</option>
              <option value="100">100 条/页</option>
            </select>
          </div>

          <div className="rounded-xl border border-white/5 bg-white/[0.01] overflow-hidden">
            <div className="overflow-x-auto">
              <table className={`w-full border-collapse text-left text-sm ${isPlaceholderData ? 'opacity-60' : ''}`}>
                <thead>
                  {table.getHeaderGroups().map((headerGroup) => (
                    <tr key={headerGroup.id} className="border-b border-white/5 bg-white/[0.02]">
                      {headerGroup.headers.map((header) => (
                        <th key={header.id} className="px-6 py-4 font-medium text-zinc-500 whitespace-nowrap">
                          {flexRender(header.column.columnDef.header, header.getContext())}
                        </th>
                      ))}
                    </tr>
                  ))}
                </thead>
                <tbody className="divide-y divide-white/[0.02]">
                  {isPending && !isPlaceholderData ? (
                    <tr>
                      <td colSpan={columns.length} className="h-32 text-center text-zinc-500">
                        加载中…
                      </td>
                    </tr>
                  ) : data?.items.length === 0 ? (
                    <tr>
                      <td colSpan={columns.length} className="h-32 text-center text-zinc-500">
                        暂无匹配设备
                      </td>
                    </tr>
                  ) : (
                    table.getRowModel().rows.map((row) => (
                      <tr key={row.id} className="transition-colors hover:bg-white/[0.02]">
                        {row.getVisibleCells().map((cell) => (
                          <td key={cell.id} className="px-6 py-4 whitespace-nowrap">
                            {flexRender(cell.column.columnDef.cell, cell.getContext())}
                          </td>
                        ))}
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </div>
          </div>

          <div className="mt-6 flex items-center justify-between text-sm text-zinc-500">
            <div>
              显示 {data?.items.length ?? 0} 台设备
              {data?.total ? ` (共 ${data.total} 台)` : ''}
            </div>
            <div className="flex items-center gap-2">
              <button
                type="button"
                className="rounded-lg border border-white/10 bg-white/5 px-4 py-2 hover:bg-white/10 disabled:opacity-30 disabled:hover:bg-white/5 transition-colors"
                onClick={handlePrevPage}
                disabled={isPlaceholderData || (!search.cursor && (!search.cursors || search.cursors.length === 0))}
              >
                上一页
              </button>
              <button
                type="button"
                className="rounded-lg border border-white/10 bg-white/5 px-4 py-2 hover:bg-white/10 disabled:opacity-30 disabled:hover:bg-white/5 transition-colors"
                onClick={handleNextPage}
                disabled={isPlaceholderData || !data?.nextCursor}
              >
                下一页
              </button>
            </div>
          </div>
        </section>
      </div>
    </main>
  )
}
