import { useEffect, useState, useCallback } from 'react'
import { ChevronLeft, ChevronRight, Plus } from 'lucide-react'
import type { Calendar, EventSummary } from '../types'
import { can } from '../types'
import { useAuth } from '../components/AuthGate'
import { fetchCalendars, fetchEvents } from '../api'
import CalendarToggleList from '../components/CalendarToggleList'
import ViewSwitcher, { type CalendarViewKey } from '../components/ViewSwitcher'
import EventForm from '../components/EventForm'
import MonthGrid from '../components/views/MonthGrid'
import WeekGrid from '../components/views/WeekGrid'
import DayGrid from '../components/views/DayGrid'
import AgendaList from '../components/views/AgendaList'
import {
  addDays, addMonths, monthGridDays, startOfWeek, toISODate,
  formatMonthLabel, formatWeekLabel, formatDateLabel,
} from '../dateUtils'

function rangeFor(view: CalendarViewKey, date: Date): { from: Date; to: Date } {
  if (view === 'month') {
    const days = monthGridDays(date)
    return { from: days[0], to: days[days.length - 1] }
  }
  if (view === 'week') {
    const start = startOfWeek(date)
    return { from: start, to: addDays(start, 6) }
  }
  if (view === 'day') {
    return { from: date, to: date }
  }
  // list/agenda — rolling 30-day window from the current date
  return { from: date, to: addDays(date, 30) }
}

function labelFor(view: CalendarViewKey, date: Date): string {
  if (view === 'month') return formatMonthLabel(date)
  if (view === 'week') return formatWeekLabel(date)
  if (view === 'day') return formatDateLabel(date)
  return `Next 30 days from ${formatDateLabel(date)}`
}

function shiftDate(view: CalendarViewKey, date: Date, dir: 1 | -1): Date {
  if (view === 'month') return addMonths(date, dir)
  if (view === 'week') return addDays(date, 7 * dir)
  return addDays(date, dir)
}

export default function CalendarView() {
  const { user } = useAuth()
  const [view, setView] = useState<CalendarViewKey>('month')
  const [currentDate, setCurrentDate] = useState(new Date())
  const [calendars, setCalendars] = useState<Calendar[]>([])
  const [visibleIds, setVisibleIds] = useState<Set<number>>(new Set())
  const [events, setEvents] = useState<EventSummary[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  const [formState, setFormState] = useState<{ open: boolean; eventId?: number; initialDate?: Date }>({ open: false })

  useEffect(() => {
    fetchCalendars().then(cals => {
      setCalendars(cals)
      setVisibleIds(new Set(cals.map(c => c.id)))
    }).catch(err => setError(err.message))
  }, [])

  const reload = useCallback(() => {
    const { from, to } = rangeFor(view, currentDate)
    setLoading(true)
    setError(null)
    fetchEvents({ from: toISODate(from), to: toISODate(to) })
      .then(setEvents)
      .catch(err => setError(err.message))
      .finally(() => setLoading(false))
  }, [view, currentDate])

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

  function toggleCalendar(id: number) {
    setVisibleIds(prev => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const visibleEvents = events.filter(ev => visibleIds.has(ev.calendar_id))

  function openCreate(date: Date) {
    if (!can(user, 'create')) return
    setFormState({ open: true, initialDate: date })
  }
  function openEdit(id: number) {
    setFormState({ open: true, eventId: id })
  }
  function closeForm() {
    setFormState({ open: false })
  }

  const viewProps = {
    events: visibleEvents,
    date: currentDate,
    onSelectDate: openCreate,
    onSelectEvent: openEdit,
  }

  return (
    <div className="page" style={{ maxWidth: 1300 }}>
      <div className="page-header">
        <h1>Calendar</h1>
        {can(user, 'create') && (
          <button className="btn btn-primary" onClick={() => openCreate(currentDate)}>
            <Plus size={14} strokeWidth={1.75} />
            New event
          </button>
        )}
      </div>

      {error && <div className="error-banner">{error}</div>}

      <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>
        <div className="card" style={{ width: 220, flexShrink: 0 }}>
          <div className="section-title" style={{ marginTop: 0 }}>Calendars</div>
          <CalendarToggleList calendars={calendars} visibleIds={visibleIds} onToggle={toggleCalendar} />
        </div>

        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="filter-row" style={{ marginBottom: 12, alignItems: 'center' }}>
            <button className="btn btn-sm" onClick={() => setCurrentDate(shiftDate(view, currentDate, -1))}>
              <ChevronLeft size={14} strokeWidth={1.75} />
            </button>
            <button className="btn btn-sm" onClick={() => setCurrentDate(new Date())}>Today</button>
            <button className="btn btn-sm" onClick={() => setCurrentDate(shiftDate(view, currentDate, 1))}>
              <ChevronRight size={14} strokeWidth={1.75} />
            </button>
            <div style={{ fontWeight: 600, fontSize: 14, flex: 1 }}>{labelFor(view, currentDate)}</div>
            <ViewSwitcher view={view} onChange={setView} />
          </div>

          {loading ? (
            <div className="empty-state">Loading…</div>
          ) : view === 'month' ? (
            <MonthGrid {...viewProps} />
          ) : view === 'week' ? (
            <WeekGrid {...viewProps} />
          ) : view === 'day' ? (
            <DayGrid {...viewProps} />
          ) : (
            <AgendaList {...viewProps} />
          )}
        </div>
      </div>

      {formState.open && (
        <EventForm
          eventId={formState.eventId}
          initialDate={formState.initialDate}
          onClose={closeForm}
          onSaved={reload}
        />
      )}
    </div>
  )
}
