import { useState, useRef, useCallback, useEffect } from 'react'
import { addDays, format, startOfDay, differenceInDays, parseISO, isToday } from 'date-fns'
import { ru } from 'date-fns/locale'
import { ChevronLeft, ChevronRight, Plus, CalendarDays, ChevronDown } from 'lucide-react'
import { cn, BOOKING_STATUS_COLORS, BOOKING_STATUS_LABELS, SOURCE_LABELS } from '../../lib/utils'
import type { Room, Booking, DraftBooking } from '../../types'
import type { RentalObject, RentalBooking } from '../../data/rentalData'
import { BookingModal } from '../bookings/BookingModal'
import { BookingDetailPanel } from '../bookings/BookingDetailPanel'
import { RentalBookingModal } from '../rental/RentalBookingModal'

const CELL_WIDTH = 52
const ROW_HEIGHT = 56
const LABEL_WIDTH = 160
const DAYS_VISIBLE = 30

interface BookingCalendarProps {
  rooms: Room[]
  bookings: Booking[]
  onBookingCreate: (b: Partial<Booking>) => void
  onBookingUpdate: (id: string, b: Partial<Booking>) => void
  fadingBookingIds?: Set<string>
  rentalObjects?: RentalObject[]
  rentalBookings?: RentalBooking[]
  onRentalBookingCreate?: (b: RentalBooking) => void
}

function getRoomTypeColor(type: string): string {
  const map: Record<string, string> = {
    'Стандарт':     'bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300',
    'Делюкс':       'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300',
    'Полулюкс':     'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300',
    'Люкс':         'bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300',
    'Пентхаус':     'bg-rose-100 dark:bg-rose-900/30 text-rose-700 dark:text-rose-300',
    'Апартаменты':  'bg-teal-100 dark:bg-teal-900/30 text-teal-700 dark:text-teal-300',
  }
  return map[type] ?? 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-300'
}

