import { useState, useEffect, useCallback } from 'react'
import { ChevronLeft, ChevronRight, Calendar, Users, X, Check, Loader2 } from 'lucide-react'
import { api, type ScheduleEntry } from '../lib/api'
import { useAuth } from '../contexts/AuthContext'
import type { User } from '../types'
import { cn } from '../lib/utils'
import {
  format, startOfWeek, addDays, addWeeks, subWeeks, isToday, parseISO,
  startOfMonth, endOfMonth, eachDayOfInterval, addMonths, subMonths, getDay,
} from 'date-fns'
import { ru } from 'date-fns/locale'

const ROLE_COLORS: Record<string, string> = {
  hotel_admin:  'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
  manager:      'bg-brand-100 text-brand-700 dark:bg-brand-900/30 dark:text-brand-300',
  receptionist: 'bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-300',
  housekeeper:  'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300',
  accountant:   'bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-300',
  security:     'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300',
  technician:   'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
}

const ROLE_LABELS: Record<string, string> = {
  hotel_admin:  'Сис. администратор',
  manager:      'Менеджер',
  receptionist: 'Ресепшн',
  housekeeper:  'Горничная',
  accountant:   'Бухгалтер',
  security:     'Охрана',
  technician:   'Тех. специалист',
}

const SHIFT_PRESETS = [
  { label: 'Дневная', start: '09:00', end: '21:00' },
  { label: 'Ночная',  start: '21:00', end: '09:00' },
  { label: 'Утро',   start: '07:00', end: '15:00' },
  { label: 'Вечер',  start: '15:00', end: '23:00' },
  { label: '8 часов',start: '09:00', end: '17:00' },
]

function getWeekDays(weekStart: Date): Date[] {
  return Array.from({ length: 7 }, (_, i) => addDays(weekStart, i))
}

function fmtDate(d: Date) {
  return format(d, 'yyyy-MM-dd')
}

function fmtTime(t: string | null | undefined) {
  if (!t) return ''
  return t.slice(0, 5)
}

/** Returns true if the date is Saturday (6) or Sunday (0) */
function isWeekend(d: Date): boolean {
  const dow = getDay(d)
  return dow === 0 || dow === 6
}

interface CellEditorProps {
  userId: string
  date: string
  entry: ScheduleEntry | undefined
  onClose: () => void
  onSave: (data: { shift_start?: string; shift_end?: string; is_day_off: boolean; notes?: string }) => Promise<void>
  onDelete: () => Promise<void>
}

