'use client'

import { useEffect, useMemo, useState } from 'react'
import { AdminShell } from '@/components/admin/AdminShell'
import { backend, type BackendExpert, type BackendExpertSlot } from '@/lib/backend'

const hours = Array.from({ length: 9 }, (_, index) => 8 + index)

function startOfToday() {
  const date = new Date()
  date.setHours(0, 0, 0, 0)
  return date
}

function addDays(date: Date, days: number) {
  const next = new Date(date)
  next.setDate(next.getDate() + days)
  return next
}

function slotDate(day: Date, hour: number) {
  const date = new Date(day)
  date.setHours(hour, 0, 0, 0)
  return date
}

function localSlotKey(value?: string | Date) {
  const date = value instanceof Date ? value : value ? new Date(value) : null
  if (!date || Number.isNaN(date.getTime())) return ''
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}T${String(date.getHours()).padStart(2, '0')}:00`
}

function formatDay(value: Date) {
  return `${value.getMonth() + 1}/${value.getDate()}`
}

function weekday(value: Date) {
  return ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][value.getDay()]
}

function slotLabel(slot?: BackendExpertSlot) {
  if (!slot) return '未开放'
  if (slot.status === 'open') return '可约'
  if (slot.status === 'booked') return '已约'
  return '未开放'
}

function slotClass(slot?: BackendExpertSlot) {
  if (slot?.status === 'open') return 'border-green bg-green/10 text-green'
  if (slot?.status === 'booked') return 'cursor-not-allowed border-brand bg-brand-light text-brand'
  return 'border-line bg-white text-soft hover:border-brand hover:text-brand'
}

export default function AdminSchedulesPage() {
  const [experts, setExperts] = useState<BackendExpert[]>([])
  const [selectedExpert, setSelectedExpert] = useState('')
  const [slots, setSlots] = useState<BackendExpertSlot[]>([])
  const [saved, setSaved] = useState('')
  const [error, setError] = useState('')
  const today = useMemo(() => startOfToday(), [])
  const days = useMemo(() => Array.from({ length: 7 }, (_, index) => addDays(today, index)), [today])
  const expert = experts.find((item) => item.id === selectedExpert)
  const slotsByKey = useMemo(() => new Map(slots.map((slot) => [localSlotKey(slot.startsAt), slot])), [slots])
  const summary = useMemo(() => ({
    experts: experts.length,
    open: slots.filter((slot) => slot.status === 'open').length,
    booked: slots.filter((slot) => slot.status === 'booked').length,
    closed: slots.filter((slot) => slot.status === 'closed').length,
  }), [experts.length, slots])

  async function loadExperts() {
    const result = await backend.adminExperts()
    setExperts(result.items)
    setSelectedExpert((current) => current || result.items[0]?.id || '')
  }

  async function loadSlots(expertId = selectedExpert) {
    if (!expertId) return
    try {
      const from = today.toISOString()
      const to = addDays(today, 8).toISOString()
      const result = await backend.adminExpertSlots({ expertId, from, to })
      setSlots(result.items)
      setError('')
    } catch (err) {
      setError(err instanceof Error ? err.message : '排期加载失败')
    }
  }

  useEffect(() => {
    void loadExperts().catch((err) => setError(err instanceof Error ? err.message : '专家加载失败'))
  }, [])

  useEffect(() => {
    void loadSlots()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedExpert])

  async function toggleHour(day: Date, hour: number) {
    if (!selectedExpert) return
    const startsAt = slotDate(day, hour)
    const endsAt = slotDate(day, hour + 1)
    const current = slotsByKey.get(localSlotKey(startsAt))
    if (current?.status === 'booked') return
    try {
      await backend.saveAdminExpertSlot({
        expertId: selectedExpert,
        startsAt: startsAt.toISOString(),
        endsAt: endsAt.toISOString(),
        status: current?.status === 'open' ? 'closed' : 'open',
        note: current?.status === 'open' ? '后台关闭可约时段' : '后台开放可约时段',
      })
      setSaved(current?.status === 'open' ? '时段已关闭' : '时段已开放')
      await loadSlots()
    } catch (err) {
      setError(err instanceof Error ? err.message : '排期保存失败')
    }
  }

  return (
    <AdminShell
      title="专家排期"
      description="勾选未来 7 天 8:00-17:00 的 1 小时时段；未勾选则用户端不可预约，已约时段不可改。"
      topbarMetrics={[
        { label: '专家', value: summary.experts },
        { label: '可约', value: summary.open },
        { label: '已约', value: summary.booked },
        { label: '未开放记录', value: summary.closed },
      ]}
    >
      {(saved || error) && <div className={`mb-2 rounded-[4px] px-3 py-2 text-xs font-bold ${error ? 'bg-red-50 text-red-700' : 'bg-green-50 text-green'}`}>{error || saved}</div>}
      <div className="grid h-[calc(100vh-188px)] min-h-[520px] gap-3 overflow-hidden lg:grid-cols-[280px_1fr]">
        <aside className="min-h-0 overflow-hidden border border-line bg-white">
          <div className="flex h-10 items-center justify-between border-b border-line px-3">
            <div className="text-sm font-extrabold text-ink">专家</div>
            <div className="text-xs font-bold text-muted">{experts.length} 位</div>
          </div>
          <div className="h-[calc(100%-40px)] overflow-y-auto p-2">
            {experts.map((item) => (
              <button key={item.id} type="button" onClick={() => setSelectedExpert(item.id)} className={`mb-1.5 w-full rounded-[4px] border px-3 py-2 text-left text-xs font-bold ${selectedExpert === item.id ? 'border-brand bg-brand-light text-brand' : 'border-line text-text-body hover:border-brand hover:text-brand'}`}>
                {item.name}
                <span className="mt-1 block text-xs font-normal text-muted">{item.title} · {item.acceptingOrders ? '接单中' : '停止接单'}</span>
              </button>
            ))}
          </div>
        </aside>

        <section className="min-h-0 overflow-hidden border border-line bg-white">
          <div className="flex h-12 items-center justify-between border-b border-line px-3">
            <div>
              <h2 className="text-sm font-extrabold text-ink">{expert?.name || '请选择专家'} 可预约时间</h2>
              <div className="mt-0.5 text-[11px] font-bold text-soft">点击格子开放/关闭；用户端只展示“可约”。</div>
            </div>
            <div className="flex gap-2 text-[11px] font-bold">
              <span className="rounded-[3px] bg-green/10 px-2 py-1 text-green">可约</span>
              <span className="rounded-[3px] bg-brand-light px-2 py-1 text-brand">已约</span>
              <span className="rounded-[3px] bg-bg px-2 py-1 text-soft">未开放</span>
            </div>
          </div>
          <div className="h-[calc(100%-48px)] overflow-auto p-3">
            <div className="min-w-[880px]">
              <div className="grid grid-cols-[72px_repeat(7,minmax(104px,1fr))] gap-1.5">
                <div />
                {days.map((day) => (
                  <div key={localSlotKey(day)} className="border border-line bg-bg px-2 py-2 text-center">
                    <div className="text-xs font-extrabold text-ink">{formatDay(day)}</div>
                    <div className="mt-0.5 text-[11px] font-bold text-soft">{weekday(day)}</div>
                  </div>
                ))}
                {hours.map((hour) => (
                  <div key={hour} className="contents">
                    <div className="grid h-9 place-items-center border border-line bg-bg text-[11px] font-extrabold text-muted">{hour}:00</div>
                    {days.map((day) => {
                      const start = slotDate(day, hour)
                      const slot = slotsByKey.get(localSlotKey(start))
                      return (
                        <button
                          key={`${localSlotKey(day)}-${hour}`}
                          type="button"
                          disabled={slot?.status === 'booked'}
                          onClick={() => void toggleHour(day, hour)}
                          className={`h-9 rounded-[4px] border px-2 text-[11px] font-extrabold ${slotClass(slot)}`}
                          title={`${formatDay(day)} ${hour}:00-${hour + 1}:00`}
                        >
                          {slotLabel(slot)}
                        </button>
                      )
                    })}
                  </div>
                ))}
              </div>
            </div>
          </div>
        </section>
      </div>
    </AdminShell>
  )
}
