"use client"

import Link from "next/link"
import { Fragment, useMemo, useState } from "react"
import {
  addDays,
  addWeeks,
  addMonths,
  endOfMonth,
  endOfWeek,
  format,
  isSameDay,
  isSameMonth,
  isToday,
  startOfMonth,
  startOfWeek,
} from "date-fns"
import { ptBR } from "date-fns/locale/pt-BR"
import { ChevronLeft, ChevronRight, CalendarDays, AlertCircle } from "lucide-react"

import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { ScrollArea } from "@/components/ui/scroll-area"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { priorityStyles } from "@/lib/ticket-priority-style"
import type { AgendaCalendarEvent } from "@/lib/agenda-utils"
import { cn } from "@/lib/utils"

type AgendaCalendarViewProps = {
  events: AgendaCalendarEvent[]
  range: { start: Date; end: Date }
}

const weekdayLabels = ["Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"]

const slaColors: Record<AgendaCalendarEvent["slaStatus"], string> = {
  on_track: "border-emerald-200 bg-emerald-50 text-emerald-800",
  at_risk: "border-amber-200 bg-amber-50 text-amber-800",
  breached: "border-rose-200 bg-rose-50 text-rose-800",
  met: "border-primary/20 bg-primary/5 text-primary",
}

export function AgendaCalendarView({ events, range }: AgendaCalendarViewProps) {
  const [viewMode, setViewMode] = useState<"month" | "week">("month")
  const [currentMonth, setCurrentMonth] = useState<Date>(startOfMonth(range.start))
  const [currentWeekStart, setCurrentWeekStart] = useState<Date>(startOfWeek(range.start, { weekStartsOn: 1 }))

  const monthMatrix = useMemo(() => buildCalendarMatrix(currentMonth), [currentMonth])
  const availableYears = useMemo(() => {
    const years = new Set<number>()
    const baseYear = new Date().getFullYear()
    for (let offset = 0; offset <= 5; offset += 1) {
      years.add(baseYear + offset)
    }
    years.add(currentMonth.getFullYear())
    years.add(currentWeekStart.getFullYear())
    events.forEach((event) => {
      years.add(event.start.getFullYear())
      years.add(event.end.getFullYear())
    })
    return Array.from(years).sort((a, b) => a - b)
  }, [currentMonth, currentWeekStart, events])
  const eventsByDay = useMemo(() => {
    const map = new Map<string, AgendaCalendarEvent[]>()
    for (const event of events) {
      const key = format(event.start, "yyyy-MM-dd")
      if (!map.has(key)) {
        map.set(key, [])
      }
      map.get(key)!.push(event)
    }
    for (const value of map.values()) {
      value.sort((a, b) => a.start.getTime() - b.start.getTime())
    }
    return map
  }, [events])

  const weekDays = useMemo(() => {
    const start = currentWeekStart
    return Array.from({ length: 7 }, (_, index) => addDays(start, index))
  }, [currentWeekStart])

  const handlePrev = () => {
    if (viewMode === "month") {
      setCurrentMonth(addMonths(currentMonth, -1))
    } else {
      setCurrentWeekStart(addWeeks(currentWeekStart, -1))
    }
  }

  const handleNext = () => {
    if (viewMode === "month") {
      setCurrentMonth(addMonths(currentMonth, 1))
    } else {
      setCurrentWeekStart(addWeeks(currentWeekStart, 1))
    }
  }

  const handleToday = () => {
    const today = new Date()
    setCurrentMonth(startOfMonth(today))
    setCurrentWeekStart(startOfWeek(today, { weekStartsOn: 1 }))
  }

  const handleSelectMonth = (year: number, monthIndex: number) => {
    const nextMonth = startOfMonth(new Date(year, monthIndex, 1))
    setCurrentMonth(nextMonth)
    setCurrentWeekStart(startOfWeek(nextMonth, { weekStartsOn: 1 }))
  }

  const currentLabel =
    viewMode === "month"
      ? format(currentMonth, "MMMM 'de' yyyy", { locale: ptBR })
      : `${format(currentWeekStart, "d MMM", { locale: ptBR })} – ${format(
          addDays(currentWeekStart, 6),
          "d MMM",
          { locale: ptBR },
        )}`

  return (
    <div className="rounded-2xl border border-border/60 bg-card/70 p-4 shadow-sm">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
        <div className="space-y-1">
          <h3 className="text-lg font-semibold text-foreground">Calendário operacional</h3>
          <p className="text-sm text-muted-foreground">{currentLabel}</p>
        </div>
        <div className="flex flex-wrap items-center gap-3">
          <ToggleGroup
            type="single"
            value={viewMode}
            onValueChange={(value) => value && setViewMode(value as "month" | "week")}
            className="rounded-xl border border-border/70 bg-background/60 p-0.5"
          >
            <ToggleGroupItem value="month" className="rounded-lg px-4 py-2 text-sm font-medium data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
              Mês
            </ToggleGroupItem>
            <ToggleGroupItem value="week" className="rounded-lg px-4 py-2 text-sm font-medium data-[state=on]:bg-primary data-[state=on]:text-primary-foreground">
              Semana
            </ToggleGroupItem>
          </ToggleGroup>
          <div className="flex flex-wrap items-center gap-2 rounded-2xl bg-white/80 px-2 py-1.5 shadow-sm">
            <Button variant="ghost" size="icon" onClick={handlePrev}>
              <ChevronLeft className="size-4" />
            </Button>
            <Button variant="ghost" size="icon" onClick={handleNext}>
              <ChevronRight className="size-4" />
            </Button>
            <Button variant="secondary" onClick={handleToday}>
              Hoje
            </Button>
            <YearPopover years={availableYears} onSelectMonth={handleSelectMonth} />
          </div>
        </div>
      </div>
      {viewMode === "month" ? (
        <MonthView
          monthMatrix={monthMatrix}
          eventsByDay={eventsByDay}
          currentMonth={currentMonth}
        />
      ) : (
        <WeekView weekDays={weekDays} eventsByDay={eventsByDay} />
      )}
      {events.length === 0 ? (
        <div className="mt-6 flex items-center gap-3 rounded-lg border border-dashed border-border/60 bg-background/60 p-4 text-sm text-muted-foreground">
          <AlertCircle className="size-4" />
          Nenhum compromisso previsto para o período filtrado.
        </div>
      ) : null}
    </div>
  )
}

