'use client'

import { Suspense, useEffect, useMemo, useState } from 'react'
import { useSearchParams } from 'next/navigation'
import { AdminShell, hasAdminPermission } from '@/components/admin/AdminShell'
import { backend, type BackendExpertBooking, type StaffAccount } from '@/lib/backend'

const statuses: Array<{ label: string; value: '' | BackendExpertBooking['status'] }> = [
  { label: '全部', value: '' },
  { label: '待支付', value: 'pending_payment' },
  { label: '待确认', value: 'pending_expert' },
  { label: '已确认', value: 'confirmed' },
  { label: '待用户确认', value: 'pending_user_confirm' },
  { label: '争议中', value: 'disputed' },
  { label: '已完成', value: 'completed' },
  { label: '已取消', value: 'cancelled' },
  { label: '已拒绝', value: 'rejected' },
]

function statusLabel(status: BackendExpertBooking['status']) {
  return statuses.find((item) => item.value === status)?.label || status
}

function statusTone(status: BackendExpertBooking['status']) {
  if (status === 'pending_payment') return 'bg-amber-50 text-amber-700'
  if (status === 'pending_expert') return 'bg-sky-50 text-sky-700'
  if (status === 'confirmed') return 'bg-green-50 text-green-700'
  if (status === 'pending_user_confirm') return 'bg-purple-50 text-purple-700'
  if (status === 'disputed') return 'bg-red-50 text-red-700'
  if (status === 'completed') return 'bg-ink text-white'
  return 'bg-bg text-muted'
}

function formatDateTime(value?: string) {
  if (!value) return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '-'
  return `${date.getMonth() + 1}月${date.getDate()}日 ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
}

function localInputValue(value?: string) {
  if (!value) return ''
  const date = new Date(value)
  if (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')}:${String(date.getMinutes()).padStart(2, '0')}`
}

function isoFromLocal(value: string) {
  const date = new Date(value)
  return Number.isNaN(date.getTime()) ? '' : date.toISOString()
}

function hasMeetingInfo(form: BookingForm) {
  return Boolean(form.meetingMethod || form.meetingPlatform || form.meetingNo || form.meetingUrl || form.meetingNote)
}

type BookingForm = {
  startsAt: string
  endsAt: string
  reason: string
  meetingMethod: string
  meetingPlatform: string
  meetingNo: string
  meetingUrl: string
  meetingPassword: string
  meetingNote: string
  meetingInternalNote: string
}

