import { Input, Picker, ScrollView, Text, Textarea, View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import { useMemo, useState } from 'react'
import { backend, yuan, type BackendExpertApplication, type BackendExpertBooking, type BackendExpertProfile, type BackendExpertSlot, type BackendExpertWallet, type BackendExpertWithdrawal } from '@/api/backend'
import { BottomDrawer, EmptyState, MetaRow, Page } from '@/components/ui'
import { ensureLoggedIn, getToken } from '@/stores/storage'
import { toast } from '@/utils/nav'

type MeetingDraft = { method: string; platform: string; no: string; url: string; password: string; note: string }
type RescheduleDraft = { startsAt: string; endsAt: string; reason: string }

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

function statusLabel(status?: BackendExpertBooking['status']) {
  if (status === 'pending_payment') return '待用户支付'
  if (status === 'pending_expert') return '待确认'
  if (status === 'confirmed') return '预约中'
  if (status === 'pending_user_confirm') return '待用户确认'
  if (status === 'disputed') return '争议中'
  if (status === 'completed') return '已完成'
  if (status === 'rejected') return '已拒绝'
  return '已取消'
}

function applicationLabel(status?: BackendExpertApplication['status']) {
  if (status === 'pending') return '审核中'
  if (status === 'approved') return '已通过'
  if (status === 'rejected') return '未通过'
  return '未提交'
}

function pad(value: number) {
  return String(value).padStart(2, '0')
}

function startOfToday() {
  const now = new Date()
  return new Date(now.getFullYear(), now.getMonth(), now.getDate())
}

function addDays(date: Date, days: number) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days)
}

function formatDate(value?: string | null) {
  if (!value) return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '-'
  return `${date.getMonth() + 1}月${date.getDate()}日 ${pad(date.getHours())}:${pad(date.getMinutes())}`
}

function localValue(value?: string | null) {
  if (!value) return ''
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return ''
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}