function MonthView({
  monthMatrix,
  eventsByDay,
  currentMonth,
}: {
  monthMatrix: Date[][]
  eventsByDay: Map<string, AgendaCalendarEvent[]>
  currentMonth: Date
}) {
  return (
    <div className="mt-6">
      <div className="grid grid-cols-7 text-center text-xs font-medium text-muted-foreground">
        {weekdayLabels.map((label) => (
          <div key={label} className="pb-2">
            {label}
          </div>
        ))}
      </div>
      <div className="grid grid-cols-7 gap-1 text-sm">
        {monthMatrix.map((week, weekIndex) => (
          <Fragment key={`week-${weekIndex}`}>
            {week.map((day) => {
              const dayKey = format(day, "yyyy-MM-dd")
              const dayEvents = eventsByDay.get(dayKey) ?? []
              const isCurrent = isSameMonth(day, currentMonth)
              return (
                <div
                  key={dayKey}
                  className={cn(
                    "min-h-[110px] rounded-xl border bg-background/70 p-2",
                    isCurrent ? "border-border/80" : "border-border/40 bg-muted/30",
                    isToday(day) ? "ring-2 ring-primary/60" : ""
                  )}
                >
                  <div className="flex items-center justify-between text-xs font-semibold text-foreground">
                    <span className={isCurrent ? "text-foreground" : "text-muted-foreground"}>{day.getDate()}</span>
                    {dayEvents.length > 0 ? (
                      <Badge variant="secondary" className="text-[10px]">
                        {dayEvents.length}
                      </Badge>
                    ) : null}
                  </div>
                  <div className="mt-2 space-y-1">
                    {dayEvents.slice(0, 3).map((event) => (
                      <CalendarEventBadge key={event.id} event={event} />
                    ))}
                    {dayEvents.length > 3 ? (
                      <p className="text-[10px] text-muted-foreground">+{dayEvents.length - 3} mais</p>
                    ) : null}
                  </div>
                </div>
              )
            })}
          </Fragment>
        ))}
      </div>
    </div>
  )
}

