import { useState, useEffect, useCallback, useRef } from 'react'
import { CheckCircle2, Clock, Sparkles, User, ListChecks, Settings2, Save, Wrench, X as XIcon, Send, AlertTriangle, BanIcon, Loader2, History, ChevronLeft, ChevronRight, Camera } from 'lucide-react'
import { useAuth } from '../contexts/AuthContext'
import { useHotelSocket } from '../hooks/useHotelSocket'
import type { WsMessage } from '../hooks/useHotelSocket'
import { api } from '../lib/api'
import type { HkSettings } from '../lib/api'
import type { HousekeepingTask } from '../types'
import { cn } from '../lib/utils'
import { Badge } from '../components/ui/Badge'
import { useNotifications } from '../contexts/NotificationsContext'
import { format, subDays, addDays, parseISO } from 'date-fns'
import { ru } from 'date-fns/locale'

// Normalize snake_case WS task objects to camelCase
function normalizeTask(raw: Record<string, unknown>): Record<string, unknown> {
  return {
    ...raw,
    roomNumber:       raw.roomNumber       ?? raw.room_number,
    roomId:           raw.roomId           ?? raw.room_id,
    assigneeName:     raw.assigneeName     ?? raw.assignee_name,
    dueDate:          raw.dueDate          ?? raw.due_date,
    completedAt:      raw.completedAt      ?? raw.completed_at,
    startedAt:        raw.startedAt        ?? raw.started_at,
    resolutionNotes:  raw.resolutionNotes  ?? raw.resolution_notes,
    resolutionPhotos: raw.resolutionPhotos ?? raw.resolution_photos,
  }
}

function Toggle({ on, onChange }: { on: boolean; onChange: () => void }) {
  return (
    <button
      onClick={onChange}
      className={cn('relative w-10 rounded-full transition-colors shrink-0 h-[22px]', on ? 'bg-brand-600' : 'bg-slate-200 dark:bg-slate-600')}
    >
      <div className={cn('absolute top-0.5 rounded-full bg-white shadow-sm transition-transform w-[18px] h-[18px]', on ? 'left-[20px]' : 'left-0.5')} />
    </button>
  )
}

type Column = 'pending' | 'in_progress' | 'done'

const COLUMNS: { id: Column; label: string; icon: React.ElementType; color: string }[] = [
  { id: 'pending',     label: 'Ожидают',    icon: Clock,        color: 'text-amber-600 dark:text-amber-400' },
  { id: 'in_progress', label: 'В процессе', icon: Sparkles,     color: 'text-blue-600 dark:text-blue-400' },
  { id: 'done',        label: 'Готово',      icon: CheckCircle2, color: 'text-emerald-600 dark:text-emerald-400' },
]

const PRIORITY_COLORS: Record<string, string> = {
  urgent: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300',
  high:   'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300',
  medium: 'bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-300',
  low:    'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300',
}

const PRIORITY_LABELS: Record<string, string> = {
  urgent: 'Срочно', high: 'Срочно', medium: 'Обычный', low: 'Низкий',
}

const TYPE_COLORS: Record<string, string> = {
  cleaning:    'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300',
  turnover:    'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
  inspection:  'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
  maintenance: 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300',
}

const TYPE_LABELS: Record<string, string> = {
  cleaning: 'Уборка', turnover: 'Уборка при выезде', inspection: 'Проверка', maintenance: 'Ремонт',
}

