'use client'

import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useEffect, useMemo, useState } from 'react'
import { CalendarDays, Clock3, FileUp } from 'lucide-react'
import type { Expert } from '@/types'
import { useApp } from '@/components/providers/AppProvider'
import { backend, type BackendExpertSlot } from '@/lib/backend'

type ScheduleDay = {
  date: string
  slots: BackendExpertSlot[]
}

function formatDateLabel(value: string) {
  const date = new Date(value)
  const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()]
  return `${date.getMonth() + 1}月${date.getDate()}日 ${weekday}`
}

function formatSlotTime(slot: BackendExpertSlot) {
  const start = new Date(slot.startsAt)
  const end = new Date(slot.endsAt)
  return `${String(start.getHours()).padStart(2, '0')}:${String(start.getMinutes()).padStart(2, '0')}-${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`
}

function slotStatusLabel(status: BackendExpertSlot['status']) {
  if (status === 'booked') return '已约'
  if (status === 'closed') return '关闭'
  return ''
}

function groupSlots(slots: BackendExpertSlot[]) {
  const groups = new Map<string, BackendExpertSlot[]>()
  slots.forEach((slot) => {
    const label = formatDateLabel(slot.startsAt)
    groups.set(label, [...(groups.get(label) || []), slot])
  })
  return Array.from(groups.entries()).map(([date, items]) => ({ date, slots: items }))
}

function firstAvailableSlot(schedule?: ScheduleDay) {
  return schedule?.slots.find((slot) => slot.status === 'open')?.id ?? ''
}