function localSlotKey(value: string | Date) {
  const date = typeof value === 'string' ? new Date(value) : value
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}`
}

function slotDate(day: Date, hour: number) {
  return new Date(day.getFullYear(), day.getMonth(), day.getDate(), hour)
}

function datePart(value: string) {
  return value.split(' ')[0] || ''
}

function timePart(value: string) {
  return value.split(' ')[1] || '09:00'
}

function withDate(value: string, nextDate: string) {
  return `${nextDate} ${timePart(value)}`
}

function withTime(value: string, nextTime: string) {
  return `${datePart(value)} ${nextTime}`
}

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

function cents(value: string) {
  return Math.round(Number(value || 0) * 100)
}

export default function ExpertHomePage() {
  const [application, setApplication] = useState<BackendExpertApplication | null>(null)
  const [profile, setProfile] = useState<BackendExpertProfile | null>(null)
  const [bookings, setBookings] = useState<BackendExpertBooking[]>([])
  const [slots, setSlots] = useState<BackendExpertSlot[]>([])
  const [wallet, setWallet] = useState<BackendExpertWallet | null>(null)
  const [withdrawals, setWithdrawals] = useState<BackendExpertWithdrawal[]>([])
  const [loading, setLoading] = useState(false)
  const [meetingForms, setMeetingForms] = useState<Record<string, MeetingDraft>>({})
  const [rescheduleForms, setRescheduleForms] = useState<Record<string, RescheduleDraft>>({})
  const [withdrawOpen, setWithdrawOpen] = useState(false)
  const [withdrawDraft, setWithdrawDraft] = useState({ amount: '', payeeName: '', bankAccount: '', bankName: '' })
  const today = useMemo(() => startOfToday(), [])
  const scheduleDays = useMemo(() => Array.from({ length: 7 }, (_, index) => addDays(today, index)), [today])
  const slotsByKey = useMemo(() => new Map(slots.map((slot) => [localSlotKey(slot.startsAt), slot])), [slots])

  useDidShow(() => {
    void reload()
  })

  async function reload() {
    const user = ensureLoggedIn('/pages/account/expert-home/index')
    const token = getToken()
    if (!user || !token) return
    setLoading(true)
    try {
      const [nextApplication, nextProfile, nextBookings, nextWithdrawals, nextWallet] = await Promise.all([
        backend.accountExpertApplication(token),
        backend.accountExpertProfile(token),
        backend.accountExpertBookings(token),
        backend.accountExpertWithdrawals(token),
        backend.accountExpertWallet(token).catch(() => null)
      ])
      setApplication(nextApplication)
      setProfile(nextProfile)
      setBookings(nextBookings.items)
      setWithdrawals(nextWithdrawals.items)
      setWallet(nextWallet)
      if (nextProfile) {
        const nextSlots = await backend.accountExpertSlots(token, { from: today.toISOString(), to: addDays(today, 8).toISOString() }).catch(() => ({ items: [] }))
        setSlots(nextSlots.items)
      } else {
        setSlots([])
      }
    } catch (error) {
      toast(error instanceof Error ? error.message : '专家工作台加载失败')
    } finally {
      setLoading(false)
    }
  }

  const expertBookings = useMemo(() => {
    if (!profile) return []
    return bookings.filter((booking) => booking.expertId === profile.id)
  }, [bookings, profile])

  const activeBookings = expertBookings.filter((booking) => ['pending_payment', 'pending_expert', 'confirmed', 'pending_user_confirm', 'disputed'].includes(booking.status))
  const pendingBookings = expertBookings.filter((booking) => booking.status === 'pending_expert')

  function meetingDraft(booking: BackendExpertBooking): MeetingDraft {
    return meetingForms[booking.id] || {
      method: booking.meetingMethod || 'online',
      platform: booking.meetingPlatform || '',
      no: booking.meetingNo || '',
      url: booking.meetingUrl || '',
      password: booking.meetingPassword || '',
      note: booking.meetingNote || ''
    }
  }

  function rescheduleDraft(booking: BackendExpertBooking): RescheduleDraft {
    return rescheduleForms[booking.id] || {
      startsAt: localValue(booking.startsAt),
      endsAt: localValue(booking.endsAt),
      reason: ''
    }
  }

  function setMeetingField(booking: BackendExpertBooking, key: keyof MeetingDraft, value: string) {
    setMeetingForms((current) => ({ ...current, [booking.id]: { ...meetingDraft(booking), [key]: value } }))
  }

  function setRescheduleField(booking: BackendExpertBooking, key: keyof RescheduleDraft, value: string) {
    setRescheduleForms((current) => ({ ...current, [booking.id]: { ...rescheduleDraft(booking), [key]: value } }))
  }

  async function toggleAccepting() {
    const token = getToken()
    if (!token || !profile) return
    try {
      const updated = await backend.setAccountExpertAccepting(token, !profile.acceptingOrders)
      setProfile(updated)
      toast(updated.acceptingOrders ? '已恢复接单' : '已暂停接单')
    } catch (error) {
      toast(error instanceof Error ? error.message : '接单状态更新失败')
    }
  }

  async function updateBooking(booking: BackendExpertBooking, status: BackendExpertBooking['status'], payload: Record<string, unknown> = {}) {
    const token = getToken()
    if (!token) return
    try {
      const updated = await backend.updateAccountExpertBooking(token, booking.id, {
        status,
        statusReason: status === 'rejected' ? '专家暂无法接单' : '',
        ...payload
      })
      setBookings((items) => items.map((item) => item.id === updated.id ? updated : item))
      toast('预约状态已更新')
    } catch (error) {
      toast(error instanceof Error ? error.message : '预约状态更新失败')
    }
  }

  function meetingPayload(booking: BackendExpertBooking) {
    const draft = meetingDraft(booking)
    return {
      meetingMethod: draft.method,
      meetingPlatform: draft.platform,
      meetingNo: draft.no,
      meetingUrl: draft.url,
      meetingPassword: draft.password,
      meetingNote: draft.note
    }
  }

  async function requestReschedule(booking: BackendExpertBooking) {
    const token = getToken()
    if (!token) return
    const draft = rescheduleDraft(booking)
    const startsAt = isoFromInput(draft.startsAt)
    const endsAt = isoFromInput(draft.endsAt)
    if (!startsAt || !endsAt || new Date(startsAt).getTime() >= new Date(endsAt).getTime()) {
      toast('请填写有效的新会议时间')
      return
    }
    try {
      const updated = await backend.createExpertBookingReschedule(token, booking.id, { startsAt, endsAt, reason: draft.reason || '专家申请改期' })
      setBookings((items) => items.map((item) => item.id === updated.id ? updated : item))
      toast('改期申请已发送')
    } catch (error) {
      toast(error instanceof Error ? error.message : '改期申请失败')
    }
  }

  async function respondReschedule(booking: BackendExpertBooking, action: 'accepted' | 'rejected') {
    const token = getToken()
    if (!token || !booking.pendingChange) return
    try {
      const updated = await backend.respondExpertBookingReschedule(token, booking.id, booking.pendingChange.id, {
        action,
        note: action === 'accepted' ? '专家确认改期' : '专家拒绝改期'
      })
      setBookings((items) => items.map((item) => item.id === updated.id ? updated : item))
      toast(action === 'accepted' ? '已确认改期' : '已拒绝改期')
    } catch (error) {
      toast(error instanceof Error ? error.message : '改期处理失败')
    }
  }

  function copy(value?: string) {
    if (!value) {
      toast('资料链接暂不可用')
      return
    }
    void Taro.setClipboardData({ data: value })
    toast('资料链接已复制')
  }

  async function toggleSlotHour(day: Date, hour: number) {
    const token = getToken()
    if (!token) return
    const startsAt = slotDate(day, hour)
    const endsAt = slotDate(day, hour + 1)
    const current = slotsByKey.get(localSlotKey(startsAt))
    if (current?.status === 'booked') return
    try {
      const nextStatus = current?.status === 'open' ? 'closed' : 'open'
      const slot = await backend.saveAccountExpertSlot(token, { startsAt: startsAt.toISOString(), endsAt: endsAt.toISOString(), status: nextStatus })
      setSlots((items) => [slot, ...items.filter((item) => item.id !== slot.id)])
      toast(nextStatus === 'open' ? '已开放该时段' : '已关闭该时段')
    } catch (error) {
      toast(error instanceof Error ? error.message : '排期保存失败')
    }
  }

  async function submitWithdrawal() {
    const token = getToken()
    if (!token) return
    const amount = cents(withdrawDraft.amount)
    if (!amount || !withdrawDraft.payeeName || !withdrawDraft.bankAccount || !withdrawDraft.bankName) {
      toast('请完整填写提现金额和收款信息')
      return
    }
    try {
      const created = await backend.createExpertWithdrawal(token, {
        amount,
        payeeName: withdrawDraft.payeeName,
        bankAccount: withdrawDraft.bankAccount,
        bankName: withdrawDraft.bankName
      })
      setWithdrawals((items) => [created, ...items])
      setWithdrawOpen(false)
      setWithdrawDraft({ amount: '', payeeName: '', bankAccount: '', bankName: '' })
      toast('提现申请已提交')
    } catch (error) {
      toast(error instanceof Error ? error.message : '提现申请提交失败')
    }
  }

  if (loading && !profile && !application) {
    return (
      <Page title="专家工作台">
        <View className="flow-section"><Text className="row-sub">正在加载专家状态...</Text></View>
      </Page>
    )
  }

  if (!profile) {
    const rejected = application?.status === 'rejected'
    return (
      <Page title="专家工作台" subtle={`申请状态：${applicationLabel(application?.status)}`}>
        <View className="flow-success">
          <Text className="flow-success-mark">{application?.status === 'pending' ? '…' : rejected ? '!' : '>'}</Text>
          <Text className="flow-success-title">{application?.status === 'pending' ? '专家申请审核中' : rejected ? '申请未通过' : '还不是专家'}</Text>
          <Text className="flow-success-copy">{rejected ? `未通过原因：${application?.rejectReason || '请补充资料后重新提交。'}` : '提交专家申请并审核通过后，可以在这里管理排期、预约和提现。'}</Text>
        </View>
        <View className="bottom-bar">
          <View className="primary-btn" onClick={() => Taro.navigateTo({ url: '/pages/experts/join/index' })}>{rejected ? '修改后重新提交' : '申请成为专家'}</View>
        </View>
      </Page>
    )
  }

  return (
    <Page title="专家工作台" subtle={`${profile.name} · ${profile.organization || '专家服务'}`}>
      <View className="expert-home-hero">
        <View>
          <Text className="status-pill">{profile.acceptingOrders ? '接单中' : '已暂停'}</Text>
          <Text className="booking-detail-title">{profile.name}</Text>
          <Text className="booking-detail-sub">{profile.title} · {profile.organization}</Text>
        </View>
        <View className="ghost-btn compact" onClick={toggleAccepting}>{profile.acceptingOrders ? '暂停接单' : '恢复接单'}</View>
      </View>

      <View className="expert-stats">
        <View><Text className="stat-value">{pendingBookings.length}</Text><Text className="stat-label">待确认</Text></View>
        <View><Text className="stat-value">{activeBookings.length}</Text><Text className="stat-label">进行中</Text></View>
        <View><Text className="stat-value">¥{yuan(wallet?.availableAmount || 0)}</Text><Text className="stat-label">可提现</Text></View>
      </View>

      <View className="flow-section">
        <Text className="flow-section-title">待处理预约</Text>
        {activeBookings.length === 0 ? <EmptyState title="暂无待处理预约" text="用户支付或发起改期后，会在这里显示。" /> : activeBookings.map((booking) => (
          <View key={booking.id} className="expert-booking-block">
            <View className="booking-block-head">
              <View>
                <Text className="row-title">{booking.contactName || booking.user?.displayName || '平台用户'}</Text>
                <Text className="row-sub">{booking.bookingNo} · {formatDate(booking.startsAt)} · {statusLabel(booking.status)}</Text>
              </View>
              <Text className="status-pill muted">{statusLabel(booking.status)}</Text>
            </View>
            <View className="staff-text-block">
              <Text className="staff-text-label">咨询问题</Text>
              <Text className="staff-text-value">{booking.question || booking.background || '-'}</Text>
            </View>
            {(booking.materialFiles || []).length > 0 && (
              <View className="file-list">
                {(booking.materialFiles || []).map((file) => (
                  <View key={file.id} className="file-line" onClick={() => copy(file.url)}>
                    <Text>{file.fileName || file.id}</Text>
                    <Text className="arrow">复制</Text>
                  </View>
                ))}
              </View>
            )}

            {(booking.status === 'pending_expert' || booking.status === 'confirmed') && (
              <View className="meeting-form">
                <Input className="flow-input" value={meetingDraft(booking).platform} placeholder="会议平台，如腾讯会议" onInput={(event) => setMeetingField(booking, 'platform', String(event.detail.value))} />
                <Input className="flow-input" value={meetingDraft(booking).no} placeholder="会议号" onInput={(event) => setMeetingField(booking, 'no', String(event.detail.value))} />
                <Input className="flow-input" value={meetingDraft(booking).password} placeholder="会议密码" onInput={(event) => setMeetingField(booking, 'password', String(event.detail.value))} />
                <Input className="flow-input" value={meetingDraft(booking).url} placeholder="会议链接" onInput={(event) => setMeetingField(booking, 'url', String(event.detail.value))} />
                <Textarea className="flow-textarea small" value={meetingDraft(booking).note} placeholder="会议备注" onInput={(event) => setMeetingField(booking, 'note', String(event.detail.value))} />
              </View>
            )}

            {booking.pendingChange && (
              <View className="soft-warn inline-warn">
                <Text className="row-sub">改期：{formatDate(booking.pendingChange.requestedStartsAt)} 至 {formatDate(booking.pendingChange.requestedEndsAt)}</Text>
                <Text className="row-sub">{booking.pendingChange.reason || '未填写原因'}</Text>
                {booking.pendingChange.requesterType === 'user' ? (
                  <View className="inline-actions">
                    <View className="primary-btn compact" onClick={() => respondReschedule(booking, 'accepted')}>同意改期</View>
                    <View className="ghost-btn compact" onClick={() => respondReschedule(booking, 'rejected')}>拒绝</View>
                  </View>
                ) : <Text className="row-sub">等待用户确认</Text>}
              </View>
            )}

            {booking.status === 'confirmed' && !booking.pendingChange && (
              <View className="reschedule-form">
                <Text className="flow-label standalone">专家申请改期</Text>
                <View className="meta-grid compact">
                  <Picker mode="date" value={datePart(rescheduleDraft(booking).startsAt)} onChange={(event) => setRescheduleField(booking, 'startsAt', withDate(rescheduleDraft(booking).startsAt, String(event.detail.value)))}>
                    <View><Text className="meta-label">新开始日期</Text><Text className="meta-value">{datePart(rescheduleDraft(booking).startsAt)}</Text></View>
                  </Picker>
                  <Picker mode="time" value={timePart(rescheduleDraft(booking).startsAt)} onChange={(event) => setRescheduleField(booking, 'startsAt', withTime(rescheduleDraft(booking).startsAt, String(event.detail.value)))}>
                    <View><Text className="meta-label">新开始时间</Text><Text className="meta-value">{timePart(rescheduleDraft(booking).startsAt)}</Text></View>
                  </Picker>
                </View>
                <Input className="flow-input" value={rescheduleDraft(booking).reason} placeholder="改期原因" onInput={(event) => setRescheduleField(booking, 'reason', String(event.detail.value))} />
              </View>
            )}

            <View className="inline-actions">
              {booking.status === 'pending_expert' && <View className="primary-btn compact" onClick={() => updateBooking(booking, 'confirmed', meetingPayload(booking))}>确认预约</View>}
              {booking.status === 'pending_expert' && <View className="ghost-btn compact" onClick={() => updateBooking(booking, 'rejected')}>拒绝</View>}
              {booking.status === 'confirmed' && <View className="primary-btn compact" onClick={() => updateBooking(booking, 'pending_user_confirm', meetingPayload(booking))}>提交完成</View>}
              {booking.status === 'confirmed' && !booking.pendingChange && <View className="ghost-btn compact" onClick={() => requestReschedule(booking)}>提交改期</View>}
              {booking.status === 'confirmed' && <View className="ghost-btn compact" onClick={() => updateBooking(booking, 'confirmed', meetingPayload(booking))}>保存会议</View>}
            </View>
          </View>
        ))}
      </View>

      <View className="flow-section">
        <Text className="flow-section-title">未来 7 天排期</Text>
        <Text className="row-sub">点亮为开放预约，灰色为关闭，已预约时段不可修改。</Text>
        <ScrollView scrollX className="schedule-scroll">
          <View className="schedule-grid">
            {scheduleDays.map((day) => (
              <View key={day.toISOString()} className="schedule-day">
                <Text className="schedule-day-title">{day.getMonth() + 1}/{day.getDate()}</Text>
                {hours.map((hour) => {
                  const slot = slotsByKey.get(localSlotKey(slotDate(day, hour)))
                  const cls = slot?.status === 'booked' ? 'schedule-slot booked' : slot?.status === 'open' ? 'schedule-slot open' : 'schedule-slot'
                  return <Text key={`${day.toISOString()}-${hour}`} className={cls} onClick={() => toggleSlotHour(day, hour)}>{hour}:00</Text>
                })}
              </View>
            ))}
          </View>
        </ScrollView>
      </View>

      <View className="flow-section">
        <Text className="flow-section-title">钱包提现</Text>
        <MetaRow label="可提现金额" value={`¥${yuan(wallet?.availableAmount || 0).toLocaleString()}`} />
        <MetaRow label="锁定金额" value={`¥${yuan(wallet?.lockedAmount || 0).toLocaleString()}`} />
        <MetaRow label="已提现" value={`¥${yuan(wallet?.withdrawnAmount || 0).toLocaleString()}`} />
        <View className="primary-btn" onClick={() => setWithdrawOpen(true)}>申请提现</View>
        {withdrawals.slice(0, 3).map((item) => (
          <View key={item.id} className="file-line">
            <Text>{item.withdrawalNo || item.id}</Text>
            <Text className="arrow">¥{yuan(item.amount).toLocaleString()} · {item.status === 'completed' ? '已打款' : item.status === 'rejected' ? '已驳回' : '待处理'}</Text>
          </View>
        ))}
      </View>

      {withdrawOpen && (
        <BottomDrawer title="申请提现" onClose={() => setWithdrawOpen(false)} className="withdraw-drawer">
          <View className="flow-section drawer-inner">
            <Input className="flow-input" type="digit" value={withdrawDraft.amount} placeholder="提现金额（元）" onInput={(event) => setWithdrawDraft((current) => ({ ...current, amount: String(event.detail.value) }))} />
            <Input className="flow-input" value={withdrawDraft.payeeName} placeholder="收款人姓名" onInput={(event) => setWithdrawDraft((current) => ({ ...current, payeeName: String(event.detail.value) }))} />
            <Input className="flow-input" value={withdrawDraft.bankAccount} placeholder="银行卡号/收款账号" onInput={(event) => setWithdrawDraft((current) => ({ ...current, bankAccount: String(event.detail.value) }))} />
            <Input className="flow-input" value={withdrawDraft.bankName} placeholder="开户行/收款渠道" onInput={(event) => setWithdrawDraft((current) => ({ ...current, bankName: String(event.detail.value) }))} />
            <View className="primary-btn" onClick={submitWithdrawal}>提交提现申请</View>
          </View>
        </BottomDrawer>
      )}
    </Page>
  )
}
