import { useState, useRef, useEffect } from 'react'
import { X, Clock, CalendarDays, User, Phone, AlertCircle, Banknote, CreditCard, Building2, Link2 } from 'lucide-react'
import { cn } from '../../lib/utils'
import { api } from '../../lib/api'
import type { RentalObject, RentalBooking } from '../../data/rentalData'
import type { Booking, Room } from '../../types'

interface RentalBookingModalProps {
  obj: RentalObject
  date: string
  existingBookings: RentalBooking[]
  editBooking?: RentalBooking
  bookings?: Booking[]    // all room bookings (for guest search + link)
  rooms?: Room[]          // room list (for displaying room numbers)
  slug?: string
  onClose: () => void
  onSave: (b: RentalBooking) => void
}

function hourOptions(from: number, to: number): number[] {
  return Array.from({ length: to - from + 1 }, (_, i) => from + i)
}

function formatHour(h: number): string {
  return `${h}:00`
}

export function RentalBookingModal({
  obj, date, existingBookings, editBooking, bookings = [], rooms = [], slug, onClose, onSave,
}: RentalBookingModalProps) {
  const isEdit = !!editBooking
  const [isFullDay, setIsFullDay] = useState(editBooking?.isFullDay ?? false)
  const [startHour, setStartHour] = useState(editBooking?.startHour ?? obj.openHour)
  const [endHour, setEndHour] = useState(editBooking?.endHour ?? Math.min(obj.openHour + 2, obj.closeHour))
  const [guestName, setGuestName] = useState(editBooking?.guestName ?? '')
  const [guestPhone, setGuestPhone] = useState(editBooking?.guestPhone ?? '')
  const [notes, setNotes] = useState(editBooking?.notes ?? '')
  const [paidAmount, setPaidAmount] = useState<string>(editBooking?.paidAmount ? String(editBooking.paidAmount) : '')
  const [payMethod, setPayMethod] = useState<'cash' | 'card' | 'transfer'>('cash')
  const [linkedBookingId, setLinkedBookingId] = useState<string>(editBooking?.linkedRoomId ?? '')
  // true = selected from dropdown (existing guest), false = typed manually (new guest)
  const [guestIsKnown, setGuestIsKnown] = useState(isEdit)

  // Guest search
  const [showSuggestions, setShowSuggestions] = useState(false)
  const nameRef = useRef<HTMLDivElement>(null)

  // DB guest search
  const [dbResults, setDbResults] = useState<{ id: string; firstName: string; lastName: string; phone: string | null }[]>([])
  const searchTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const [saving, setSaving] = useState(false)

  // Bookings with guest info — checked_in first, then confirmed
  const checkedIn = bookings.filter(b => b.status === 'checked_in')
  const confirmed  = bookings.filter(b => b.status === 'confirmed')
  const guestSuggestions = [...checkedIn, ...confirmed]

  const filtered = guestName.trim().length > 0
    ? guestSuggestions.filter(b =>
        b.guestName.toLowerCase().includes(guestName.toLowerCase()),
      )
    : guestSuggestions

  // Room label helper
  const roomLabel = (b: Booking) => {
    const r = rooms.find(r => r.id === b.roomId)
    return r ? `№${r.number}` : ''
  }

  // Close suggestions on outside click
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (nameRef.current && !nameRef.current.contains(e.target as Node)) {
        setShowSuggestions(false)
      }
    }
    document.addEventListener('mousedown', handler)
    return () => document.removeEventListener('mousedown', handler)
  }, [])

  const selectGuest = (b: Booking) => {
    setGuestName(b.guestName)
    setGuestPhone(b.guestPhone ?? '')
    setLinkedBookingId(b.id)
    setShowSuggestions(false)
    setGuestIsKnown(true)
  }

  const otherBookings = existingBookings.filter(b => b.id !== editBooking?.id && b.status !== 'cancelled')
  const timedBookings  = otherBookings.filter(b => !b.isFullDay)
  const hasFullDayConflict = otherBookings.some(b => b.isFullDay)
  // If any timed slot is booked, "весь день" is unavailable
  const hasTimedConflict   = timedBookings.length > 0

  // Break between sessions (ceil to whole hours)
  const breakHours = Math.ceil((obj.bufferMinutes ?? 0) / 60)

  // Available start hours: exclude hours inside any booked slot + its buffer
  const availableStartHours = hourOptions(obj.openHour, obj.closeHour - 1).filter(h =>
    !timedBookings.some(b => h >= b.startHour && h < b.endHour + breakHours),
  )

  // Max end hour for a given start: limited by the next booking that starts after `start`
  const getMaxEndHour = (start: number) => {
    const next = timedBookings
      .filter(b => b.startHour >= start + 1)
      .sort((a, b) => a.startHour - b.startHour)[0]
    return next ? next.startHour : obj.closeHour
  }

  const availableEndHours = hourOptions(startHour + 1, getMaxEndHour(startHour))

  // If current startHour is blocked, snap to first available
  const effectiveStartHour = availableStartHours.includes(startHour)
    ? startHour
    : (availableStartHours[0] ?? obj.openHour)

  const hours = isFullDay
    ? obj.closeHour - obj.openHour
    : Math.max(0, endHour - effectiveStartHour)

  const totalAmount = isFullDay ? obj.pricePerDay : hours * obj.pricePerHour
  const maxHoursOk = !obj.maxHoursPerSlot || hours <= obj.maxHoursPerSlot

  const isTimeConflict = !isFullDay && timedBookings.some(b =>
    b.startHour < endHour && b.endHour > effectiveStartHour,
  )

  const noSlots = !hasFullDayConflict && availableStartHours.length === 0

  // For new (unknown) guests, phone is required
  const phoneRequired = !guestIsKnown
  const canSave = guestName.trim() !== '' &&
    (!phoneRequired || guestPhone.trim() !== '') &&
    hours > 0 && maxHoursOk && !isTimeConflict && !hasFullDayConflict && !noSlots &&
    (!isFullDay || (!hasFullDayConflict && !hasTimedConflict))

  const handleSave = async () => {
    if (!canSave || saving) return
    setSaving(true)
    try {
      // If guest is new (typed manually), create them in the guests DB
      if (!guestIsKnown && slug) {
        const nameParts = guestName.trim().split(' ')
        await api.guests.create(slug, {
          last_name:   nameParts[0] ?? '',
          first_name:  nameParts[1] ?? '',
          middle_name: nameParts.slice(2).join(' ') || undefined,
          phone:       guestPhone.trim() || undefined,
        })
      }
      const linked = bookings.find(b => b.id === linkedBookingId)
      onSave({
        id: editBooking?.id ?? `rb-${Date.now()}`,
        objectId: obj.id,
        date,
        isFullDay,
        startHour: isFullDay ? obj.openHour : startHour,
        endHour:   isFullDay ? obj.closeHour : endHour,
        guestName: guestName.trim(),
        guestPhone: guestPhone.trim(),
        linkedRoomId: (linked?.roomId ?? linkedBookingId) || undefined,
        notes: notes.trim() || undefined,
        totalAmount,
        paidAmount: parseFloat(paidAmount) || 0,
        status: 'confirmed',
      })
    } finally {
      setSaving(false)
    }
  }

  const displayDate = new Intl.DateTimeFormat('ru-RU', {
    day: 'numeric', month: 'long', weekday: 'short',
  }).format(new Date(date))

  // For link dropdown — show checked-in first, label includes room number
  const linkableBookings = [...checkedIn, ...confirmed.filter(b => !checkedIn.includes(b))]

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50">
      <div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl w-full max-w-md flex flex-col max-h-[90vh]">
        {/* Header */}
        <div className="flex items-center gap-3 px-5 py-4 border-b border-slate-200 dark:border-slate-700 shrink-0">
          <span className="text-2xl">{obj.icon}</span>
          <div className="flex-1 min-w-0">
            <p className="font-semibold text-slate-900 dark:text-slate-100">{obj.name}</p>
            <p className="text-xs text-slate-500 dark:text-slate-400 capitalize">{displayDate}</p>
          </div>
          <button onClick={onClose} className="btn-ghost p-1.5"><X size={16} /></button>
        </div>

        <div className="overflow-y-auto flex-1 p-5 space-y-4">
          {/* Existing bookings for the day */}
          {existingBookings.filter(b => b.status !== 'cancelled').length > 0 && (
            <div className="rounded-xl bg-slate-50 dark:bg-slate-700/50 p-3 space-y-1.5">
              <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">Уже забронировано</p>
              {existingBookings.filter(b => b.status !== 'cancelled').map(b => (
                <div key={b.id} className="flex items-center gap-2 text-sm">
                  <div className={cn('w-2 h-2 rounded-full shrink-0', obj.color)} />
                  <span className="text-slate-700 dark:text-slate-300 font-medium">
                    {b.isFullDay ? 'Весь день' : `${b.startHour}:00 – ${b.endHour}:00`}
                  </span>
                  <span className="text-slate-500 dark:text-slate-400 truncate">{b.guestName}</span>
                </div>
              ))}
            </div>
          )}

          {hasFullDayConflict && (
            <div className="flex items-center gap-2 p-3 rounded-xl bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 text-sm">
              <AlertCircle size={15} className="shrink-0" />
              <span>Объект уже забронирован на весь день</span>
            </div>
          )}

          {/* Full day toggle */}
          <div className={cn(
            'flex items-center gap-3 p-3 rounded-xl border',
            (hasTimedConflict || hasFullDayConflict)
              ? 'border-slate-200 dark:border-slate-600 opacity-50 pointer-events-none'
              : 'border-slate-200 dark:border-slate-600',
          )}>
            <CalendarDays size={16} className="text-slate-400 shrink-0" />
            <span className="text-sm font-medium text-slate-700 dark:text-slate-300 flex-1">Весь день</span>
            {hasTimedConflict && (
              <span className="text-xs text-slate-400">Есть частичные брони</span>
            )}
            <button
              onClick={() => (!hasTimedConflict && !hasFullDayConflict) && setIsFullDay(v => !v)}
              className={cn(
                'relative rounded-full transition-colors shrink-0',
                isFullDay ? 'bg-brand-600' : 'bg-slate-200 dark:bg-slate-600',
              )}
              style={{ height: 22, width: 40 }}
            >
              <span className={cn(
                'absolute top-0.5 w-4 h-4 rounded-full bg-white shadow transition-transform',
                isFullDay ? 'translate-x-5' : 'translate-x-0.5',
              )} />
            </button>
          </div>

          {/* Time selection */}
          {!isFullDay && !hasFullDayConflict && (
            <div>
              <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">
                Время аренды ({obj.openHour}:00 – {obj.closeHour}:00)
                {breakHours > 0 && <span className="ml-1 font-normal normal-case">(перерыв {obj.bufferMinutes} мин)</span>}
              </label>
              {noSlots ? (
                <div className="flex items-center gap-2 p-3 rounded-xl bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 text-sm">
                  <AlertCircle size={15} className="shrink-0" />
                  <span>Все слоты на этот день заняты</span>
                </div>
              ) : (
                <>
                  <div className="flex items-center gap-3">
                    <div className="flex-1">
                      <label className="block text-xs text-slate-500 mb-1">Начало</label>
                      <select
                        className="input text-sm"
                        value={effectiveStartHour}
                        onChange={e => {
                          const v = parseInt(e.target.value)
                          setStartHour(v)
                          const maxEnd = getMaxEndHour(v)
                          if (endHour <= v || endHour > maxEnd) setEndHour(Math.min(v + 1, maxEnd))
                        }}
                      >
                        {availableStartHours.map(h => (
                          <option key={h} value={h}>{formatHour(h)}</option>
                        ))}
                      </select>
                    </div>
                    <Clock size={14} className="text-slate-400 mt-4 shrink-0" />
                    <div className="flex-1">
                      <label className="block text-xs text-slate-500 mb-1">Конец</label>
                      <select
                        className="input text-sm"
                        value={availableEndHours.includes(endHour) ? endHour : (availableEndHours[0] ?? endHour)}
                        onChange={e => setEndHour(parseInt(e.target.value))}
                      >
                        {availableEndHours.map(h => (
                          <option key={h} value={h}>{formatHour(h)}</option>
                        ))}
                      </select>
                    </div>
                  </div>
                  {obj.maxHoursPerSlot && !maxHoursOk && (
                    <p className="mt-1.5 text-xs text-red-500">Максимум: {obj.maxHoursPerSlot} ч</p>
                  )}
                  {isTimeConflict && (
                    <p className="mt-1.5 text-xs text-red-500">Время пересекается с существующей бронью</p>
                  )}
                </>
              )}
            </div>
          )}

          {/* Guest search */}
          <div className="space-y-3">
            <div>
              <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">
                Гость *
              </label>
              <div className="relative" ref={nameRef}>
                <User size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 z-10" />
                <input
                  type="text"
                  className="input pl-8 text-sm"
                  placeholder="Имя гостя"
                  value={guestName}
                  onChange={e => {
                    const val = e.target.value
                    setGuestName(val)
                    setGuestIsKnown(false)   // manual typing = new guest
                    setShowSuggestions(true)
                    if (searchTimerRef.current) clearTimeout(searchTimerRef.current)
                    if (val.trim().length >= 2 && slug) {
                      searchTimerRef.current = setTimeout(async () => {
                        try {
                          const results = await api.guests.list(slug, val.trim())
                          setDbResults(results.slice(0, 8))
                        } catch { setDbResults([]) }
                      }, 300)
                    } else {
                      setDbResults([])
                    }
                  }}
                  onFocus={() => setShowSuggestions(true)}
                  autoComplete="off"
                />
                {/* Suggestions dropdown */}
                {showSuggestions && (filtered.length > 0 || dbResults.length > 0) && (
                  <div className="absolute top-full left-0 right-0 mt-1 z-50 bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-600 shadow-xl overflow-hidden max-h-60 overflow-y-auto">
                    {/* Current/upcoming guests from bookings */}
                    {filtered.slice(0, 5).map(b => {
                      const rLabel = roomLabel(b)
                      const isCheckedIn = b.status === 'checked_in'
                      return (
                        <button
                          key={b.id}
                          type="button"
                          onMouseDown={() => selectGuest(b)}
                          className="w-full flex items-center gap-2.5 px-3 py-2.5 hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors text-left"
                        >
                          <div className={cn('w-2 h-2 rounded-full shrink-0', isCheckedIn ? 'bg-emerald-500' : 'bg-sky-400')} />
                          <div className="min-w-0 flex-1">
                            <p className="text-sm font-medium text-slate-800 dark:text-slate-200 truncate">{b.guestName}</p>
                            <p className="text-[11px] text-slate-400 truncate">
                              {b.guestPhone
                                ? b.guestPhone
                                : isCheckedIn ? '🏠 Проживает' : '📅 Бронь'
                              }{rLabel ? ` · ${rLabel}` : ''}
                            </p>
                          </div>
                        </button>
                      )
                    })}
                    {/* DB guest search results */}
                    {dbResults
                      .filter(g => !filtered.some(b => b.guestName === `${g.lastName} ${g.firstName}`))
                      .map(g => (
                        <button
                          key={g.id}
                          type="button"
                          onMouseDown={() => {
                            setGuestName(`${g.lastName} ${g.firstName}`)
                            setGuestPhone(g.phone ?? '')
                            setShowSuggestions(false)
                            setDbResults([])
                            setGuestIsKnown(true)
                          }}
                          className="w-full flex items-center gap-2.5 px-3 py-2.5 hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors text-left"
                        >
                          <div className="w-2 h-2 rounded-full shrink-0 bg-slate-400" />
                          <div className="min-w-0 flex-1">
                            <p className="text-sm font-medium text-slate-800 dark:text-slate-200 truncate">{g.lastName} {g.firstName}</p>
                            <p className="text-[11px] text-slate-400 truncate">
                              {g.phone ?? 'нет телефона'}
                            </p>
                          </div>
                        </button>
                      ))
                    }
                  </div>
                )}
              </div>
            </div>

            <div>
              <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">
                Телефон {phoneRequired && <span className="text-red-500">*</span>}
              </label>
              <div className="relative">
                <Phone size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" />
                <input
                  type="tel"
                  className={cn('input pl-8 text-sm', phoneRequired && !guestPhone.trim() && 'border-red-400 focus:ring-red-400')}
                  placeholder={phoneRequired ? '+7 999 000 11 22 (обязательно)' : '+7 999 000 11 22'}
                  value={guestPhone}
                  onChange={e => setGuestPhone(e.target.value)}
                />
              </div>
              {phoneRequired && !guestPhone.trim() && (
                <p className="mt-1 text-[11px] text-red-500">Для нового гостя необходим телефон — он будет добавлен в базу</p>
              )}
            </div>

            {/* Link to room */}
            <div>
              <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5 flex items-center gap-1">
                <Link2 size={11} /> Привязать к номеру
              </label>
              <select
                className="input text-sm"
                value={linkedBookingId}
                onChange={e => {
                  const id = e.target.value
                  setLinkedBookingId(id)
                  if (id) {
                    const b = bookings.find(b => b.id === id)
                    if (b && !guestName) {
                      setGuestName(b.guestName)
                      setGuestPhone(b.guestPhone ?? '')
                    }
                  }
                }}
              >
                <option value="">— Без привязки —</option>
                {linkableBookings.map(b => {
                  const r = rooms.find(r => r.id === b.roomId)
                  const isCI = b.status === 'checked_in'
                  return (
                    <option key={b.id} value={b.id}>
                      {isCI ? '🏠' : '📅'} №{r?.number ?? '?'} — {b.guestName}
                      {isCI ? ' (проживает)' : ''}
                    </option>
                  )
                })}
              </select>
            </div>

            <div>
              <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide mb-1.5">
                Примечание
              </label>
              <textarea
                className="input resize-none text-sm"
                rows={2}
                placeholder="Дополнительно..."
                value={notes}
                onChange={e => setNotes(e.target.value)}
              />
            </div>
          </div>

          {/* Price summary */}
          <div className="rounded-xl bg-slate-50 dark:bg-slate-700/50 px-4 py-3 flex items-center justify-between">
            <span className="text-sm text-slate-600 dark:text-slate-300">
              {isFullDay
                ? `Весь день (${obj.openHour}:00 – ${obj.closeHour}:00)`
                : `${hours} ч × ${obj.pricePerHour.toLocaleString('ru-RU')} ₽`}
            </span>
            <span className="text-lg font-bold text-slate-900 dark:text-slate-100">
              {totalAmount.toLocaleString('ru-RU')} ₽
            </span>
          </div>

          {/* Payment */}
          <div className="space-y-2">
            <label className="block text-xs font-semibold text-slate-500 uppercase tracking-wide">
              Оплата при бронировании
            </label>
            <div className="grid grid-cols-3 gap-1.5">
              {([
                { id: 'cash' as const,     label: 'Наличные', icon: Banknote },
                { id: 'card' as const,     label: 'Карта',    icon: CreditCard },
                { id: 'transfer' as const, label: 'Перевод',  icon: Building2 },
              ]).map(m => (
                <button
                  key={m.id} type="button" onClick={() => setPayMethod(m.id)}
                  className={cn(
                    'flex flex-col items-center gap-1 py-2 rounded-lg border text-xs font-medium transition-colors',
                    payMethod === m.id
                      ? 'bg-brand-600 border-brand-600 text-white'
                      : 'bg-white dark:bg-slate-700 border-slate-200 dark:border-slate-600 text-slate-600 dark:text-slate-300',
                  )}
                >
                  <m.icon size={14} /> {m.label}
                </button>
              ))}
            </div>
            <input
              type="number"
              className="input text-sm"
              placeholder={`Сумма (макс. ${totalAmount.toLocaleString('ru-RU')} ₽)`}
              value={paidAmount}
              onChange={e => setPaidAmount(e.target.value)}
              min="0"
              max={totalAmount}
            />
            {paidAmount && parseFloat(paidAmount) > 0 && parseFloat(paidAmount) < totalAmount && (
              <p className="text-xs text-amber-600 dark:text-amber-400">
                Остаток: {(totalAmount - parseFloat(paidAmount)).toLocaleString('ru-RU')} ₽
              </p>
            )}
          </div>
        </div>

        {/* Footer */}
        <div className="flex items-center justify-end gap-2 px-5 py-4 border-t border-slate-200 dark:border-slate-700 shrink-0">
          <button onClick={onClose} className="btn-secondary">Отмена</button>
          <button
            onClick={() => { void handleSave() }}
            disabled={!canSave || saving}
            className="btn-primary disabled:opacity-50 disabled:cursor-not-allowed"
          >
            {saving ? 'Сохранение...' : isEdit ? 'Сохранить' : 'Забронировать'}
          </button>
        </div>
      </div>
    </div>
  )
}