export function ExpertBookingClient({ expert }: { expert: Expert }) {
  const router = useRouter()
  const { hydrated, user, token } = useApp()
  const [step, setStep] = useState(0)
  const [contactName, setContactName] = useState('')
  const [contactPhone, setContactPhone] = useState('')
  const [background, setBackground] = useState('')
  const [question, setQuestion] = useState('')
  const [materialFileIds, setMaterialFileIds] = useState<string[]>([])
  const [materialNames, setMaterialNames] = useState<string[]>([])
  const [error, setError] = useState('')
  const [slots, setSlots] = useState<BackendExpertSlot[]>([])
  const [slotsLoading, setSlotsLoading] = useState(true)
  const [submitting, setSubmitting] = useState(false)
  const [uploading, setUploading] = useState(false)
  const [selectedDate, setSelectedDate] = useState('')
  const [selectedSlotId, setSelectedSlotId] = useState('')
  const schedules = useMemo(() => groupSlots(slots), [slots])
  const activeSchedule = schedules.find((item) => item.date === selectedDate)
  const selectedSlot = slots.find((slot) => slot.id === selectedSlotId)
  const hasOpenSlots = slots.some((slot) => slot.status === 'open')
  const steps = ['确认信息', '选择时间', '咨询问题']
  const loginRequiredHref = `/login-required?redirect=${encodeURIComponent(`/experts/${expert.slug}/booking`)}&action=expert`

  useEffect(() => {
    if (hydrated && !user) router.replace(loginRequiredHref)
  }, [hydrated, loginRequiredHref, router, user])

  useEffect(() => {
    let cancelled = false
    setSlotsLoading(true)
    void backend.expertSlots(expert.slug)
      .then((result) => {
        if (cancelled) return
        const nextSlots = result.items.filter((slot) => new Date(slot.startsAt).getTime() > Date.now())
        setSlots(nextSlots)
      })
      .catch(() => {
        if (!cancelled) setSlots([])
      })
      .finally(() => {
        if (!cancelled) setSlotsLoading(false)
      })
    return () => {
      cancelled = true
    }
  }, [expert.slug])

  useEffect(() => {
    if (selectedDate && schedules.some((schedule) => schedule.date === selectedDate)) return
    const nextSchedule = schedules.find((schedule) => schedule.slots.some((slot) => slot.status === 'open')) || schedules[0]
    setSelectedDate(nextSchedule?.date || '')
    setSelectedSlotId(firstAvailableSlot(nextSchedule))
  }, [schedules, selectedDate])

  const defaultContactName = user?.name || '平台用户'
  const defaultContactPhone = user?.contactPhone || user?.phone || ''
  const effectiveContactName = contactName || defaultContactName
  const effectiveContactPhone = contactPhone || defaultContactPhone
  const basicReady = effectiveContactName.trim().length > 0 && effectiveContactPhone.trim().length > 0
  const contentReady = background.trim().length > 0 && question.trim().length > 0
  const accepting = expert.acceptingOrders !== false && expert.availabilityStatus !== 'unavailable'
  const canCheckout = accepting && hasOpenSlots && Boolean(selectedSlotId) && basicReady && contentReady && !submitting && !uploading

  async function uploadMaterials(files: FileList | null) {
    if (!files || !token) return
    setUploading(true)
    setError('')
    try {
      const uploaded: Array<{ id: string; fileName: string }> = []
      for (const file of Array.from(files)) {
        uploaded.push(await backend.uploadAccountFile(token, file))
      }
      setMaterialFileIds((current) => [...current, ...uploaded.map((item) => item.id)])
      setMaterialNames((current) => [...current, ...uploaded.map((item) => item.fileName)])
    } catch (err) {
      setError(err instanceof Error ? err.message : '资料上传失败')
    } finally {
      setUploading(false)
    }
  }

  async function goCheckout() {
    if (!user || !token) {
      router.push(loginRequiredHref)
      return
    }
    if (!canCheckout || !selectedSlot) {
      setError('请先填写联系人、联系电话、咨询背景、问题，并选择可预约时段。')
      return
    }
    setSubmitting(true)
    setError('')
    try {
      const booking = await backend.createExpertBooking(token, {
        expertId: expert.id,
        slotId: selectedSlot.id,
        contactName: effectiveContactName.trim(),
        contactPhone: effectiveContactPhone.trim(),
        background: background.trim(),
        question: question.trim(),
        materialFileIds,
      })
      const params = new URLSearchParams({
        type: 'expert',
        expert: expert.slug,
        bookingId: booking.id,
        date: formatDateLabel(selectedSlot.startsAt),
        slot: formatSlotTime(selectedSlot),
        contactName: effectiveContactName.trim(),
        contactPhone: effectiveContactPhone.trim(),
        message: question.trim(),
      })
      router.push(`/checkout?${params.toString()}`)
    } catch (err) {
      setError(err instanceof Error ? err.message : '预约创建失败，请刷新排期后重试。')
    } finally {
      setSubmitting(false)
    }
  }

  function goStep(nextStep: number) {
    if (nextStep > step) {
      if (step === 0 && !basicReady) {
        setError('请填写联系人和联系电话。')
        return
      }
      if (step === 1 && (!hasOpenSlots || !selectedSlotId)) {
        setError('请选择可预约的咨询时段。')
        return
      }
      if (step === 2 && !contentReady) {
        setError('请填写咨询背景和希望专家回答的问题。')
        return
      }
    }
    setError('')
    setStep(nextStep)
    window.scrollTo({ top: 0, behavior: 'smooth' })
  }

  if (!hydrated || !user) {
    return (
      <section className="grid min-h-[calc(100vh-70px)] place-items-center bg-bg px-6 md:min-h-[calc(100vh-106px)]">
        <div className="text-sm font-bold text-muted">正在打开登录提醒...</div>
      </section>
    )
  }

  return (
    <section className="min-h-[calc(100vh-70px)] bg-bg py-6 md:min-h-[calc(100vh-106px)]">
      <div className="mx-auto grid max-w-[1180px] items-start gap-8 px-6 lg:grid-cols-[1fr_340px]">
        <div className="h-fit self-start rounded-[4px] border border-line bg-white p-6">
          <h1 className="text-3xl font-extrabold text-ink">预约咨询</h1>
          <p className="mt-3 text-sm text-muted">{expert.name} · {expert.title} · {expert.organization}</p>

          <div className="mt-6 flex items-center justify-between border-y border-line py-3">
            <div className="text-sm font-extrabold text-brand">
              第 {step + 1} / {steps.length} 步 · {steps[step]}
            </div>
            <div className="flex items-center gap-2">
              {steps.map((item, index) => (
                <button
                  key={item}
                  type="button"
                  onClick={() => goStep(index)}
                  className={`h-2 rounded-full transition-all ${step === index ? 'w-8 bg-brand' : 'w-2 bg-line-dark hover:bg-muted'}`}
                  aria-label={`跳转到${item}`}
                />
              ))}
            </div>
          </div>

          <div className="mt-5">
            {step === 0 && (
              <div className="space-y-5">
                <div>
                  <h2 className="text-xl font-extrabold text-ink">确认联系信息</h2>
                  <p className="mt-2 text-sm leading-7 text-muted">已从个人资料带入，可在本次预约中临时调整。</p>
                </div>
                <div className="grid gap-5 md:grid-cols-2">
                  <label className="block">
                    <span className="mb-2 block text-sm font-bold text-ink">联系人</span>
                    <input value={effectiveContactName} onChange={(event) => setContactName(event.target.value)} placeholder="请输入联系人" className="h-11 w-full rounded-[4px] border border-line px-3 text-sm outline-none focus:border-brand" />
                  </label>
                  <label className="block">
                    <span className="mb-2 block text-sm font-bold text-ink">联系电话</span>
                    <input value={effectiveContactPhone} onChange={(event) => setContactPhone(event.target.value)} placeholder="请输入联系电话" className="h-11 w-full rounded-[4px] border border-line px-3 text-sm outline-none focus:border-brand" />
                  </label>
                </div>
              </div>
            )}

            {step === 1 && (
              <div className="rounded-[4px] border border-line p-5">
                <div className="flex items-center gap-2 text-sm font-extrabold text-ink">
                  <CalendarDays className="h-4 w-4 text-brand" />
                  选择未来 7 天咨询日期
                </div>
                {slotsLoading ? (
                  <div className="mt-4 rounded-[4px] bg-bg px-4 py-5 text-sm text-muted">正在读取专家排期...</div>
                ) : accepting && schedules.length > 0 ? (
                  <>
                    <div className="mt-4 grid gap-3 md:grid-cols-3">
                      {schedules.map((schedule) => {
                        const dayHasOpenSlot = schedule.slots.some((slot) => slot.status === 'open')
                        return (
                          <button
                            key={schedule.date}
                            type="button"
                            disabled={!dayHasOpenSlot}
                            onClick={() => {
                              setSelectedDate(schedule.date)
                              setSelectedSlotId(firstAvailableSlot(schedule))
                            }}
                            className={`rounded-[4px] border px-4 py-3 text-sm font-bold ${
                              selectedDate === schedule.date ? 'border-brand bg-brand-light text-brand' : dayHasOpenSlot ? 'border-line text-text-body hover:border-brand hover:text-brand' : 'cursor-not-allowed border-line bg-bg text-soft'
                            }`}
                          >
                            {schedule.date}
                          </button>
                        )
                      })}
                    </div>
                    <div className="mt-5 flex items-center gap-2 text-sm font-extrabold text-ink">
                      <Clock3 className="h-4 w-4 text-brand" />
                      选择咨询时段
                    </div>
                    <div className="mt-4 grid gap-3 md:grid-cols-3">
                      {activeSchedule?.slots.map((slot) => {
                        const disabled = slot.status !== 'open'
                        const selected = selectedSlotId === slot.id

                        return (
                          <button
                            key={slot.id}
                            type="button"
                            disabled={disabled}
                            onClick={() => setSelectedSlotId(slot.id)}
                            className={`rounded-[4px] border px-4 py-3 text-left text-sm font-bold ${
                              disabled
                                ? 'cursor-not-allowed border-line bg-bg text-soft'
                                : selected
                                  ? 'border-brand bg-brand text-white'
                                  : 'border-line text-text-body hover:border-brand hover:text-brand'
                            }`}
                          >
                            <span className="block">{formatSlotTime(slot)}</span>
                            {disabled && <span className="mt-1 block text-xs font-bold">{slotStatusLabel(slot.status)}</span>}
                          </button>
                        )
                      })}
                    </div>
                  </>
                ) : (
                  <div className="mt-4 rounded-[4px] bg-bg px-4 py-5 text-sm text-muted">
                    当前专家无法预约。
                  </div>
                )}
              </div>
            )}

            {step === 2 && (
              <div className="space-y-5">
                <div>
                  <h2 className="text-xl font-extrabold text-ink">填写咨询问题</h2>
                  <p className="mt-2 text-sm leading-7 text-muted">请说明项目背景和希望专家重点回答的问题。</p>
                </div>
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">咨询背景</span>
                  <textarea value={background} onChange={(event) => setBackground(event.target.value)} rows={5} maxLength={600} placeholder="请填写项目背景、当前进展、已有材料等。" className="w-full rounded-[4px] border border-line p-3 text-sm leading-7 outline-none focus:border-brand" />
                </label>
                <label className="block">
                  <span className="mb-2 block text-sm font-bold text-ink">希望专家回答的问题</span>
                  <textarea value={question} onChange={(event) => setQuestion(event.target.value)} rows={5} maxLength={600} placeholder="请列出希望专家重点回应的问题。" className="w-full rounded-[4px] border border-line p-3 text-sm leading-7 outline-none focus:border-brand" />
                </label>
                <label className="flex min-h-11 cursor-pointer items-center gap-3 rounded-[4px] border border-dashed border-line bg-bg px-4 py-3 text-sm font-bold text-muted hover:border-brand hover:text-brand">
                  <FileUp className="h-4 w-4" />
                  {uploading ? '正在上传资料...' : '上传项目资料'}
                  <input type="file" multiple className="sr-only" onChange={(event) => void uploadMaterials(event.target.files)} />
                </label>
                {materialNames.length > 0 && (
                  <div className="rounded-[4px] bg-bg px-4 py-3 text-xs font-bold leading-6 text-muted">
                    {materialNames.join('、')}
                  </div>
                )}
              </div>
            )}
          </div>

          {error && (
            <div className="mt-5 rounded-[4px] bg-white px-4 py-3 text-sm font-bold text-[#b45309]">
              {error}
            </div>
          )}

          <div className="mt-5 flex items-center justify-between border-t border-line pt-5">
            <button
              type="button"
              disabled={step === 0}
              onClick={() => goStep(Math.max(step - 1, 0))}
              className="rounded-[4px] border border-line px-5 py-2.5 text-sm font-extrabold text-muted disabled:cursor-not-allowed disabled:opacity-40 hover:border-brand hover:text-brand"
            >
              上一步
            </button>
            {step < steps.length - 1 && (
              <button
                type="button"
                onClick={() => goStep(Math.min(step + 1, steps.length - 1))}
                className="rounded-[4px] bg-brand px-6 py-2.5 text-sm font-extrabold text-white hover:bg-brand-dark"
              >
                下一步
              </button>
            )}
          </div>
        </div>
        <aside className="h-fit rounded-[4px] border border-line bg-white p-6 shadow-[0_16px_45px_rgba(15,23,42,0.08)] lg:sticky lg:top-28">
          <div className="text-2xl font-extrabold text-brand">¥{expert.pricePerHour.toLocaleString()}</div>
          <p className="mt-2 text-sm text-muted">1 小时专家咨询，支付后等待专家确认。</p>
          <div className="mt-5 rounded-[4px] bg-bg p-4 text-sm">
            <div className="font-bold text-ink">预约信息</div>
            <div className="mt-2 grid gap-1 text-muted">
              <div>联系人：{effectiveContactName || '未填写'}</div>
              <div>电话：{effectiveContactPhone || '未填写'}</div>
            </div>
          </div>
          {selectedSlot ? (
            <>
              <div className="mt-5 rounded-[4px] bg-bg p-4 text-sm">
                <div className="font-bold text-ink">已选时段</div>
                <div className="mt-1 text-muted">{formatDateLabel(selectedSlot.startsAt)} · {formatSlotTime(selectedSlot)}</div>
              </div>
              <div className="mt-5 rounded-[4px] bg-bg p-4 text-sm">
                <div className="font-bold text-ink">咨询问题</div>
                <div className="mt-2 max-h-28 overflow-auto leading-6 text-muted">{question || '未填写'}</div>
              </div>
              <button
                type="button"
                disabled={!canCheckout}
                onClick={() => void goCheckout()}
                className="mt-6 w-full rounded-[4px] bg-brand py-3 text-sm font-extrabold text-white hover:bg-brand-dark disabled:cursor-not-allowed disabled:bg-line-dark"
              >
                {submitting ? '正在锁定时段...' : '确认预约并结算'}
              </button>
            </>
          ) : (
            <button type="button" disabled className="mt-6 w-full cursor-not-allowed rounded-[4px] bg-bg py-3 text-sm font-extrabold text-soft">
              无法预约
            </button>
          )}
          <Link href={`/experts/${expert.slug}`} className="mt-4 block text-center text-sm font-bold text-brand">返回专家主页</Link>
        </aside>
      </div>
    </section>
  )
}