export function BookingCalendar({ rooms, bookings, onBookingCreate, onBookingUpdate, fadingBookingIds, rentalObjects, rentalBookings, onRentalBookingCreate }: BookingCalendarProps) {
  const [startDate, setStartDate] = useState(() => startOfDay(new Date()))
  const [visibleDays, setVisibleDays] = useState(DAYS_VISIBLE)

  // Date picker state
  const [showNavPicker, setShowNavPicker] = useState(false)
  const [pickerDateInput, setPickerDateInput] = useState(format(new Date(), 'yyyy-MM-dd'))
  const navPickerRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!showNavPicker) return
    const handler = (e: MouseEvent) => {
      if (navPickerRef.current && !navPickerRef.current.contains(e.target as Node)) {
        setShowNavPicker(false)
      }
    }
    document.addEventListener('mousedown', handler)
    return () => document.removeEventListener('mousedown', handler)
  }, [showNavPicker])

  // Drag-to-book state
  const [draft, setDraft] = useState<DraftBooking | null>(null)
  const [dragStart, setDragStart] = useState<{ roomId: string; dayIdx: number } | null>(null)
  const [dragEnd, setDragEnd] = useState<number | null>(null)

  // Modals
  const [bookingModalDraft, setBookingModalDraft] = useState<DraftBooking | null>(null)
  const [selectedBooking, setSelectedBooking] = useState<Booking | null>(null)
  const [rentalModal, setRentalModal] = useState<{ obj: RentalObject; date: string } | null>(null)

  const gridRef = useRef<HTMLDivElement>(null)

  const dates = Array.from({ length: visibleDays }, (_, i) => addDays(startDate, i))

  const shiftDays = (n: number) => setStartDate(d => addDays(d, n))

  const getBlockStyle = (booking: Booking) => {
    const start = parseISO(booking.checkIn)
    const end = parseISO(booking.checkOut)

    const colStart = Math.max(0, differenceInDays(start, startDate))
    const colEnd = Math.min(visibleDays, differenceInDays(end, startDate))
    if (colStart >= visibleDays || colEnd <= 0) return null

    return {
      left: colStart * CELL_WIDTH,
      width: (colEnd - colStart) * CELL_WIDTH - 4,
    }
  }

  const handleCellMouseDown = useCallback((roomId: string, dayIdx: number, e: React.MouseEvent) => {
    if (e.button !== 0) return
    e.preventDefault()
    setDragStart({ roomId, dayIdx })
    setDragEnd(dayIdx)
  }, [])

  const handleCellMouseEnter = useCallback((dayIdx: number) => {
    if (!dragStart) return
    setDragEnd(dayIdx)
  }, [dragStart])

  const handleMouseUp = useCallback(() => {
    if (!dragStart || dragEnd === null) return
    const minDay = Math.min(dragStart.dayIdx, dragEnd)
    const maxDay = Math.max(dragStart.dayIdx, dragEnd)
    const checkIn = format(addDays(startDate, minDay), 'yyyy-MM-dd')
    const checkOut = format(addDays(startDate, maxDay + 1), 'yyyy-MM-dd')
    setBookingModalDraft({ roomId: dragStart.roomId, checkIn, checkOut })
    setDragStart(null)
    setDragEnd(null)
    setDraft(null)
  }, [dragStart, dragEnd, startDate])

  const getDraftStyle = (roomId: string) => {
    if (!dragStart || dragEnd === null || dragStart.roomId !== roomId) return null
    const minDay = Math.min(dragStart.dayIdx, dragEnd)
    const maxDay = Math.max(dragStart.dayIdx, dragEnd)
    return {
      left: minDay * CELL_WIDTH,
      width: (maxDay - minDay + 1) * CELL_WIDTH - 2,
    }
  }

  return (
    <div className="flex flex-col h-full" onMouseUp={handleMouseUp} onMouseLeave={handleMouseUp}>
      {/* Toolbar */}
      <div className="flex items-center gap-3 px-4 py-3 border-b border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 shrink-0 flex-wrap gap-y-2">
        <div className="flex items-center gap-1.5">
          <button onClick={() => shiftDays(-7)} className="btn-ghost p-2"><ChevronLeft size={16} /></button>

          {/* Date / period picker */}
          <div className="relative" ref={navPickerRef}>
            <button
              onClick={() => setShowNavPicker(v => !v)}
              className={cn(
                'btn-secondary flex items-center gap-1.5 px-2.5 py-1.5 text-xs',
                showNavPicker && 'bg-slate-200 dark:bg-slate-600',
              )}
            >
              <CalendarDays size={12} className={isToday(startDate) ? 'text-brand-600' : 'text-slate-400'} />
              <span className={cn('font-medium', isToday(startDate) ? 'text-brand-600' : '')}>
                {isToday(startDate) ? 'Сегодня' : format(startDate, 'd MMM', { locale: ru })}
              </span>
              <span className="text-slate-400">·</span>
              <span className="text-slate-400">{visibleDays}д</span>
              <ChevronDown size={11} className="text-slate-400" />
            </button>

            {showNavPicker && (
              <div className="absolute top-full left-0 mt-1 z-50 bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 shadow-xl p-4 w-64">
                <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">Начало периода</p>
                <div className="flex gap-2 mb-3">
                  <input
                    type="date"
                    value={pickerDateInput}
                    onChange={e => setPickerDateInput(e.target.value)}
                    className="input text-sm py-1.5 flex-1"
                  />
                  <button
                    onClick={() => {
                      const today = format(new Date(), 'yyyy-MM-dd')
                      setPickerDateInput(today)
                      setStartDate(startOfDay(new Date()))
                    }}
                    className="btn-secondary text-xs px-2.5 shrink-0"
                  >
                    Сег.
                  </button>
                </div>

                <p className="text-xs font-semibold text-slate-500 uppercase tracking-wide mb-2">Дней в окне</p>
                <div className="flex gap-1.5 flex-wrap mb-4">
                  {[14, 21, 30, 45, 60].map(d => (
                    <button
                      key={d}
                      onClick={() => setVisibleDays(d)}
                      className={cn(
                        'px-2.5 py-1 rounded-lg text-xs font-medium border transition-colors',
                        visibleDays === d
                          ? '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 hover:border-brand-400',
                      )}
                    >
                      {d}д
                    </button>
                  ))}
                </div>

                <button
                  onClick={() => {
                    const parsed = new Date(pickerDateInput)
                    if (!isNaN(parsed.getTime())) setStartDate(startOfDay(parsed))
                    setShowNavPicker(false)
                  }}
                  className="btn-primary w-full justify-center text-sm py-1.5"
                >
                  Показать
                </button>
              </div>
            )}
          </div>

          <button onClick={() => shiftDays(7)} className="btn-ghost p-2"><ChevronRight size={16} /></button>
        </div>

        <span className="text-sm font-medium text-slate-700 dark:text-slate-300 capitalize">
          {format(startDate, 'LLLL yyyy', { locale: ru })}
        </span>

        <div className="flex-1" />

        {/* Legend */}
        <div className="hidden lg:flex items-center gap-3 text-xs text-slate-500">
          {(['confirmed', 'checked_in', 'checked_out', 'inquiry', 'cancelled'] as const).map(s => (
            <div key={s} className="flex items-center gap-1.5">
              <div className={cn('w-3 h-3 rounded-sm', BOOKING_STATUS_COLORS[s].split(' ')[0])} />
              <span>{BOOKING_STATUS_LABELS[s]}</span>
            </div>
          ))}
        </div>

        <button
          onClick={() => {
            const today = format(new Date(), 'yyyy-MM-dd')
            const tomorrow = format(addDays(new Date(), 1), 'yyyy-MM-dd')
            setBookingModalDraft({ roomId: rooms[0]?.id ?? '', checkIn: today, checkOut: tomorrow })
          }}
          className="btn-primary"
        >
          <Plus size={15} />
          <span className="hidden sm:inline">Новое бронирование</span>
        </button>
      </div>

      {/* Grid */}
      <div className="flex-1 overflow-auto" ref={gridRef}>
        <div style={{ minWidth: LABEL_WIDTH + visibleDays * CELL_WIDTH }}>

          {/* Date header row */}
          <div
            className="flex sticky top-0 z-20 bg-white dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700 shadow-sm"
            style={{ height: 48 }}
          >
            <div
              className="shrink-0 sticky left-0 z-30 bg-white dark:bg-slate-800 border-r border-slate-200 dark:border-slate-700 flex items-center px-3"
              style={{ width: LABEL_WIDTH }}
            >
              <span className="text-xs font-semibold text-slate-500 uppercase tracking-wide">Номер</span>
            </div>
            {dates.map((date, i) => {
              const isWe = date.getDay() === 0 || date.getDay() === 6
              const isTod = isToday(date)
              return (
                <div
                  key={i}
                  className={cn(
                    'shrink-0 flex flex-col items-center justify-center border-r border-slate-200 dark:border-slate-700 select-none',
                    isWe && 'bg-slate-50 dark:bg-slate-800/60',
                    isTod && 'bg-brand-50 dark:bg-brand-900/20',
                  )}
                  style={{ width: CELL_WIDTH }}
                >
                  <span className={cn(
                    'text-xs font-medium',
                    isTod ? 'text-brand-600 dark:text-brand-400' : isWe ? 'text-slate-400' : 'text-slate-500 dark:text-slate-400',
                  )}>
                    {format(date, 'EEE', { locale: ru }).slice(0, 2)}
                  </span>
                  <span className={cn(
                    'text-sm font-bold',
                    isTod ? 'text-brand-600 dark:text-brand-400' : 'text-slate-700 dark:text-slate-200',
                  )}>
                    {format(date, 'd')}
                  </span>
                </div>
              )
            })}
          </div>

          {/* Room rows */}
          {rooms.map(room => {
            const roomBookings = bookings.filter(b => b.roomId === room.id)
            const draftStyle = getDraftStyle(room.id)

            return (
              <div
                key={room.id}
                className="flex border-b border-slate-200 dark:border-slate-700 group hover:bg-slate-50/50 dark:hover:bg-slate-800/30"
                style={{ height: ROW_HEIGHT }}
              >
                {/* Room label */}
                <div
                  className="shrink-0 sticky left-0 z-10 bg-white dark:bg-slate-800 border-r border-slate-200 dark:border-slate-700 flex items-center gap-2 px-3 group-hover:bg-slate-50 dark:group-hover:bg-slate-750"
                  style={{ width: LABEL_WIDTH }}
                >
                  <div>
                    <div className="flex items-center gap-1.5">
                      <span className="text-sm font-bold text-slate-900 dark:text-slate-100">{room.number}</span>
                      {room.name && <span className="text-xs text-slate-500 dark:text-slate-400">{room.name}</span>}
                    </div>
                    <span className={cn('text-xs px-1.5 py-0.5 rounded-md font-medium', getRoomTypeColor(room.type))}>
                      {room.type}
                    </span>
                  </div>
                  <div className="ml-auto text-xs text-slate-400 dark:text-slate-500">
                    {room.baseRate.toLocaleString('ru-RU')} ₽
                  </div>
                </div>

                {/* Day cells + booking blocks */}
                <div className="relative flex-1">
                  <div className="flex h-full">
                    {dates.map((date, i) => {
                      const isWe = date.getDay() === 0 || date.getDay() === 6
                      const isTod = isToday(date)
                      return (
                        <div
                          key={i}
                          className={cn(
                            'shrink-0 h-full border-r border-slate-200 dark:border-slate-700 cursor-crosshair',
                            isWe && 'bg-slate-50 dark:bg-slate-800/60',
                            isTod && 'bg-brand-50/50 dark:bg-brand-900/10',
                          )}
                          style={{ width: CELL_WIDTH }}
                          onMouseDown={(e) => handleCellMouseDown(room.id, i, e)}
                          onMouseEnter={() => handleCellMouseEnter(i)}
                        />
                      )
                    })}
                  </div>

                  {/* Booking blocks */}
                  {roomBookings.map(booking => {
                    const style = getBlockStyle(booking)
                    if (!style) return null
                    const nights = differenceInDays(parseISO(booking.checkOut), parseISO(booking.checkIn))
                    const isFading = fadingBookingIds?.has(booking.id)
                    return (
                      <div
                        key={booking.id}
                        className={cn(
                          'booking-block border-l-4 transition-all duration-700',
                          BOOKING_STATUS_COLORS[booking.status],
                          isFading && 'opacity-0 scale-y-0',
                        )}
                        style={{
                          left: style.left + 2,
                          width: style.width,
                          top: 4,
                          bottom: 4,
                          position: 'absolute',
                        }}
                        onClick={(e) => { e.stopPropagation(); setSelectedBooking(booking) }}
                        title={`${booking.guestName} • ${booking.checkIn} – ${booking.checkOut}`}
                      >
                        <span className="truncate text-xs font-semibold opacity-95 drop-shadow-sm">
                          {booking.guestName}
                        </span>
                        {style.width > 80 && (
                          <span className="ml-2 opacity-75 text-[10px] shrink-0">
                            {nights}н • {SOURCE_LABELS[booking.source]}
                          </span>
                        )}
                      </div>
                    )
                  })}

                  {/* Draft overlay */}
                  {draftStyle && (
                    <div
                      className="absolute top-2 bottom-2 bg-brand-400/40 border-2 border-brand-500 border-dashed rounded-md pointer-events-none"
                      style={{ left: draftStyle.left + 2, width: draftStyle.width }}
                    />
                  )}
                </div>
              </div>
            )
          })}

          {/* ── Rental section ── */}
          {rentalObjects && rentalObjects.length > 0 && (
            <>
              {/* Separator */}
              <div className="flex sticky left-0 bg-slate-100 dark:bg-slate-700/60 border-b border-t border-slate-200 dark:border-slate-600"
                   style={{ height: 32 }}>
                <div
                  className="shrink-0 sticky left-0 z-10 bg-slate-100 dark:bg-slate-700/60 border-r border-slate-200 dark:border-slate-600 flex items-center px-4"
                  style={{ width: LABEL_WIDTH }}
                >
                  <span className="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">
                    Аренда объектов
                  </span>
                </div>
                {dates.map((_, i) => (
                  <div key={i} className="shrink-0 border-r border-slate-200 dark:border-slate-600"
                       style={{ width: CELL_WIDTH }} />
                ))}
              </div>

              {/* Rental object rows */}
              {rentalObjects.map(obj => {
                const totalSpan = obj.closeHour - obj.openHour
                return (
                  <div key={obj.id}
                       className="flex border-b border-slate-200 dark:border-slate-700"
                       style={{ height: ROW_HEIGHT }}>
                    {/* Label */}
                    <div
                      className="shrink-0 sticky left-0 z-10 bg-white dark:bg-slate-800 border-r border-slate-200 dark:border-slate-700 flex items-center gap-2 px-3"
                      style={{ width: LABEL_WIDTH }}
                    >
                      <span className="text-lg">{obj.icon}</span>
                      <div className="min-w-0">
                        <p className="text-sm font-medium text-slate-800 dark:text-slate-200 truncate">{obj.name}</p>
                        <p className="text-xs text-slate-400">
                          {obj.pricePerHour.toLocaleString('ru-RU')} ₽/ч · {obj.pricePerDay.toLocaleString('ru-RU')} ₽/день
                        </p>
                      </div>
                    </div>

                    {/* Day cells */}
                    {dates.map((date, i) => {
                      const dateStr = format(date, 'yyyy-MM-dd')
                      const isWe = date.getDay() === 0 || date.getDay() === 6
                      const isTod = isToday(date)
                      const dayBookings = (rentalBookings ?? []).filter(
                        b => b.objectId === obj.id && b.date === dateStr && b.status !== 'cancelled',
                      )
                      const hasFullDay = dayBookings.some(b => b.isFullDay)

                      return (
                        <div
                          key={i}
                          onClick={() => setRentalModal({ obj, date: dateStr })}
                          className={cn(
                            'shrink-0 border-r border-slate-200 dark:border-slate-700 cursor-pointer relative',
                            'hover:bg-slate-50 dark:hover:bg-slate-700/40 transition-colors',
                            isWe && 'bg-amber-50/30 dark:bg-amber-900/10',
                            isTod && 'bg-brand-50/40 dark:bg-brand-900/10',
                          )}
                          style={{ width: CELL_WIDTH, height: ROW_HEIGHT }}
                        >
                          {hasFullDay ? (
                            /* Full day booking */
                            <div className={cn(
                              'absolute inset-1.5 rounded flex items-center justify-center text-white text-[10px] font-medium',
                              obj.color,
                            )}>
                              Весь день
                            </div>
                          ) : dayBookings.length > 0 ? (
                            /* Hourly booking bars */
                            <div className="absolute inset-x-1 bottom-1" style={{ top: 6 }}>
                              {/* Time scale bar (background) */}
                              <div className="w-full h-2.5 rounded-sm bg-slate-100 dark:bg-slate-600 relative overflow-hidden">
                                {dayBookings.map(b => {
                                  const leftPct = ((b.startHour - obj.openHour) / totalSpan) * 100
                                  const widthPct = ((b.endHour - b.startHour) / totalSpan) * 100
                                  return (
                                    <div
                                      key={b.id}
                                      className={cn('absolute h-full rounded-sm', obj.color)}
                                      style={{ left: `${leftPct}%`, width: `${widthPct}%` }}
                                      title={`${b.guestName} · ${b.startHour}:00–${b.endHour}:00`}
                                    />
                                  )
                                })}
                              </div>
                              {/* Hour labels */}
                              <div className="flex justify-between mt-0.5 px-0.5">
                                <span className="text-[9px] text-slate-400">{obj.openHour}:00</span>
                                <span className="text-[9px] text-slate-400">{obj.closeHour}:00</span>
                              </div>
                              {/* Booking count */}
                              <div className="flex flex-wrap gap-0.5 mt-1">
                                {dayBookings.map(b => (
                                  <span key={b.id} className="text-[9px] text-slate-500 dark:text-slate-400 bg-slate-100 dark:bg-slate-700 px-1 rounded truncate max-w-full">
                                    {b.startHour}–{b.endHour}
                                  </span>
                                ))}
                              </div>
                            </div>
                          ) : (
                            /* Empty — show "+" hint on hover */
                            <div className="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity">
                              <span className="text-xs text-slate-400">+</span>
                            </div>
                          )}
                        </div>
                      )
                    })}
                  </div>
                )
              })}
            </>
          )}
        </div>
      </div>

      {/* Booking create modal */}
      {bookingModalDraft && (
        <BookingModal
          open={true}
          draft={bookingModalDraft}
          rooms={rooms}
          onClose={() => setBookingModalDraft(null)}
          onSave={(data) => {
            onBookingCreate(data)
            setBookingModalDraft(null)
          }}
        />
      )}

      {/* Booking detail panel */}
      {selectedBooking && (
        <BookingDetailPanel
          booking={selectedBooking}
          room={rooms.find(r => r.id === selectedBooking.roomId)}
          onClose={() => setSelectedBooking(null)}
          onUpdate={(id, data) => {
            onBookingUpdate(id, data)
            setSelectedBooking(null)
          }}
        />
      )}

      {/* Rental booking modal */}
      {rentalModal && (
        <RentalBookingModal
          obj={rentalModal.obj}
          date={rentalModal.date}
          existingBookings={(rentalBookings ?? []).filter(
            b => b.objectId === rentalModal.obj.id && b.date === rentalModal.date,
          )}
          onClose={() => setRentalModal(null)}
          onSave={(b) => {
            onRentalBookingCreate?.(b)
            setRentalModal(null)
          }}
        />
      )}
    </div>
  )
}