function CellEditor({ date, entry, onClose, onSave, onDelete }: CellEditorProps) {
  const [isDayOff, setIsDayOff] = useState(entry?.isDayOff ?? false)
  const [shiftStart, setShiftStart] = useState(fmtTime(entry?.shiftStart) || '09:00')
  const [shiftEnd,   setShiftEnd]   = useState(fmtTime(entry?.shiftEnd)   || '18:00')
  const [notes, setNotes] = useState(entry?.notes ?? '')
  const [saving, setSaving] = useState(false)

  const applyPreset = (p: typeof SHIFT_PRESETS[0]) => {
    setShiftStart(p.start)
    setShiftEnd(p.end)
    setIsDayOff(false)
  }

  const handleSave = async () => {
    setSaving(true)
    await onSave({
      shift_start: isDayOff ? undefined : shiftStart || undefined,
      shift_end:   isDayOff ? undefined : shiftEnd   || undefined,
      is_day_off:  isDayOff,
      notes:       notes || undefined,
    })
    setSaving(false)
  }

  const handleDelete = async () => {
    setSaving(true)
    await onDelete()
    setSaving(false)
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50" onClick={onClose}>
      <div className="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-5 w-full max-w-sm" onClick={e => e.stopPropagation()}>
        <div className="flex items-center justify-between mb-4">
          <h3 className="font-semibold text-slate-900 dark:text-slate-100 text-sm">
            {format(parseISO(date), 'd MMMM', { locale: ru })}
          </h3>
          <button onClick={onClose} className="btn-ghost p-1"><X size={16} /></button>
        </div>

        {/* Day off toggle */}
        <div className="flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-slate-700/50 mb-3">
          <span className="text-sm font-medium text-slate-700 dark:text-slate-300">Выходной день</span>
          <button
            onClick={() => setIsDayOff(v => !v)}
            className={cn('relative w-10 h-5 rounded-full transition-colors', isDayOff ? 'bg-red-500' : 'bg-slate-300 dark:bg-slate-600')}
          >
            <div className={cn('absolute top-0.5 w-4 h-4 rounded-full bg-white shadow transition-transform', isDayOff ? 'left-[22px]' : 'left-0.5')} />
          </button>
        </div>

        {!isDayOff && (
          <>
            {/* Presets */}
            <div className="flex flex-wrap gap-1.5 mb-3">
              {SHIFT_PRESETS.map(p => (
                <button key={p.label} onClick={() => applyPreset(p)}
                  className="text-xs px-2 py-1 rounded-lg bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-400 hover:bg-brand-50 hover:text-brand-700 dark:hover:bg-brand-900/30 dark:hover:text-brand-300 transition-colors">
                  {p.label}
                </button>
              ))}
            </div>

            {/* Time inputs */}
            <div className="grid grid-cols-2 gap-3 mb-3">
              <div>
                <label className="text-xs text-slate-500 dark:text-slate-400 mb-1 block">Начало</label>
                <input type="time" value={shiftStart} onChange={e => setShiftStart(e.target.value)}
                  className="input text-sm w-full" />
              </div>
              <div>
                <label className="text-xs text-slate-500 dark:text-slate-400 mb-1 block">Конец</label>
                <input type="time" value={shiftEnd} onChange={e => setShiftEnd(e.target.value)}
                  className="input text-sm w-full" />
              </div>
            </div>
          </>
        )}

        {/* Notes */}
        <textarea
          value={notes}
          onChange={e => setNotes(e.target.value)}
          placeholder="Заметка (необязательно)"
          rows={2}
          className="input text-sm w-full resize-none mb-4"
        />

        <div className="flex gap-2">
          {entry && (
            <button onClick={handleDelete} disabled={saving}
              className="btn-secondary text-sm text-red-600 dark:text-red-400 border-red-200 dark:border-red-800 hover:bg-red-50 dark:hover:bg-red-900/20">
              Удалить
            </button>
          )}
          <button onClick={handleSave} disabled={saving}
            className="btn-primary flex-1 justify-center text-sm gap-2">
            {saving ? <Loader2 size={14} className="animate-spin" /> : <Check size={14} />}
            Сохранить
          </button>
        </div>
      </div>
    </div>
  )
}