export function HousekeepingPage() {
  const { user, session } = useAuth()
  const slug = user?.hotelSlug ?? ''

  const [activeTasks, setActiveTasks]   = useState<HousekeepingTask[]>([])
  const [historyTasks, setHistoryTasks] = useState<HousekeepingTask[]>([])
  const [historyDate, setHistoryDate]   = useState(format(new Date(), 'yyyy-MM-dd'))
  const [loading, setLoading]           = useState(true)
  const [historyLoading, setHistoryLoading] = useState(false)
  const [activeTab, setActiveTab]       = useState<'tasks' | 'history' | 'plans'>('tasks')
  const [planSaved, setPlanSaved]       = useState(false)

  const handleWsMessage = useCallback((msg: WsMessage) => {
    if (msg.type === 'housekeeping_task_created') {
      const task = normalizeTask(msg.task as Record<string, unknown>)
      if (task.category !== 'maintenance') {
        setActiveTasks(prev => prev.some(t => t.id === task.id) ? prev : [task as unknown as HousekeepingTask, ...prev])
      }
    } else if (msg.type === 'housekeeping_updated') {
      const task = normalizeTask(msg.task as Record<string, unknown>)
      if (task.category !== 'maintenance') {
        if (task.status === 'done') {
          setActiveTasks(prev => prev.filter(t => t.id !== task.id))
        } else {
          setActiveTasks(prev => prev.map(t => t.id === task.id ? task as unknown as HousekeepingTask : t))
        }
      }
    }
  }, [])

  const { send } = useHotelSocket({ slug, token: session?.token ?? null, onMessage: handleWsMessage })

  // Load active tasks (all pending/in_progress — no date filter)
  useEffect(() => {
    if (!slug) return
    Promise.all([
      api.housekeeping.list(slug, { status: 'active', category: 'housekeeping' }),
      api.housekeeping.getSettings(slug).catch(() => null),
    ]).then(([t, s]) => {
      setActiveTasks(t)
      if (s) {
        // API response goes through transformKeys → camelCase
        const ss = s as unknown as {
          checkoutAuto: boolean; checkoutPriority: string
          inspectionAfterClean: boolean; requireCompletionPhoto: boolean; emergencyCloseDays: number
          autoAssign: boolean; autoAssignStrategy: string
        }
        setPlans(prev => ({
          ...prev,
          checkoutAuto: ss.checkoutAuto,
          checkoutPriority: ss.checkoutPriority as 'high' | 'medium',
          inspectionAfterClean: ss.inspectionAfterClean,
          requireCompletionPhoto: ss.requireCompletionPhoto ?? false,
          emergencyCloseDays: ss.emergencyCloseDays ?? 1,
          autoAssign: ss.autoAssign ?? false,
          autoAssignStrategy: (ss.autoAssignStrategy ?? 'least_loaded') as 'round_robin' | 'least_loaded' | 'first_free',
        }))
      }
    }).catch(console.error)
      .finally(() => setLoading(false))
  }, [slug])

  // Load history when tab opens or date changes
  useEffect(() => {
    if (activeTab !== 'history' || !slug) return
    setHistoryLoading(true)
    Promise.all([
      api.housekeeping.list(slug, { status: 'done', date: historyDate }),
      api.housekeeping.list(slug, { category: 'maintenance', status: 'active', date: historyDate }),
    ]).then(([done, activeMaint]) => {
      const merged = [...done]
      for (const t of activeMaint) {
        if (!merged.some(x => x.id === t.id)) merged.push(t)
      }
      setHistoryTasks(merged)
    })
      .catch(console.error)
      .finally(() => setHistoryLoading(false))
  }, [activeTab, historyDate, slug])

  // Cleaning plan settings
  const [plans, setPlans] = useState({
    checkoutAuto: true, checkoutPriority: 'high' as 'high' | 'medium',
    checkoutInspection: true, dailyEnabled: true, dailyIntervalDays: 1,
    dailyStartFromDay: 1, onDemandEnabled: true, onDemandPriority: 'medium' as 'high' | 'medium' | 'low',
    deepCleanEnabled: false, deepCleanEveryDays: 7,
    inspectionAfterClean: true, autoAssign: false, autoAssignStrategy: 'least_loaded' as 'round_robin' | 'least_loaded' | 'first_free',
    requireCompletionPhoto: false, emergencyCloseDays: 1,
  })

  const setP = <K extends keyof typeof plans>(k: K, v: typeof plans[K]) =>
    setPlans(prev => ({ ...prev, [k]: v }))

  const [planSaving, setPlanSaving] = useState(false)
  const savePlans = async () => {
    setPlanSaving(true)
    try {
      const settings: HkSettings = {
        checkout_auto: plans.checkoutAuto,
        checkout_priority: plans.checkoutPriority,
        inspection_after_clean: plans.inspectionAfterClean,
        require_completion_photo: plans.requireCompletionPhoto,
        emergency_close_days: plans.emergencyCloseDays,
        auto_assign: plans.autoAssign,
        auto_assign_strategy: plans.autoAssignStrategy,
      }
      await api.housekeeping.saveSettings(slug, settings)
      setPlanSaved(true)
      setTimeout(() => setPlanSaved(false), 2000)
    } catch (err) {
      console.error('Failed to save settings:', err)
    } finally {
      setPlanSaving(false)
    }
  }

  const updateStatus = async (id: string, status: HousekeepingTask['status'], resolutionNotes?: string) => {
    try {
      const payload: Record<string, unknown> = { status }
      if (resolutionNotes) payload.resolution_notes = resolutionNotes
      const updated = await api.housekeeping.update(slug, id, payload)
      if (updated.status === 'done') {
        setActiveTasks(prev => prev.filter(t => t.id !== id))
        if (activeTab === 'history' && updated.completedAt?.startsWith(historyDate)) {
          setHistoryTasks(prev => [updated, ...prev])
        }
      } else {
        setActiveTasks(prev => prev.map(t => t.id === id ? updated : t))
      }
    } catch (err) {
      console.error('Failed to update task:', err)
    }
  }

  const { addNotification } = useNotifications()

  const addMaintenanceReport = async (id: string, note: string, severity: 'low' | 'medium' | 'high', photos: string[]) => {
    const task = activeTasks.find(t => t.id === id)
    const tAny = task as unknown as Record<string, string>
    const priority = severity === 'high' ? 'urgent' : severity === 'medium' ? 'medium' : 'low'
    try {
      const newTask = await api.housekeeping.create(slug, {
        room_id: tAny?.roomId || undefined,
        type: 'maintenance',
        priority,
        notes: note,
        due_date: format(new Date(), 'yyyy-MM-dd'),
        category: 'maintenance',
        photos,
      })
      send({ type: 'housekeeping_task_created', task: newTask as unknown as Record<string, unknown> })
    } catch (err) {
      console.error('Failed to create maintenance task:', err)
    }
    const severityLabel = severity === 'high' ? 'Экстренно' : severity === 'medium' ? 'Средняя срочность' : 'Не срочно'
    addNotification({
      type: 'maintenance',
      title: severity === 'high'
        ? `⚠️ Экстренная поломка — Номер ${task?.roomNumber}`
        : `Поломка в номере ${task?.roomNumber}`,
      body: `[${severityLabel}] ${note}`,
      link: '/technical',
    })
  }

  const total = activeTasks.length
  const done  = activeTasks.filter(t => t.status === 'done').length

  if (loading) {
    return (
      <div className="flex items-center justify-center h-64">
        <Loader2 size={24} className="animate-spin text-brand-600" />
      </div>
    )
  }

  return (
    <div className="p-4 md:p-6 space-y-5">
      {/* Header */}
      <div className="flex items-start justify-between">
        <div className="flex-1">
          <h1 className="text-xl font-bold text-slate-900 dark:text-slate-100">Уборка и обслуживание</h1>
          {activeTab === 'tasks' && (
            <div className="flex items-center gap-3 mt-1.5">
              <div className="flex-1 bg-slate-200 dark:bg-slate-700 rounded-full h-2">
                <div
                  className="h-2 rounded-full bg-emerald-500 transition-all duration-500"
                  style={{ width: total ? `${(done / total) * 100}%` : '0%' }}
                />
              </div>
              <span className="text-sm text-slate-600 dark:text-slate-400 shrink-0">
                {done} / {total} завершено
              </span>
            </div>
          )}
        </div>
      </div>

      {/* Tabs */}
      <div className="flex border-b border-slate-200 dark:border-slate-700">
        {([
          { id: 'tasks'   as const, label: 'Задачи',        icon: ListChecks },
          { id: 'history' as const, label: 'История',        icon: History },
          { id: 'plans'   as const, label: 'Планы уборки',  icon: Settings2 },
        ]).map(t => (
          <button
            key={t.id}
            onClick={() => setActiveTab(t.id)}
            className={cn(
              'flex items-center gap-1.5 px-4 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors',
              activeTab === t.id
                ? 'border-brand-600 text-brand-600 dark:text-brand-400 dark:border-brand-400'
                : 'border-transparent text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-300',
            )}
          >
            <t.icon size={14} />
            {t.label}
          </button>
        ))}
      </div>

      {/* ── Tasks tab ── */}
      {activeTab === 'tasks' && (
        <>
          {activeTasks.length === 0 ? (
            <div className="text-center py-16 text-slate-400 dark:text-slate-500">
              Активных задач нет
            </div>
          ) : (
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              {(['pending', 'in_progress'] as Column[]).map(colId => {
                const col = COLUMNS.find(c => c.id === colId)!
                const colTasks = activeTasks.filter(t => t.status === colId)
                const Icon = col.icon
                return (
                  <div key={col.id} className="space-y-3">
                    <div className="flex items-center gap-2">
                      <Icon size={16} className={col.color} />
                      <h3 className="font-semibold text-slate-700 dark:text-slate-300">{col.label}</h3>
                      <span className="ml-auto text-xs font-bold px-2 py-0.5 rounded-full bg-slate-200 dark:bg-slate-700 text-slate-600 dark:text-slate-400">
                        {colTasks.length}
                      </span>
                    </div>
                    <div className="space-y-2.5">
                      {colTasks.map(task => (
                        <TaskCard key={task.id} task={task} onStatusChange={updateStatus} onReport={(id, note, sev, photos) => addMaintenanceReport(id, note, sev, photos)} />
                      ))}
                      {colTasks.length === 0 && (
                        <div className="rounded-xl border-2 border-dashed border-slate-200 dark:border-slate-700 py-8 text-center">
                          <p className="text-sm text-slate-400 dark:text-slate-500">Пусто</p>
                        </div>
                      )}
                    </div>
                  </div>
                )
              })}
            </div>
          )}
        </>
      )}

      {/* ── History tab ── */}
      {activeTab === 'history' && (
        <div className="space-y-4">
          {/* Date picker */}
          <div className="flex items-center gap-2">
            <button
              onClick={() => setHistoryDate(format(subDays(parseISO(historyDate), 1), 'yyyy-MM-dd'))}
              className="p-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-500"
            >
              <ChevronLeft size={16} />
            </button>
            <input
              type="date"
              value={historyDate}
              onChange={e => setHistoryDate(e.target.value)}
              className="input text-sm w-auto"
            />
            <button
              onClick={() => setHistoryDate(format(addDays(parseISO(historyDate), 1), 'yyyy-MM-dd'))}
              disabled={historyDate >= format(new Date(), 'yyyy-MM-dd')}
              className="p-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-500 disabled:opacity-30"
            >
              <ChevronRight size={16} />
            </button>
            <span className="text-sm text-slate-500 dark:text-slate-400">
              {format(parseISO(historyDate), 'd MMMM yyyy', { locale: ru })}
            </span>
          </div>

          {historyLoading ? (
            <div className="flex justify-center py-12">
              <Loader2 size={20} className="animate-spin text-brand-600" />
            </div>
          ) : historyTasks.length === 0 ? (
            <div className="text-center py-16 text-slate-400 dark:text-slate-500">
              Завершённых задач за этот день нет
            </div>
          ) : (
            <div className="space-y-2.5">
              {historyTasks.map(task => (
                <HistoryCard key={task.id} task={task} />
              ))}
            </div>
          )}
        </div>
      )}

      {/* ── Plans tab ── */}
      {activeTab === 'plans' && (
        <div className="max-w-2xl space-y-5">
          <div className="card p-4 space-y-3">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Уборка при выезде</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">
                  Автоматически создавать задачу на уборку, как только гость освобождает номер
                </p>
              </div>
              <Toggle on={plans.checkoutAuto} onChange={() => setP('checkoutAuto', !plans.checkoutAuto)} />
            </div>
            {plans.checkoutAuto && (
              <div className="pl-1 space-y-3 border-t border-slate-100 dark:border-slate-700 pt-3">
                <div>
                  <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1.5">Приоритет задачи</label>
                  <div className="flex gap-2">
                    {([['high', 'Срочно'], ['medium', 'Обычный']] as const).map(([v, l]) => (
                      <button
                        key={v}
                        onClick={() => setP('checkoutPriority', v)}
                        className={cn(
                          'px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors',
                          plans.checkoutPriority === v
                            ? v === 'high' ? 'bg-red-500 border-red-500 text-white' : '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',
                        )}
                      >
                        {l}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="flex items-center justify-between">
                  <div>
                    <p className="text-sm text-slate-700 dark:text-slate-300">Инспекция после уборки</p>
                    <p className="text-xs text-slate-500 dark:text-slate-400">Создавать задачу проверки для старшей горничной</p>
                  </div>
                  <Toggle on={plans.checkoutInspection} onChange={() => setP('checkoutInspection', !plans.checkoutInspection)} />
                </div>
              </div>
            )}
          </div>

          <div className="card p-4 space-y-3">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Ежедневная уборка</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Регулярная уборка в номерах с проживающими гостями</p>
              </div>
              <Toggle on={plans.dailyEnabled} onChange={() => setP('dailyEnabled', !plans.dailyEnabled)} />
            </div>
            {plans.dailyEnabled && (
              <div className="pl-1 space-y-3 border-t border-slate-100 dark:border-slate-700 pt-3">
                <div className="grid grid-cols-2 gap-4">
                  <div>
                    <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1.5">Каждые N дней</label>
                    <div className="flex gap-1.5 flex-wrap">
                      {[1, 2, 3, 7].map(n => (
                        <button
                          key={n}
                          onClick={() => setP('dailyIntervalDays', n)}
                          className={cn(
                            'px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors',
                            plans.dailyIntervalDays === n
                              ? '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',
                          )}
                        >
                          {n === 1 ? 'Ежедневно' : `${n} дня`}
                        </button>
                      ))}
                    </div>
                  </div>
                  <div>
                    <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1.5">Начинать с дня заезда №</label>
                    <input
                      type="number" min={1} max={10}
                      className="input w-20 text-sm"
                      value={plans.dailyStartFromDay}
                      onChange={e => setP('dailyStartFromDay', Math.max(1, parseInt(e.target.value) || 1))}
                    />
                    <p className="text-xs text-slate-400 mt-1">Уборка начнётся на {plans.dailyStartFromDay}-й день</p>
                  </div>
                </div>
              </div>
            )}
          </div>

          <div className="card p-4 space-y-3">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Уборка по запросу гостя</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Гость может запросить уборку через QR-код</p>
              </div>
              <Toggle on={plans.onDemandEnabled} onChange={() => setP('onDemandEnabled', !plans.onDemandEnabled)} />
            </div>
            {plans.onDemandEnabled && (
              <div className="pl-1 border-t border-slate-100 dark:border-slate-700 pt-3">
                <label className="block text-xs font-medium text-slate-600 dark:text-slate-400 mb-1.5">Приоритет</label>
                <div className="flex gap-2">
                  {([['high', 'Срочно'], ['medium', 'Обычный'], ['low', 'Низкий']] as const).map(([v, l]) => (
                    <button
                      key={v}
                      onClick={() => setP('onDemandPriority', v)}
                      className={cn(
                        'px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors',
                        plans.onDemandPriority === v
                          ? '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',
                      )}
                    >
                      {l}
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>

          <div className="card p-4 space-y-3">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Генеральная уборка</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Глубокая уборка с чисткой мебели, мытьём окон</p>
              </div>
              <Toggle on={plans.deepCleanEnabled} onChange={() => setP('deepCleanEnabled', !plans.deepCleanEnabled)} />
            </div>
            {plans.deepCleanEnabled && (
              <div className="pl-1 border-t border-slate-100 dark:border-slate-700 pt-3 flex items-center gap-3">
                <label className="text-xs font-medium text-slate-600 dark:text-slate-400 shrink-0">Проводить каждые</label>
                <input
                  type="number" min={1} max={30}
                  className="input w-20 text-sm"
                  value={plans.deepCleanEveryDays}
                  onChange={e => setP('deepCleanEveryDays', Math.max(1, parseInt(e.target.value) || 7))}
                />
                <span className="text-xs text-slate-500 dark:text-slate-400">дней</span>
              </div>
            )}
          </div>

          <div className="card p-4">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Проверка после уборки</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">После завершения любой уборки создавать задачу инспекции</p>
              </div>
              <Toggle on={plans.inspectionAfterClean} onChange={() => setP('inspectionAfterClean', !plans.inspectionAfterClean)} />
            </div>
          </div>

          <div className="card p-4 space-y-3">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Автоназначение горничной</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Автоматически назначать горничную при создании задачи</p>
              </div>
              <Toggle on={plans.autoAssign} onChange={() => setP('autoAssign', !plans.autoAssign)} />
            </div>
            {plans.autoAssign && (
              <div className="border-t border-slate-100 dark:border-slate-700 pt-3 space-y-2">
                <p className="text-xs font-semibold text-slate-700 dark:text-slate-300">Стратегия распределения (обычные задачи)</p>
                <p className="text-[11px] text-slate-400 dark:text-slate-500">Срочные задачи всегда назначаются первой свободной горничной</p>
                <div className="space-y-1.5">
                  {([
                    { value: 'round_robin',   label: 'По кругу',             desc: 'Кому сегодня назначено меньше задач' },
                    { value: 'least_loaded',  label: 'Наименее загруженная', desc: 'У кого сейчас меньше активных задач' },
                    { value: 'first_free',    label: 'Первая свободная',     desc: 'Кто раньше завершила последнюю задачу' },
                  ] as const).map(opt => (
                    <button
                      key={opt.value}
                      onClick={() => setP('autoAssignStrategy', opt.value)}
                      className={cn(
                        'w-full text-left px-3 py-2 rounded-lg border text-xs transition-colors',
                        plans.autoAssignStrategy === opt.value
                          ? 'bg-blue-50 dark:bg-blue-900/20 border-blue-300 dark:border-blue-700 text-blue-700 dark:text-blue-300'
                          : 'bg-white dark:bg-slate-700 border-slate-200 dark:border-slate-600 text-slate-600 dark:text-slate-300 hover:border-blue-200',
                      )}
                    >
                      <span className="font-medium">{opt.label}</span>
                      <span className="text-slate-400 dark:text-slate-500 ml-2">{opt.desc}</span>
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>

          <div className="card p-4">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-semibold text-slate-900 dark:text-slate-100">Обязательное фото при завершении тех. задачи</p>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Технический специалист должен прикрепить фото перед тем как отметить задачу выполненной</p>
              </div>
              <Toggle on={plans.requireCompletionPhoto} onChange={() => setP('requireCompletionPhoto', !plans.requireCompletionPhoto)} />
            </div>
          </div>

          <div className="card p-4 space-y-3">
            <div>
              <p className="font-semibold text-slate-900 dark:text-slate-100">Экстренное закрытие номера</p>
              <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">
                При отчёте о критической поломке (статус «Экстренно!») номер автоматически закрывается для бронирования
              </p>
            </div>
            <div className="flex items-center gap-3 border-t border-slate-100 dark:border-slate-700 pt-3">
              <label className="text-sm text-slate-700 dark:text-slate-300 shrink-0">Закрывать на</label>
              <div className="flex gap-1.5 flex-wrap">
                {[1, 2, 3, 5, 7, 14].map(n => (
                  <button
                    key={n}
                    onClick={() => setP('emergencyCloseDays', n)}
                    className={cn(
                      'px-3 py-1.5 rounded-lg text-xs font-medium border transition-colors',
                      plans.emergencyCloseDays === n
                        ? 'bg-red-600 border-red-600 text-white'
                        : 'bg-white dark:bg-slate-700 border-slate-200 dark:border-slate-600 text-slate-600 dark:text-slate-300',
                    )}
                  >
                    {n === 1 ? '1 день' : n < 5 ? `${n} дня` : `${n} дней`}
                  </button>
                ))}
              </div>
            </div>
          </div>

          <div className="flex justify-end">
            <button onClick={savePlans} disabled={planSaving} className="btn-primary">
              {planSaving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />}
              {planSaved ? 'Сохранено!' : 'Сохранить планы'}
            </button>
          </div>
        </div>
      )}
    </div>
  )
}

const SEVERITY_CONFIG = {
  low:    { label: 'Не срочно',  bg: 'bg-emerald-100 dark:bg-emerald-900/30', text: 'text-emerald-700 dark:text-emerald-300', border: 'border-emerald-200 dark:border-emerald-800', dot: 'bg-emerald-500' },
  medium: { label: 'Средняя',    bg: 'bg-amber-100 dark:bg-amber-900/30',     text: 'text-amber-700 dark:text-amber-300',     border: 'border-amber-200 dark:border-amber-800',   dot: 'bg-amber-500' },
  high:   { label: 'Экстренно!', bg: 'bg-red-100 dark:bg-red-900/30',         text: 'text-red-700 dark:text-red-300',         border: 'border-red-200 dark:border-red-800',       dot: 'bg-red-500' },
}

function TaskCard({ task, onStatusChange, onReport }: {
  task: HousekeepingTask
  onStatusChange: (id: string, status: HousekeepingTask['status'], resolutionNotes?: string) => void
  onReport: (id: string, note: string, severity: 'low' | 'medium' | 'high', photos: string[]) => void
}) {
  const [reportOpen, setReportOpen] = useState(false)
  const [reportText, setReportText] = useState('')
  const [severity, setSeverity] = useState<'low' | 'medium' | 'high'>('medium')
  const [reportPhotos, setReportPhotos] = useState<string[]>([])
  const [photoUploading, setPhotoUploading] = useState(false)
  const photoInputRef = useRef<HTMLInputElement>(null)
  const [completingOpen, setCompletingOpen] = useState(false)
  const [completionComment, setCompletionComment] = useState('')

  const uploadReportPhoto = async (file: File) => {
    setPhotoUploading(true)
    try {
      const url = await api.upload.photo(file, 'tasks')
      setReportPhotos(prev => [...prev, url])
    } catch { /* ignore */ } finally {
      setPhotoUploading(false)
    }
  }

  const submitReport = () => {
    if (!reportText.trim()) return
    onReport(task.id, reportText.trim(), severity, reportPhotos)
    setReportText('')
    setReportPhotos([])
    setReportOpen(false)
  }

  const sev = task.maintenanceSeverity ? SEVERITY_CONFIG[task.maintenanceSeverity] : null
  const taskAny = task as unknown as Record<string, string>

  return (
    <div className={cn(
      'card p-3.5 space-y-2.5 transition-all',
      task.roomBlocked && 'ring-2 ring-red-400 dark:ring-red-600',
    )}>
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-1.5">
          <span className="text-xl font-bold text-slate-900 dark:text-slate-100">
            №{task.roomNumber}
          </span>
          {task.roomBlocked && (
            <span className="flex items-center gap-0.5 text-[10px] font-bold text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/30 px-1.5 py-0.5 rounded">
              <BanIcon size={10} /> Закрыт
            </span>
          )}
        </div>
        <Badge className={PRIORITY_COLORS[task.priority] ?? PRIORITY_COLORS.medium}>
          {PRIORITY_LABELS[task.priority] ?? task.priority}
        </Badge>
      </div>

      <div className="flex gap-1.5 flex-wrap">
        <Badge className={TYPE_COLORS[task.type] ?? TYPE_COLORS.cleaning}>
          {TYPE_LABELS[task.type] ?? task.type}
        </Badge>
        {task.dueDate && (
          <span className="text-[11px] text-slate-400 dark:text-slate-500 self-center">
            до {format(parseISO(task.dueDate), 'd MMM', { locale: ru })}
          </span>
        )}
      </div>

      {task.notes && (
        <p className="text-xs text-slate-500 dark:text-slate-400 bg-slate-50 dark:bg-slate-700/40 rounded-lg p-2">
          {task.notes}
        </p>
      )}

      {task.maintenanceNote && sev && (
        <div className={cn('rounded-lg p-2.5 border space-y-1', sev.bg, sev.border)}>
          <div className="flex items-center gap-1.5">
            <AlertTriangle size={11} className={sev.text} />
            <span className={cn('text-[10px] font-bold uppercase tracking-wide', sev.text)}>{sev.label}</span>
            {task.roomBlocked && (
              <span className={cn('text-[10px] font-semibold ml-auto', sev.text)}>Номер закрыт</span>
            )}
          </div>
          <p className={cn('text-xs', sev.text)}>{task.maintenanceNote}</p>
        </div>
      )}

      {/* Assignee */}
      {(task.assignedToName || taskAny.assigneeName) && (
        <div className="flex items-center gap-1.5 text-xs text-slate-500 dark:text-slate-400">
          <User size={11} />
          <span>{task.assignedToName || taskAny.assigneeName}</span>
        </div>
      )}

      {reportOpen && (
        <div className="border-t border-slate-100 dark:border-slate-700 pt-2.5 space-y-2">
          <div className="flex items-center justify-between">
            <p className="text-xs font-semibold text-slate-700 dark:text-slate-300 flex items-center gap-1">
              <Wrench size={11} /> Сообщить о неисправности
            </p>
            <button onClick={() => setReportOpen(false)} className="text-slate-400 hover:text-slate-600">
              <XIcon size={13} />
            </button>
          </div>
          <div className="flex gap-1.5">
            {(Object.entries(SEVERITY_CONFIG) as [typeof severity, typeof SEVERITY_CONFIG['low']][]).map(([key, cfg]) => (
              <button
                key={key}
                onClick={() => setSeverity(key)}
                className={cn(
                  'flex-1 text-xs py-1.5 rounded-lg font-medium border transition-colors',
                  severity === key
                    ? `${cfg.bg} ${cfg.text} ${cfg.border}`
                    : 'bg-white dark:bg-slate-700 text-slate-500 dark:text-slate-400 border-slate-200 dark:border-slate-600',
                )}
              >
                {cfg.label}
              </button>
            ))}
          </div>
          {severity === 'high' && (
            <p className="text-[11px] text-red-600 dark:text-red-400 flex items-center gap-1 bg-red-50 dark:bg-red-900/20 rounded-lg px-2 py-1.5">
              <AlertTriangle size={11} className="shrink-0" />
              Номер будет закрыт для бронирования до устранения поломки
            </p>
          )}
          <textarea
            autoFocus
            className="w-full text-xs border border-slate-200 dark:border-slate-600 rounded-lg p-2 bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 resize-none focus:outline-none focus:border-orange-400"
            rows={2}
            placeholder="Опишите неисправность..."
            value={reportText}
            onChange={e => setReportText(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter' && e.ctrlKey) submitReport() }}
          />
          {/* Photo upload */}
          <input
            ref={photoInputRef}
            type="file"
            accept="image/*"
            className="hidden"
            onChange={e => { const f = e.target.files?.[0]; if (f) { uploadReportPhoto(f); e.target.value = '' } }}
          />
          <div className="flex flex-wrap gap-1.5 items-center">
            {reportPhotos.map((url, i) => (
              <div key={i} className="relative group">
                <img src={url} alt="" className="w-12 h-12 object-cover rounded border border-slate-200 dark:border-slate-600" />
                <button
                  onClick={() => setReportPhotos(prev => prev.filter((_, j) => j !== i))}
                  className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-red-500 text-white flex items-center justify-center opacity-0 group-hover:opacity-100"
                ><XIcon size={9} /></button>
              </div>
            ))}
            <button
              onClick={() => photoInputRef.current?.click()}
              disabled={photoUploading}
              className="w-12 h-12 rounded border-2 border-dashed border-slate-300 dark:border-slate-600 flex flex-col items-center justify-center gap-0.5 text-slate-400 hover:border-orange-400 hover:text-orange-500 transition-colors text-[10px]"
            >
              {photoUploading ? <Loader2 size={13} className="animate-spin" /> : <Camera size={13} />}
              {!photoUploading && 'Фото'}
            </button>
          </div>
          <button
            onClick={submitReport}
            disabled={!reportText.trim() || photoUploading}
            className={cn(
              'w-full flex items-center justify-center gap-1 text-xs py-1.5 rounded-lg text-white font-medium transition-colors disabled:opacity-40 disabled:cursor-not-allowed',
              severity === 'high' ? 'bg-red-600 hover:bg-red-700' :
              severity === 'medium' ? 'bg-amber-500 hover:bg-amber-600' :
              'bg-emerald-600 hover:bg-emerald-700',
            )}
          >
            <Send size={11} /> Отправить технической службе
          </button>
        </div>
      )}

      {completingOpen && (
        <div className="border-t border-slate-100 dark:border-slate-700 pt-2.5 space-y-2">
          <div className="flex items-center justify-between">
            <p className="text-xs font-semibold text-slate-700 dark:text-slate-300 flex items-center gap-1">
              <CheckCircle2 size={11} className="text-emerald-500" /> Завершение уборки
            </p>
            <button onClick={() => setCompletingOpen(false)} className="text-slate-400 hover:text-slate-600">
              <XIcon size={13} />
            </button>
          </div>
          <textarea
            autoFocus
            className="w-full text-xs border border-slate-200 dark:border-slate-600 rounded-lg p-2 bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 resize-none focus:outline-none focus:border-emerald-400"
            rows={2}
            placeholder="Комментарий (необязательно)..."
            value={completionComment}
            onChange={e => setCompletionComment(e.target.value)}
            onKeyDown={e => {
              if (e.key === 'Enter' && e.ctrlKey) {
                onStatusChange(task.id, 'done', completionComment.trim() || undefined)
                setCompletingOpen(false)
              }
            }}
          />
          <button
            onClick={() => {
              onStatusChange(task.id, 'done', completionComment.trim() || undefined)
              setCompletingOpen(false)
            }}
            className="w-full flex items-center justify-center gap-1 text-xs py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-medium transition-colors"
          >
            <CheckCircle2 size={11} /> Завершить уборку
          </button>
        </div>
      )}

      <div className="flex gap-1.5 pt-1">
        {task.status === 'pending' && (
          <button
            onClick={() => onStatusChange(task.id, 'in_progress')}
            className="flex-1 text-xs py-1.5 rounded-lg bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 font-medium hover:bg-blue-100 dark:hover:bg-blue-900/30 transition-colors"
          >
            Начать
          </button>
        )}
        {task.status === 'in_progress' && !completingOpen && (
          <button
            onClick={() => { setCompletingOpen(true); setReportOpen(false) }}
            className="flex-1 text-xs py-1.5 rounded-lg bg-emerald-50 dark:bg-emerald-900/20 text-emerald-700 dark:text-emerald-300 font-medium hover:bg-emerald-100 dark:hover:bg-emerald-900/30 transition-colors"
          >
            Завершить
          </button>
        )}
        {!reportOpen && !completingOpen && (
          <button
            onClick={() => setReportOpen(true)}
            title="Сообщить о неисправности"
            className={cn(
              'text-xs py-1.5 px-2.5 rounded-lg font-medium transition-colors flex items-center gap-1 shrink-0',
              task.maintenanceNote
                ? `${sev?.bg} ${sev?.text}`
                : 'bg-slate-50 dark:bg-slate-700 text-slate-500 dark:text-slate-400 hover:bg-orange-50 dark:hover:bg-orange-900/20 hover:text-orange-600',
            )}
          >
            <Wrench size={11} />
          </button>
        )}
      </div>
    </div>
  )
}

function HistoryCard({ task }: { task: HousekeepingTask }) {
  const taskAny = task as unknown as Record<string, string>
  const isMaintenance = task.type === 'maintenance' || (taskAny.category === 'maintenance')
  const isActive = task.status === 'pending' || task.status === 'in_progress'

  const completedTime = task.completedAt
    ? new Date(task.completedAt).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })
    : null

  // Duration: started_at → completed_at
  const durationMin = task.startedAt && task.completedAt
    ? Math.round((new Date(task.completedAt).getTime() - new Date(task.startedAt).getTime()) / 60000)
    : null

  const photos = task.photos ?? []

  return (
    <div className={cn('card p-3.5', isMaintenance && 'border-l-4 border-l-orange-400 dark:border-l-orange-500', !isActive && 'opacity-90')}>
      <div className="flex items-start gap-3">
        {isMaintenance
          ? <Wrench size={16} className={cn('shrink-0 mt-0.5', isActive ? 'text-orange-400' : 'text-orange-500')} />
          : <CheckCircle2 size={16} className="text-emerald-500 shrink-0 mt-0.5" />
        }
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="font-semibold text-slate-900 dark:text-slate-100">№{task.roomNumber}</span>
            <Badge className={TYPE_COLORS[task.type] ?? TYPE_COLORS.cleaning}>
              {TYPE_LABELS[task.type] ?? task.type}
            </Badge>
            <Badge className={PRIORITY_COLORS[task.priority] ?? PRIORITY_COLORS.medium}>
              {PRIORITY_LABELS[task.priority] ?? task.priority}
            </Badge>
            {isActive && isMaintenance && (
              <span className="text-[10px] font-semibold px-1.5 py-0.5 rounded bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300">
                {task.status === 'in_progress' ? 'В работе' : 'Ожидает'}
              </span>
            )}
          </div>
          {isActive && isMaintenance && (
            <p className="text-[11px] text-amber-700 dark:text-amber-400 mt-1 flex items-center gap-1">
              <AlertTriangle size={10} className="shrink-0" /> Замечание по номеру — тех. задача не выполнена
            </p>
          )}
          {task.notes && (
            <p className="text-xs text-slate-600 dark:text-slate-300 mt-1.5 bg-slate-50 dark:bg-slate-700/40 rounded-lg px-2 py-1.5">
              {task.notes}
            </p>
          )}
          {task.resolutionNotes && (
            <p className="text-xs text-emerald-700 dark:text-emerald-300 mt-1.5 bg-emerald-50 dark:bg-emerald-900/20 rounded-lg px-2 py-1.5 flex items-start gap-1.5">
              <CheckCircle2 size={11} className="shrink-0 mt-0.5" />
              {task.resolutionNotes}
            </p>
          )}
          <div className="flex items-center gap-3 mt-1.5 text-xs text-slate-500 dark:text-slate-400 flex-wrap">
            {(task.assignedToName || taskAny.assigneeName) && (
              <span className="flex items-center gap-1">
                <User size={11} />
                {task.assignedToName || taskAny.assigneeName}
              </span>
            )}
            {completedTime && (
              <span className="flex items-center gap-1 text-emerald-600 dark:text-emerald-400">
                <CheckCircle2 size={11} />
                {isMaintenance ? 'Выполнено' : 'Завершено'} в {completedTime}
              </span>
            )}
            {durationMin !== null && durationMin > 0 && (
              <span className="flex items-center gap-1 text-slate-400 dark:text-slate-500">
                <Clock size={11} />
                {durationMin < 60
                  ? `${durationMin} мин`
                  : `${Math.floor(durationMin / 60)} ч ${durationMin % 60} мин`}
              </span>
            )}
          </div>
          {photos.length > 0 && (
            <div className="flex flex-wrap gap-1.5 mt-2">
              {photos.map(url => (
                <a key={url} href={url} target="_blank" rel="noreferrer">
                  <img
                    src={url}
                    alt=""
                    className="w-14 h-14 object-cover rounded-lg border border-slate-200 dark:border-slate-600 hover:opacity-80 transition-opacity"
                  />
                </a>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  )
}