function WeekView({
  weekDays,
  eventsByDay,
}: {
  weekDays: Date[]
  eventsByDay: Map<string, AgendaCalendarEvent[]>
}) {
  return (
    <div className="mt-6">
      <div className="grid grid-cols-7 text-center text-xs font-medium text-muted-foreground">
        {weekDays.map((day, index) => (
          <div key={`label-${index}`} className="pb-2">
            {weekdayLabels[index]} <span className="ml-1 font-semibold text-foreground">{day.getDate()}</span>
          </div>
        ))}
      </div>
      <div className="grid grid-cols-7 gap-2 text-sm">
        {weekDays.map((day) => {
          const dayKey = format(day, "yyyy-MM-dd")
          const dayEvents = eventsByDay.get(dayKey) ?? []
          return (
            <div
              key={`week-${dayKey}`}
              className={cn(
                "min-h-[150px] rounded-2xl border border-border/70 bg-background/70 p-3",
                isToday(day) ? "ring-2 ring-primary/60" : ""
              )}
            >
              <div className="space-y-2">
                {dayEvents.length === 0 ? (
                  <p className="text-[11px] text-muted-foreground">Sem eventos</p>
                ) : (
                  dayEvents.map((event) => (
                    <CalendarEventBadge key={event.id} event={event} />
                  ))
                )}
              </div>
            </div>
          )
        })}
      </div>
    </div>
  )
}

function YearPopover({
  years,
  onSelectMonth,
}: {
  years: number[]
  onSelectMonth: (year: number, monthIndex: number) => void
}) {
  const monthLabels = ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
  const sortedYears = years.length > 0 ? years : [new Date().getFullYear()]

  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button
          variant="ghost"
          size="sm"
          className="gap-2 rounded-full border border-slate-200 px-3 text-sm font-medium text-neutral-700 hover:border-slate-300 hover:bg-white"
        >
          Selecionar mês/ano
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-72 p-0" align="end">
        <ScrollArea className="h-64">
          <div className="divide-y divide-slate-100">
            {sortedYears.map((year) => (
              <div key={year} className="px-3 py-2">
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{year}</p>
                <div className="mt-2 grid grid-cols-3 gap-2">
                  {monthLabels.map((label, index) => (
                    <Button
                      key={`${year}-${label}`}
                      variant="outline"
                      size="sm"
                      className="h-8 rounded-full text-xs"
                      onClick={() => onSelectMonth(year, index)}
                    >
                      {label}
                    </Button>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </ScrollArea>
      </PopoverContent>
    </Popover>
  )
}

function CalendarEventBadge({ event }: { event: AgendaCalendarEvent }) {
  const priorityStyle = priorityStyles[event.priority]
  const slaColor = slaColors[event.slaStatus]
  return (
    <Link
      href={event.href}
      prefetch={false}
      className={cn(
        "block rounded-lg border px-1.5 py-1 text-[10px] transition hover:ring-2 hover:ring-primary/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
        slaColor
      )}
      aria-label={`Abrir ticket #${event.reference}`}
    >
      <div className="flex items-center justify-between gap-1">
        <span className="truncate font-semibold">#{event.reference}</span>
        <span className="text-[9px] text-muted-foreground">{format(event.start, "HH:mm")}</span>
      </div>
      <p className="truncate text-[10px] text-foreground">{event.title}</p>
      <div className="mt-0.5 flex flex-wrap items-center gap-1">
        {event.queue ? (
          <Badge variant="outline" className="rounded-full px-1.5 text-[9px]">
            {event.queue}
          </Badge>
        ) : null}
        <Badge className={cn("rounded-full px-1.5 text-[9px]", priorityStyle?.badgeClass ?? "")}>
          {priorityStyle?.label ?? event.priority}
        </Badge>
      </div>
    </Link>
  )
}

function buildCalendarMatrix(currentMonth: Date): Date[][] {
  const start = startOfWeek(startOfMonth(currentMonth), { weekStartsOn: 1 })
  const end = endOfWeek(endOfMonth(currentMonth), { weekStartsOn: 1 })
  const matrix: Date[][] = []
  let cursor = start
  while (cursor <= end) {
    const week: Date[] = []
    for (let i = 0; i < 7; i += 1) {
      week.push(cursor)
      cursor = addDays(cursor, 1)
    }
    matrix.push(week)
  }
  return matrix
}