export function SchedulePage() {
  const { user } = useAuth()
  const slug = user?.hotelSlug ?? ''
  const isManager = ['hotel_admin', 'manager', 'super_admin'].includes(user?.role ?? '')

  const [viewMode, setViewMode] = useState<'week' | 'month'>('week')

  const [weekStart, setWeekStart] = useState(() =>
    startOfWeek(new Date(), { weekStartsOn: 1 })
  )
  const [monthStart, setMonthStart] = useState(() =>
    startOfMonth(new Date())
  )

  const [users, setUsers]       = useState<User[]>([])
  const [schedule, setSchedule] = useState<ScheduleEntry[]>([])
  const [loading, setLoading]   = useState(true)
  const [roleFilter, setRoleFilter] = useState<string>('all')
  const [editing, setEditing]   = useState<{ userId: string; date: string } | null>(null)

  // Compute date range depending on view mode
  const weekDays = getWeekDays(weekStart)
  const monthDays = eachDayOfInterval({ start: monthStart, end: endOfMonth(monthStart) })

  const from = viewMode === 'week' ? fmtDate(weekDays[0]) : fmtDate(monthStart)
  const to   = viewMode === 'week' ? fmtDate(weekDays[6]) : fmtDate(endOfMonth(monthStart))

  const loadData = useCallback(async () => {
    if (!slug) return
    setLoading(true)
    try {
      const [u, s] = await Promise.all([
        api.users.list(slug),
        api.schedule.list(slug, from, to),
      ])
      setUsers(u)
      setSchedule(s)
    } catch (e) {
      console.error(e)
    } finally {
      setLoading(false)
    }
  }, [slug, from, to])

  useEffect(() => { loadData() }, [loadData])

  const getEntry = (userId: string, date: string) =>
    schedule.find(s => s.userId === userId && s.date === date)

  const handleSave = async (userId: string, date: string, data: {
    shift_start?: string; shift_end?: string; is_day_off: boolean; notes?: string
  }) => {
    try {
      const saved = await api.schedule.upsert(slug, { user_id: userId, date, ...data })
      setSchedule(prev => {
        const filtered = prev.filter(s => !(s.userId === userId && s.date === date))
        return [...filtered, saved]
      })
      setEditing(null)
    } catch (e) {
      console.error(e)
    }
  }

  const handleDelete = async (userId: string, date: string) => {
    try {
      await api.schedule.remove(slug, userId, date)
      setSchedule(prev => prev.filter(s => !(s.userId === userId && s.date === date)))
      setEditing(null)
    } catch (e) {
      console.error(e)
    }
  }

  const filteredUsers = users.filter(u =>
    roleFilter === 'all' || u.role === roleFilter
  )

  // Count scheduled shifts per user in current range
  const getShiftCount = (userId: string) =>
    schedule.filter(s => s.userId === userId && !s.isDayOff).length

  const allRoles = [...new Set(users.map(u => u.role))].filter(Boolean).sort()

  // Navigation handlers
  const goTodayWeek  = () => setWeekStart(startOfWeek(new Date(), { weekStartsOn: 1 }))
  const goTodayMonth = () => setMonthStart(startOfMonth(new Date()))

  return (
    <div className="p-4 md:p-6 space-y-5">
      {/* Header */}
      <div className="flex items-center justify-between flex-wrap gap-3">
        <div>
          <h1 className="text-xl font-bold text-slate-900 dark:text-slate-100">График работы</h1>
          <p className="text-sm text-slate-500 dark:text-slate-400">{users.length} сотрудников</p>
        </div>

        <div className="flex items-center gap-2 flex-wrap">
          {/* View mode toggle */}
          <div className="flex rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden text-sm">
            <button
              onClick={() => setViewMode('week')}
              className={cn(
                'px-3 py-1.5 transition-colors',
                viewMode === 'week'
                  ? 'bg-brand-600 text-white'
                  : 'bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-700'
              )}
            >
              Неделя
            </button>
            <button
              onClick={() => setViewMode('month')}
              className={cn(
                'px-3 py-1.5 border-l border-slate-200 dark:border-slate-700 transition-colors',
                viewMode === 'month'
                  ? 'bg-brand-600 text-white'
                  : 'bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-700'
              )}
            >
              Месяц
            </button>
          </div>

          {/* Navigation */}
          {viewMode === 'week' ? (
            <>
              <button onClick={() => setWeekStart(w => subWeeks(w, 1))} className="btn-secondary p-2">
                <ChevronLeft size={16} />
              </button>
              <div className="text-sm font-medium text-slate-700 dark:text-slate-300 min-w-[160px] text-center">
                {format(weekDays[0], 'd MMM', { locale: ru })} — {format(weekDays[6], 'd MMM yyyy', { locale: ru })}
              </div>
              <button onClick={() => setWeekStart(w => addWeeks(w, 1))} className="btn-secondary p-2">
                <ChevronRight size={16} />
              </button>
              <button onClick={goTodayWeek} className="btn-secondary text-sm">
                Сегодня
              </button>
            </>
          ) : (
            <>
              <button onClick={() => setMonthStart(m => subMonths(m, 1))} className="btn-secondary p-2">
                <ChevronLeft size={16} />
              </button>
              <div className="text-sm font-medium text-slate-700 dark:text-slate-300 min-w-[140px] text-center capitalize">
                {format(monthStart, 'LLLL yyyy', { locale: ru })}
              </div>
              <button onClick={() => setMonthStart(m => addMonths(m, 1))} className="btn-secondary p-2">
                <ChevronRight size={16} />
              </button>
              <button onClick={goTodayMonth} className="btn-secondary text-sm">
                Сегодня
              </button>
            </>
          )}
        </div>
      </div>

      {/* Filters */}
      <div className="flex items-center gap-2 flex-wrap">
        <Users size={15} className="text-slate-400" />
        <button
          onClick={() => setRoleFilter('all')}
          className={cn('text-xs px-3 py-1.5 rounded-lg border transition-colors',
            roleFilter === 'all'
              ? 'bg-brand-600 text-white border-brand-600'
              : 'bg-white dark:bg-slate-800 border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-400 hover:border-brand-300'
          )}
        >
          Все роли
        </button>
        {allRoles.map(role => (
          <button key={role}
            onClick={() => setRoleFilter(role)}
            className={cn('text-xs px-3 py-1.5 rounded-lg border transition-colors',
              roleFilter === role
                ? 'bg-brand-600 text-white border-brand-600'
                : 'bg-white dark:bg-slate-800 border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-400 hover:border-brand-300'
            )}
          >
            {ROLE_LABELS[role] ?? role}
          </button>
        ))}
      </div>

      {/* Schedule grid */}
      {loading ? (
        <div className="flex items-center justify-center h-48">
          <Loader2 size={24} className="animate-spin text-brand-600" />
        </div>
      ) : filteredUsers.length === 0 ? (
        <div className="text-center py-16 text-slate-400 dark:text-slate-500">
          {users.length === 0
            ? 'Нет сотрудников. Добавьте их на странице «Сотрудники».'
            : 'Нет сотрудников с выбранной ролью.'}
        </div>
      ) : viewMode === 'week' ? (
        /* ── WEEK VIEW ── */
        <div className="overflow-x-auto rounded-2xl border border-slate-200 dark:border-slate-700">
          <table className="w-full min-w-[700px] border-collapse">
            <thead>
              <tr className="bg-slate-50 dark:bg-slate-800/50">
                <th className="text-left px-4 py-3 text-xs font-semibold text-slate-500 dark:text-slate-400 w-44 border-b border-slate-200 dark:border-slate-700">
                  Сотрудник
                </th>
                {weekDays.map(day => (
                  <th key={fmtDate(day)}
                    className={cn(
                      'px-2 py-3 text-center text-xs font-semibold border-b border-slate-200 dark:border-slate-700 min-w-[90px]',
                      isToday(day)
                        ? 'text-brand-600 dark:text-brand-400'
                        : 'text-slate-500 dark:text-slate-400'
                    )}
                  >
                    <div>{format(day, 'EEE', { locale: ru })}</div>
                    <div className={cn(
                      'text-base font-bold mt-0.5',
                      isToday(day) ? 'text-brand-600 dark:text-brand-400' : 'text-slate-700 dark:text-slate-300'
                    )}>
                      {format(day, 'd')}
                    </div>
                  </th>
                ))}
                <th className="px-3 py-3 text-xs font-semibold text-slate-400 border-b border-slate-200 dark:border-slate-700 text-center">
                  Смен
                </th>
              </tr>
            </thead>
            <tbody>
              {filteredUsers.map((u, idx) => (
                <tr key={u.id}
                  className={cn(
                    'border-b border-slate-100 dark:border-slate-700/50 last:border-0',
                    idx % 2 === 0 ? 'bg-white dark:bg-slate-800' : 'bg-slate-50/50 dark:bg-slate-800/50'
                  )}
                >
                  {/* Employee info */}
                  <td className="px-4 py-2.5">
                    <div className="font-medium text-sm text-slate-900 dark:text-slate-100 truncate max-w-[150px]">
                      {u.name}
                    </div>
                    <span className={cn('text-[10px] px-1.5 py-0.5 rounded-md font-medium', ROLE_COLORS[u.role] ?? 'bg-slate-100 text-slate-600')}>
                      {ROLE_LABELS[u.role] ?? u.role}
                    </span>
                  </td>

                  {/* Day cells */}
                  {weekDays.map(day => {
                    const dateStr = fmtDate(day)
                    const entry = getEntry(u.id, dateStr)
                    return (
                      <td key={dateStr}
                        className={cn(
                          'px-1.5 py-1.5 text-center align-middle',
                          isToday(day) && 'bg-brand-50/30 dark:bg-brand-900/10',
                        )}
                      >
                        <button
                          onClick={() => isManager && setEditing({ userId: u.id, date: dateStr })}
                          className={cn(
                            'w-full min-h-[44px] rounded-lg text-xs font-medium transition-all',
                            isManager && 'hover:ring-2 hover:ring-brand-300',
                            entry?.isDayOff
                              ? 'bg-red-50 dark:bg-red-900/20 text-red-500 dark:text-red-400'
                              : entry?.shiftStart
                              ? 'bg-emerald-50 dark:bg-emerald-900/20 text-emerald-700 dark:text-emerald-300'
                              : 'bg-slate-50 dark:bg-slate-700/30 text-slate-300 dark:text-slate-600',
                          )}
                        >
                          {entry?.isDayOff ? (
                            <span>Вых.</span>
                          ) : entry?.shiftStart ? (
                            <div>
                              <div>{fmtTime(entry.shiftStart)}</div>
                              <div className="text-[10px] opacity-70">–{fmtTime(entry.shiftEnd)}</div>
                            </div>
                          ) : (
                            <span className="text-lg leading-none">+</span>
                          )}
                        </button>
                      </td>
                    )
                  })}

                  {/* Shift count */}
                  <td className="px-3 py-2.5 text-center text-sm font-semibold text-slate-500 dark:text-slate-400">
                    {getShiftCount(u.id)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ) : (
        /* ── MONTH VIEW ── */
        <div className="overflow-x-auto rounded-2xl border border-slate-200 dark:border-slate-700">
          <table className="border-collapse" style={{ minWidth: `${180 + monthDays.length * 36 + 44}px` }}>
            <thead>
              <tr className="bg-slate-50 dark:bg-slate-800/50">
                {/* Employee column */}
                <th className="sticky left-0 z-10 bg-slate-50 dark:bg-slate-800/50 text-left px-3 py-2 text-xs font-semibold text-slate-500 dark:text-slate-400 w-44 border-b border-slate-200 dark:border-slate-700">
                  Сотрудник
                </th>
                {monthDays.map(day => (
                  <th key={fmtDate(day)}
                    className={cn(
                      'px-0.5 py-2 text-center text-[10px] font-semibold border-b border-slate-200 dark:border-slate-700 w-9',
                      isWeekend(day) && 'bg-slate-100 dark:bg-slate-700/50',
                      isToday(day) ? 'text-brand-600 dark:text-brand-400' : 'text-slate-500 dark:text-slate-400'
                    )}
                  >
                    <div className="leading-tight">{format(day, 'EEE', { locale: ru }).slice(0, 2)}</div>
                    <div className={cn(
                      'font-bold text-xs leading-tight',
                      isToday(day) ? 'text-brand-600 dark:text-brand-400' : 'text-slate-700 dark:text-slate-300'
                    )}>
                      {format(day, 'd')}
                    </div>
                  </th>
                ))}
                {/* Shift count column */}
                <th className="px-2 py-2 text-[10px] font-semibold text-slate-400 border-b border-slate-200 dark:border-slate-700 text-center w-11">
                  Смен
                </th>
              </tr>
            </thead>
            <tbody>
              {filteredUsers.map((u, idx) => (
                <tr key={u.id}
                  className={cn(
                    'border-b border-slate-100 dark:border-slate-700/50 last:border-0',
                    idx % 2 === 0 ? 'bg-white dark:bg-slate-800' : 'bg-slate-50/30 dark:bg-slate-800/30'
                  )}
                >
                  {/* Employee info — sticky */}
                  <td className={cn(
                    'sticky left-0 z-10 px-3 py-1.5 border-r border-slate-100 dark:border-slate-700/50',
                    idx % 2 === 0 ? 'bg-white dark:bg-slate-800' : 'bg-slate-50/30 dark:bg-slate-800/30'
                  )}>
                    <div className="font-medium text-xs text-slate-900 dark:text-slate-100 truncate max-w-[140px]">
                      {u.name}
                    </div>
                    <span className={cn('text-[9px] px-1 py-0.5 rounded font-medium', ROLE_COLORS[u.role] ?? 'bg-slate-100 text-slate-600')}>
                      {ROLE_LABELS[u.role] ?? u.role}
                    </span>
                  </td>

                  {/* Day cells — compact */}
                  {monthDays.map(day => {
                    const dateStr = fmtDate(day)
                    const entry = getEntry(u.id, dateStr)
                    const weekend = isWeekend(day)
                    return (
                      <td key={dateStr}
                        className={cn(
                          'px-0.5 py-0.5 text-center align-middle',
                          weekend && 'bg-slate-50 dark:bg-slate-700/20',
                          isToday(day) && 'bg-brand-50/40 dark:bg-brand-900/10',
                        )}
                      >
                        <button
                          onClick={() => isManager && setEditing({ userId: u.id, date: dateStr })}
                          title={
                            entry?.isDayOff
                              ? 'Выходной'
                              : entry?.shiftStart
                              ? `${fmtTime(entry.shiftStart)} – ${fmtTime(entry.shiftEnd)}`
                              : dateStr
                          }
                          className={cn(
                            'w-8 h-7 rounded text-[10px] font-semibold transition-all flex items-center justify-center mx-auto',
                            isManager && 'hover:ring-1 hover:ring-brand-300',
                            entry?.isDayOff
                              ? 'bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400'
                              : entry?.shiftStart
                              ? 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300'
                              : 'bg-slate-50 dark:bg-slate-700/30 text-slate-300 dark:text-slate-600',
                          )}
                        >
                          {entry?.isDayOff ? (
                            <span>В</span>
                          ) : entry?.shiftStart ? (
                            <span>{fmtTime(entry.shiftStart).slice(0, 5)}</span>
                          ) : (
                            <span className="text-xs leading-none">+</span>
                          )}
                        </button>
                      </td>
                    )
                  })}

                  {/* Monthly shift count */}
                  <td className="px-2 py-1.5 text-center text-xs font-semibold text-slate-500 dark:text-slate-400">
                    {getShiftCount(u.id)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Legend */}
      <div className="flex items-center gap-4 text-xs text-slate-400 dark:text-slate-500">
        <div className="flex items-center gap-1.5">
          <div className="w-3 h-3 rounded bg-emerald-100 dark:bg-emerald-900/30" />
          Рабочая смена
        </div>
        <div className="flex items-center gap-1.5">
          <div className="w-3 h-3 rounded bg-red-50 dark:bg-red-900/20" />
          Выходной
        </div>
        <div className="flex items-center gap-1.5">
          <div className="w-3 h-3 rounded bg-slate-100 dark:bg-slate-700" />
          Не назначено
        </div>
        {isManager && <span className="ml-auto">Нажмите на ячейку чтобы назначить смену</span>}
      </div>

      {/* Cell editor modal */}
      {editing && (
        <CellEditor
          userId={editing.userId}
          date={editing.date}
          entry={getEntry(editing.userId, editing.date)}
          onClose={() => setEditing(null)}
          onSave={(data) => handleSave(editing.userId, editing.date, data)}
          onDelete={() => handleDelete(editing.userId, editing.date)}
        />
      )}
    </div>
  )
}

// silence unused import warning
void Calendar