function AdminExpertBookingsContent() {
  const searchParams = useSearchParams()
  const [account, setAccount] = useState<StaffAccount | null>(null)
  const [filter, setFilter] = useState<'' | BackendExpertBooking['status']>('')
  const [keyword, setKeyword] = useState('')
  const [items, setItems] = useState<BackendExpertBooking[]>([])
  const [selectedId, setSelectedId] = useState(searchParams.get('selected') || '')
  const [saved, setSaved] = useState('')
  const [error, setError] = useState('')
  const [form, setForm] = useState<BookingForm>({
    startsAt: '',
    endsAt: '',
    reason: '',
    meetingMethod: 'online',
    meetingPlatform: '',
    meetingNo: '',
    meetingUrl: '',
    meetingPassword: '',
    meetingNote: '',
    meetingInternalNote: '',
  })
  const canWriteBooking = hasAdminPermission(account, 'expert_booking:update')

  async function reload() {
    try {
      const [currentAccount, result] = await Promise.all([
        account ? Promise.resolve(account) : backend.staffMe(),
        backend.adminExpertBookings(),
      ])
      setAccount(currentAccount)
      setItems(result.items)
      setSelectedId((current) => result.items.some((item) => item.id === current || item.bookingNo === current) ? current : result.items[0]?.id || '')
      setError('')
    } catch (err) {
      setError(err instanceof Error ? err.message : '预约列表加载失败')
    }
  }

  useEffect(() => {
    void reload()
  }, [])

  const summary = useMemo(() => items.reduce((result, item) => {
    result[item.status] = (result[item.status] || 0) + 1
    return result
  }, {} as Record<string, number>), [items])

  const visibleItems = useMemo(() => {
    const word = keyword.trim().toLowerCase()
    return items.filter((item) => {
      const matchesStatus = !filter || item.status === filter
      if (!matchesStatus) return false
      if (!word) return true
      const haystack = [
        item.bookingNo,
        item.expert?.name,
        item.contactName,
        item.contactPhone,
        item.user?.phone,
        item.passportNo,
        item.question,
        item.background,
      ].filter(Boolean).join(' ').toLowerCase()
      return haystack.includes(word)
    })
  }, [filter, items, keyword])

  const selected = useMemo(
    () => items.find((item) => item.id === selectedId || item.bookingNo === selectedId)
      || visibleItems[0]
      || items[0]
      || null,
    [items, selectedId, visibleItems],
  )

  useEffect(() => {
    if (!selected) return
    setForm({
      startsAt: localInputValue(selected.startsAt),
      endsAt: localInputValue(selected.endsAt),
      reason: selected.statusReason || '',
      meetingMethod: selected.meetingMethod || 'online',
      meetingPlatform: selected.meetingPlatform || '',
      meetingNo: selected.meetingNo || '',
      meetingUrl: selected.meetingUrl || '',
      meetingPassword: selected.meetingPassword || '',
      meetingNote: selected.meetingNote || '',
      meetingInternalNote: selected.meetingInternalNote || '',
    })
  }, [selected])

  function meetingPayload() {
    return {
      meetingMethod: form.meetingMethod,
      meetingPlatform: form.meetingPlatform,
      meetingNo: form.meetingNo,
      meetingUrl: form.meetingUrl,
      meetingPassword: form.meetingPassword,
      meetingNote: form.meetingNote,
      meetingInternalNote: form.meetingInternalNote,
      statusReason: form.reason,
    }
  }

  async function patchSelected(payload: Record<string, unknown>, successText: string) {
    if (!selected) return
    if (!canWriteBooking) {
      setError('当前账号没有专家预约处理权限')
      return
    }
    try {
      await backend.updateAdminExpertBooking(selected.id, payload)
      setSaved(successText)
      setError('')
      await reload()
    } catch (err) {
      setError(err instanceof Error ? err.message : '预约更新失败')
    }
  }

  async function transitionSelected(status: BackendExpertBooking['status'], successText: string) {
    if (!selected) return
    if (status === 'confirmed' && !hasMeetingInfo(form)) {
      setError('确认预约前需要填写会议方式、平台、会议号、链接或会议说明')
      return
    }
    if (['cancelled', 'rejected', 'completed'].includes(status) && !window.confirm(`确认将预约更新为“${statusLabel(status)}”？`)) return
    await patchSelected({ status, ...meetingPayload(), reason: form.reason }, successText)
  }

  async function saveMeetingOnly() {
    if (!selected) return
    await patchSelected({ status: selected.status, ...meetingPayload() }, '会议与备注已保存')
  }

  async function rescheduleSelected() {
    if (!selected) return
    const startsAt = isoFromLocal(form.startsAt)
    const endsAt = isoFromLocal(form.endsAt)
    if (!startsAt || !endsAt || new Date(startsAt).getTime() >= new Date(endsAt).getTime()) {
      setError('请填写有效的新开始和结束时间')
      return
    }
    await patchSelected({ status: selected.status, startsAt, endsAt, note: form.reason || '管理员调整预约时间', ...meetingPayload() }, '预约时间已调整')
  }

  async function handleChange(action: 'accepted' | 'rejected') {
    if (!selected?.pendingChange) return
    if (!canWriteBooking) {
      setError('当前账号没有专家预约处理权限')
      return
    }
    if (!window.confirm(action === 'accepted' ? '确认同意这次改期？' : '确认拒绝这次改期？')) return
    try {
      await backend.respondAdminExpertBookingReschedule(selected.id, selected.pendingChange.id, {
        action,
        note: form.meetingInternalNote || form.reason || '管理员处理改期',
      })
      setSaved(action === 'accepted' ? '改期已由管理员确认' : '改期已由管理员拒绝')
      setError('')
      await reload()
    } catch (err) {
      setError(err instanceof Error ? err.message : '改期处理失败')
    }
  }

  async function releaseExpired() {
    if (!canWriteBooking) {
      setError('当前账号没有专家预约处理权限')
      return
    }
    if (!window.confirm('确认释放过期未支付的专家预约锁位？')) return
    try {
      await backend.releaseExpiredExpertBookingHolds()
      setSaved('已释放过期未支付锁位')
      setError('')
      await reload()
    } catch (err) {
      setError(err instanceof Error ? err.message : '释放过期锁位失败')
    }
  }

  return (
    <AdminShell
      title="专家预约管理"
      description="按预约状态处理支付锁位、专家确认、会议资料、完成确认和争议。"
      topbarMetrics={[
        { label: '待支付', value: summary.pending_payment || 0 },
        { label: '待确认', value: summary.pending_expert || 0 },
        { label: '已确认', value: summary.confirmed || 0 },
        { label: '待用户确认', value: summary.pending_user_confirm || 0 },
        { label: '争议', value: summary.disputed || 0 },
        { label: '完成', value: summary.completed || 0 },
      ]}
    >
      {(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="mb-2 flex flex-wrap items-center gap-2">
        <input value={keyword} onChange={(event) => setKeyword(event.target.value)} placeholder="搜编号、专家、用户、手机号、通行证" className="h-8 w-full rounded-[4px] border border-line bg-white px-3 text-xs font-bold outline-none focus:border-brand md:w-72" />
        {canWriteBooking && <button type="button" onClick={() => void releaseExpired()} className="h-8 rounded-[4px] border border-line bg-white px-3 text-xs font-extrabold text-muted hover:border-brand hover:text-brand">释放过期锁位</button>}
        <div className="flex min-w-0 flex-1 flex-wrap gap-1.5">
          {statuses.map((item) => (
            <button key={item.label} onClick={() => setFilter(item.value)} className={`h-8 rounded-[4px] border px-2.5 text-xs font-extrabold ${filter === item.value ? 'border-brand bg-brand-light text-brand' : 'border-line bg-white text-muted hover:border-brand hover:text-brand'}`}>
              {item.label}{item.value ? ` ${summary[item.value] || 0}` : ` ${items.length}`}
            </button>
          ))}
        </div>
      </div>

      <div className="grid h-[calc(100vh-198px)] min-h-[520px] gap-3 overflow-hidden xl:grid-cols-[minmax(560px,1fr)_380px]">
        <section 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">{visibleItems.length} 条</div>
          </div>
          <div className="h-[calc(100%-40px)] divide-y divide-line overflow-y-auto">
            {visibleItems.length === 0 ? (
              <div className="px-4 py-10 text-center text-sm font-bold text-muted">暂无预约</div>
            ) : visibleItems.map((item) => (
              <button key={item.id} onClick={() => setSelectedId(item.id)} className={`grid w-full gap-2 px-3 py-3 text-left hover:bg-bg lg:grid-cols-[minmax(260px,1fr)_120px_86px] lg:items-center ${selected?.id === item.id ? 'bg-brand-light' : ''}`}>
                <div className="min-w-0">
                  <div className="truncate text-sm font-extrabold text-ink">{item.expert.name} · {item.contactName}</div>
                  <div className="mt-1 truncate text-[11px] font-bold text-muted">{item.bookingNo} · {item.user?.phone || item.contactPhone} · {item.passportNo}</div>
                  <div className="mt-1 line-clamp-1 text-xs text-text-body">{item.question || item.background || '未填写咨询问题'}</div>
                  {(item.materialFiles || []).length > 0 && <div className="mt-1 text-[11px] font-extrabold text-brand">资料 {(item.materialFiles || []).length} 个</div>}
                  {item.pendingChange && <div className="mt-1 text-[11px] font-extrabold text-amber-700">有改期待处理</div>}
                </div>
                <div className="text-xs font-bold text-muted">{formatDateTime(item.startsAt)}</div>
                <div className={`w-fit rounded-[4px] px-2 py-1 text-[11px] font-extrabold ${statusTone(item.status)}`}>{statusLabel(item.status)}</div>
              </button>
            ))}
          </div>
        </section>

        {selected && (
          <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="min-w-0 truncate text-sm font-extrabold text-ink">处理预约</div>
              <span className={`rounded-[4px] px-2 py-1 text-[11px] font-extrabold ${statusTone(selected.status)}`}>{statusLabel(selected.status)}</span>
            </div>
            <div className="h-[calc(100%-40px)] overflow-y-auto p-3">
              <div className="rounded-[4px] bg-bg p-3 text-xs font-bold leading-6 text-muted">
                <div className="font-extrabold text-ink">{selected.expert.name} · {selected.bookingNo}</div>
                <div>{selected.contactName} / {selected.contactPhone}</div>
                <div>{formatDateTime(selected.startsAt)} - {formatDateTime(selected.endsAt)}</div>
                {selected.holdExpiresAt && selected.status === 'pending_payment' && <div className="text-amber-700">锁位至：{formatDateTime(selected.holdExpiresAt)}</div>}
                {selected.disputeReason && <div className="text-red-700">争议原因：{selected.disputeReason}</div>}
              </div>

              <div className="mt-3 rounded-[4px] border border-line p-3">
                <div className="mb-2 text-xs font-extrabold text-soft">用户提交内容</div>
                <LongText label="咨询问题" value={selected.question} />
                <LongText label="背景说明" value={selected.background} />
                {!selected.question && !selected.background && <div className="text-xs font-bold text-muted">用户未填写咨询问题或背景说明。</div>}
              </div>

              {(selected.materialFiles || []).length > 0 && (
                <div className="mt-3 rounded-[4px] border border-line p-3">
                  <div className="mb-2 text-xs font-extrabold text-soft">用户上传资料</div>
                  <div className="flex flex-wrap gap-1.5">
                    {(selected.materialFiles || []).map((file) => (
                      <a key={file.id} href={file.url} target="_blank" rel="noreferrer" className="rounded-[3px] bg-bg px-2 py-1 text-[11px] font-bold text-brand hover:underline">
                        {file.fileName}
                      </a>
                    ))}
                  </div>
                </div>
              )}

              {selected.pendingChange && (
                <div className="mt-3 rounded-[4px] border border-amber-200 bg-amber-50 p-3 text-xs font-bold leading-6 text-amber-800">
                  改期待处理：{formatDateTime(selected.pendingChange.requestedStartsAt)} · {selected.pendingChange.reason || '无原因'}
                  <div className="mt-2 grid grid-cols-2 gap-2">
                    {canWriteBooking && <button type="button" onClick={() => void handleChange('accepted')} className="h-8 rounded-[4px] bg-brand px-3 text-xs font-extrabold text-white">同意改期</button>}
                    {canWriteBooking && <button type="button" onClick={() => void handleChange('rejected')} className="h-8 rounded-[4px] border border-line bg-white px-3 text-xs font-extrabold text-muted">拒绝改期</button>}
                  </div>
                </div>
              )}

              <div className="mt-3 grid gap-2">
                <div className="grid grid-cols-2 gap-2">
                  <label className="grid gap-1">
                    <span className="text-[11px] font-extrabold text-muted">开始时间</span>
                    <input type="datetime-local" value={form.startsAt} onChange={(event) => setForm((current) => ({ ...current, startsAt: event.target.value }))} className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                  </label>
                  <label className="grid gap-1">
                    <span className="text-[11px] font-extrabold text-muted">结束时间</span>
                    <input type="datetime-local" value={form.endsAt} onChange={(event) => setForm((current) => ({ ...current, endsAt: event.target.value }))} className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                  </label>
                </div>
                <div className="grid grid-cols-2 gap-2">
                  <input value={form.meetingMethod} onChange={(event) => setForm((current) => ({ ...current, meetingMethod: event.target.value }))} placeholder="会议方式 online/offline" className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                  <input value={form.meetingPlatform} onChange={(event) => setForm((current) => ({ ...current, meetingPlatform: event.target.value }))} placeholder="会议平台/地点" className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                </div>
                <div className="grid grid-cols-2 gap-2">
                  <input value={form.meetingNo} onChange={(event) => setForm((current) => ({ ...current, meetingNo: event.target.value }))} placeholder="会议号/房间号" className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                  <input value={form.meetingPassword} onChange={(event) => setForm((current) => ({ ...current, meetingPassword: event.target.value }))} placeholder="入会密码" className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                </div>
                <input value={form.meetingUrl} onChange={(event) => setForm((current) => ({ ...current, meetingUrl: event.target.value }))} placeholder="会议链接" className="h-8 rounded-[4px] border border-line px-2 text-xs outline-none focus:border-brand" />
                <textarea value={form.meetingNote} onChange={(event) => setForm((current) => ({ ...current, meetingNote: event.target.value }))} rows={2} placeholder="会议说明，用户和专家可见" className="rounded-[4px] border border-line p-2 text-xs outline-none focus:border-brand" />
                <textarea value={form.meetingInternalNote} onChange={(event) => setForm((current) => ({ ...current, meetingInternalNote: event.target.value }))} rows={2} placeholder="内部备注" className="rounded-[4px] border border-line p-2 text-xs outline-none focus:border-brand" />
                <textarea value={form.reason} onChange={(event) => setForm((current) => ({ ...current, reason: event.target.value }))} rows={2} placeholder="处理原因/状态备注" className="rounded-[4px] border border-line p-2 text-xs outline-none focus:border-brand" />
              </div>

              <div className="mt-3 grid gap-2">
                {!canWriteBooking && <div className="rounded-[4px] bg-bg px-3 py-2 text-xs font-bold text-muted">当前账号仅可查看专家预约，不能保存会议、改期或推进状态。</div>}
                {canWriteBooking && <button onClick={() => void saveMeetingOnly()} className="h-8 rounded-[4px] border border-line bg-white px-3 text-xs font-extrabold text-muted hover:border-brand hover:text-brand">保存会议/备注</button>}
                {canWriteBooking && !['completed', 'cancelled', 'rejected'].includes(selected.status) && (
                  <button onClick={() => {
                    if (!window.confirm('确认保存这次预约时间调整？')) return
                    void rescheduleSelected()
                  }} className="h-8 rounded-[4px] border border-line bg-white px-3 text-xs font-extrabold text-muted hover:border-brand hover:text-brand">保存时间调整</button>
                )}

                {canWriteBooking && selected.status === 'pending_payment' && (
                  <button onClick={() => void transitionSelected('cancelled', '未支付预约已关闭')} className="h-8 rounded-[4px] border border-amber-200 px-3 text-xs font-extrabold text-amber-700">关闭未支付</button>
                )}
                {canWriteBooking && selected.status === 'pending_expert' && (
                  <div className="grid grid-cols-2 gap-2">
                    <button onClick={() => void transitionSelected('confirmed', '预约已确认并发送会议')} className="h-8 rounded-[4px] bg-brand px-3 text-xs font-extrabold text-white">确认会议</button>
                    <button onClick={() => void transitionSelected('rejected', '预约已拒绝')} className="h-8 rounded-[4px] border border-red-100 text-xs font-extrabold text-red-600">拒绝预约</button>
                  </div>
                )}
                {canWriteBooking && selected.status === 'confirmed' && (
                  <button onClick={() => void transitionSelected('pending_user_confirm', '已提交完成，等待用户确认')} className="h-8 rounded-[4px] bg-ink px-3 text-xs font-extrabold text-white">提交服务完成</button>
                )}
                {canWriteBooking && selected.status === 'pending_user_confirm' && (
                  <button onClick={() => void transitionSelected('completed', '预约已人工确认完成')} className="h-8 rounded-[4px] bg-ink px-3 text-xs font-extrabold text-white">人工确认完成</button>
                )}
                {canWriteBooking && selected.status === 'disputed' && (
                  <div className="grid grid-cols-2 gap-2">
                    <button onClick={() => void transitionSelected('completed', '争议已处理并完成')} className="h-8 rounded-[4px] bg-ink px-3 text-xs font-extrabold text-white">处理为完成</button>
                    <button onClick={() => void transitionSelected('confirmed', '争议已恢复服务')} className="h-8 rounded-[4px] border border-line text-xs font-extrabold text-muted">恢复服务</button>
                  </div>
                )}
                {['completed', 'cancelled', 'rejected'].includes(selected.status) && (
                  <div className="rounded-[4px] bg-bg px-3 py-2 text-xs font-bold text-muted">当前状态只建议维护备注，不再推进流程。</div>
                )}
              </div>
            </div>
          </aside>
        )}
      </div>
    </AdminShell>
  )
}

function LongText({ label, value }: { label: string; value?: string | null }) {
  if (!value) return null
  return (
    <div className="mb-2 last:mb-0">
      <div className="text-[11px] font-extrabold text-muted">{label}</div>
      <div className="mt-1 whitespace-pre-wrap rounded-[4px] bg-bg px-2.5 py-2 text-xs font-bold leading-6 text-ink">{value}</div>
    </div>
  )
}

export default function AdminExpertBookingsPage() {
  return (
    <Suspense fallback={<AdminShell title="专家预约" description="查看专家预约、支付、确认、改期和会议链接。"><div className="border border-line bg-white px-4 py-6 text-sm font-bold text-muted">正在加载专家预约...</div></AdminShell>}>
      <AdminExpertBookingsContent />
    </Suspense>
  )
}
