"use client"

import { useCallback, useEffect, useMemo, useState } from "react"
import { toast } from "sonner"
import { formatDistanceToNow } from "date-fns"
import { ptBR } from "date-fns/locale"
import { CalendarClock, Play, Trash2 } from "lucide-react"

import { REPORT_EXPORT_DEFINITIONS, type ReportExportKey } from "@/lib/report-definitions"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
import { MultiValueInput } from "@/components/ui/multi-value-input"
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { Badge } from "@/components/ui/badge"
import { TimePicker } from "@/components/ui/time-picker"

type SerializableRun = {
  id: string
  status: "PENDING" | "RUNNING" | "COMPLETED" | "FAILED"
  startedAt: string
  completedAt: string | null
  error?: string | null
  artifacts: Array<{
    index: number
    key: string
    fileName: string | null
    mimeType: string | null
  }>
}

type SerializableSchedule = {
  id: string
  name: string
  tenantId: string
  reportKeys: ReportExportKey[]
  range: string
  companyId: string | null
  companyName: string | null
  format: string
  frequency: "daily" | "weekly" | "monthly"
  dayOfWeek: number | null
  dayOfMonth: number | null
  hour: number
  minute: number
  timezone: string
  recipients: string[]
  status: "ACTIVE" | "PAUSED"
  lastRunAt: string | null
  nextRunAt: string | null
  runs: SerializableRun[]
}

const RUN_LABELS: Record<SerializableRun["status"], string> = {
  PENDING: "Pendente",
  RUNNING: "Em andamento",
  COMPLETED: "Concluído",
  FAILED: "Falhou",
}

const RUN_VARIANTS: Record<SerializableRun["status"], "default" | "outline" | "destructive"> = {
  PENDING: "outline",
  RUNNING: "outline",
  COMPLETED: "default",
  FAILED: "destructive",
}

function runStatusLabel(status: SerializableRun["status"]) {
  return RUN_LABELS[status] ?? status
}

function runStatusVariant(status: SerializableRun["status"]) {
  return RUN_VARIANTS[status] ?? "outline"
}

type ReportScheduleDrawerProps = {
  open: boolean
  onOpenChange: (open: boolean) => void
  defaultReports?: ReportExportKey[]
  defaultRange?: string
  defaultCompanyId?: string | null
  companyOptions: SearchableComboboxOption[]
}

export function ReportScheduleDrawer({
  open,
  onOpenChange,
  defaultReports = [],
  defaultRange = "30d",
  defaultCompanyId = null,
  companyOptions,
}: ReportScheduleDrawerProps) {
  const [name, setName] = useState("")
  const [selectedReports, setSelectedReports] = useState<ReportExportKey[]>(defaultReports)
  const [range, setRange] = useState(defaultRange)
  const [companyId, setCompanyId] = useState<string | null>(defaultCompanyId)
  const [companyName, setCompanyName] = useState("")
  const [frequency, setFrequency] = useState<"daily" | "weekly" | "monthly">("weekly")
  const [dayOfWeek, setDayOfWeek] = useState<number | null>(1)
  const [dayOfMonth, setDayOfMonth] = useState<number | null>(null)
  const [time, setTime] = useState("08:00")
  const [recipients, setRecipients] = useState<string[]>([])
  const [isSaving, setIsSaving] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [schedules, setSchedules] = useState<SerializableSchedule[]>([])

  const normalizedCompanyOptions = useMemo<SearchableComboboxOption[]>(() => {
    const deduped = new Map<string, SearchableComboboxOption>()
    companyOptions.forEach((option) => {
      if (!deduped.has(option.value)) {
        deduped.set(option.value, option)
      }
    })
    const hasAll = deduped.has("all")
    const baseLabel = hasAll ? deduped.get("all")?.label ?? "Todas as empresas" : "Todas as empresas"
    const filtered = Array.from(deduped.values()).filter((option) => option.value !== "all")
    return [{ value: "all", label: baseLabel }, ...filtered]
  }, [companyOptions])

  const loadSchedules = useCallback(async () => {
    setIsLoading(true)
    try {
      const response = await fetch("/api/reports/schedules", { cache: "no-store" })
      if (!response.ok) throw new Error("Falha ao carregar agendamentos")
      const data = (await response.json()) as { items: SerializableSchedule[] }
      setSchedules(data.items ?? [])
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível carregar os agendamentos.")
    } finally {
      setIsLoading(false)
    }
  }, [])

  useEffect(() => {
    if (open) {
      void loadSchedules()
      setSelectedReports(defaultReports.length ? defaultReports : [])
      setCompanyId(defaultCompanyId)
    }
  }, [open, loadSchedules, defaultReports, defaultCompanyId])

  useEffect(() => {
    if (!companyId) {
      setCompanyName("")
    }
  }, [companyId])

  const resetForm = useCallback(() => {
    setName("")
    setSelectedReports(defaultReports.length ? defaultReports : [])
    setRange(defaultRange)
    setCompanyId(defaultCompanyId)
    setCompanyName("")
    setFrequency("weekly")
    setDayOfWeek(1)
    setDayOfMonth(null)
    setTime("08:00")
    setRecipients([])
  }, [defaultReports, defaultRange, defaultCompanyId])

  const canSubmit = name.trim().length > 2 && selectedReports.length > 0 && recipients.length > 0

  const handleCreate = useCallback(async () => {
    if (!canSubmit) return
    setIsSaving(true)
    try {
      const response = await fetch("/api/reports/schedules", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          reportKeys: selectedReports,
          range,
          companyId,
          companyName: companyName.trim() || null,
          frequency,
          dayOfWeek,
          dayOfMonth,
          time,
          recipients,
        }),
      })
      if (!response.ok) {
        const payload = await response.json().catch(() => null)
        throw new Error(payload?.error ?? "Falha ao criar agendamento")
      }
      await loadSchedules()
      resetForm()
      toast.success("Agendamento criado com sucesso.")
    } catch (error) {
      console.error(error)
      toast.error(error instanceof Error ? error.message : "Erro ao criar agendamento")
    } finally {
      setIsSaving(false)
    }
  }, [
    canSubmit,
    name,
    selectedReports,
    range,
    companyId,
    companyName,
    frequency,
    dayOfWeek,
    dayOfMonth,
    time,
    recipients,
    loadSchedules,
    resetForm,
  ])

  const toggleReport = (key: ReportExportKey) => {
    setSelectedReports((current) =>
      current.includes(key) ? current.filter((item) => item !== key) : [...current, key]
    )
  }

  const handleDelete = async (id: string) => {
    if (!confirm("Deseja excluir este agendamento?")) return
    try {
      const response = await fetch(`/api/reports/schedules/${id}`, { method: "DELETE" })
      if (!response.ok) throw new Error()
      setSchedules((items) => items.filter((item) => item.id !== id))
      toast.success("Agendamento removido.")
    } catch {
      toast.error("Não foi possível remover o agendamento.")
    }
  }

  const handleToggleStatus = async (schedule: SerializableSchedule) => {
    const nextStatus = schedule.status === "ACTIVE" ? "PAUSED" : "ACTIVE"
    try {
      const response = await fetch(`/api/reports/schedules/${schedule.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ status: nextStatus }),
      })
      if (!response.ok) throw new Error()
      await loadSchedules()
      toast.success(`Agendamento ${nextStatus === "ACTIVE" ? "reativado" : "pausado"}.`)
    } catch {
      toast.error("Não foi possível atualizar o agendamento.")
    }
  }

  const handleRunNow = async (id: string) => {
    toast.loading("Gerando relatórios...", { id: `run-${id}` })
    try {
      const response = await fetch("/api/reports/schedules/run", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ scheduleId: id }),
      })
      if (!response.ok) throw new Error()
      toast.success("Execução iniciada. Você receberá um e-mail assim que finalizar.", {
        id: `run-${id}`,
      })
      await loadSchedules()
    } catch {
      toast.error("Não foi possível iniciar a execução.", { id: `run-${id}` })
    }
  }

  const nextRunLabel = useCallback((schedule: SerializableSchedule) => {
    if (!schedule.nextRunAt) return "Sem previsão"
    return formatDistanceToNow(new Date(schedule.nextRunAt), { addSuffix: true, locale: ptBR })
  }, [])

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="flex w-full flex-col gap-6 overflow-y-auto p-0 sm:max-w-3xl">
        <div className="space-y-6 px-6 py-6">
          <SheetHeader>
            <SheetTitle>Agendar exportação</SheetTitle>
            <SheetDescription>
              Configure a periodicidade dos relatórios e defina quem receberá os arquivos automaticamente.
            </SheetDescription>
          </SheetHeader>
          <div className="space-y-4 rounded-2xl border border-border/60 bg-muted/30 p-4">
            <div className="space-y-2">
              <Label htmlFor="schedule-name">Nome</Label>
              <Input
                id="schedule-name"
                value={name}
                onChange={(event) => setName(event.target.value)}
                placeholder="Ex.: Horas semanais clientes A/B"
              />
            </div>
            <div className="space-y-2">
              <Label>Relatórios incluídos</Label>
              <div className="flex flex-wrap gap-2">
                {Object.entries(REPORT_EXPORT_DEFINITIONS).map(([key, meta]) => {
                  const typedKey = key as ReportExportKey
                  const active = selectedReports.includes(typedKey)
                  return (
                    <button
                      type="button"
                      key={key}
                      onClick={() => toggleReport(typedKey)}
                      className={`rounded-2xl border px-3 py-2 text-left text-sm ${
                        active
                          ? "border-primary bg-primary/10 text-foreground"
                          : "border-border/70 bg-white text-muted-foreground"
                      }`}
                    >
                      <div className="font-semibold">{meta.label}</div>
                      <div className="text-xs text-muted-foreground">{meta.description}</div>
                    </button>
                  )
                })}
              </div>
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              <div className="space-y-2">
                <Label>Período padrão</Label>
                <Select value={range} onValueChange={setRange}>
                  <SelectTrigger>
                    <SelectValue placeholder="Selecione" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="7d">Últimos 7 dias</SelectItem>
                    <SelectItem value="30d">Últimos 30 dias</SelectItem>
                    <SelectItem value="90d">Últimos 90 dias</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-2">
                <Label>Empresa (opcional)</Label>
                <SearchableCombobox
                  value={companyId ?? "all"}
                  onValueChange={(next) => setCompanyId(next && next !== "all" ? next : null)}
                  options={normalizedCompanyOptions}
                  placeholder="Todas as empresas"
                />
                {companyId ? (
                  <Input
                    value={companyName}
                    onChange={(event) => setCompanyName(event.target.value)}
                    placeholder="Nome amigável para o relatório"
                  />
                ) : null}
              </div>
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              <div className="space-y-2">
                <Label>Frequência</Label>
                <Select
                  value={frequency}
                  onValueChange={(value) => setFrequency(value as "daily" | "weekly" | "monthly")}
                >
                  <SelectTrigger>
                    <SelectValue placeholder="Selecione" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="daily">Diária</SelectItem>
                    <SelectItem value="weekly">Semanal</SelectItem>
                    <SelectItem value="monthly">Mensal</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              {frequency === "weekly" ? (
                <div className="space-y-2">
                  <Label>Dia da semana</Label>
                  <Select
                    value={String(dayOfWeek ?? 1)}
                    onValueChange={(value) => setDayOfWeek(Number(value))}
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Selecione" />
                    </SelectTrigger>
                    <SelectContent>
                      {["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"].map(
                        (label, index) => (
                          <SelectItem key={label} value={String(index)}>
                            {label}
                          </SelectItem>
                        )
                      )}
                    </SelectContent>
                  </Select>
                </div>
              ) : frequency === "monthly" ? (
                <div className="space-y-2">
                  <Label>Dia do mês</Label>
                  <Input
                    type="number"
                    min={1}
                    max={28}
                    value={dayOfMonth ?? ""}
                    onChange={(event) => setDayOfMonth(Number(event.target.value) || 1)}
                  />
                </div>
              ) : null}
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              <div className="space-y-2">
                <Label>Horário (HH:MM)</Label>
                <TimePicker value={time} onChange={setTime} />
              </div>
              <div className="space-y-2">
                <Label>Destinatários (emails)</Label>
                <MultiValueInput
                  placeholder="exemplo@empresa.com"
                  values={recipients}
                  onChange={setRecipients}
                />
              </div>
            </div>
            <Button disabled={!canSubmit || isSaving} onClick={handleCreate}>
              {isSaving ? "Salvando..." : "Salvar agendamento"}
            </Button>
          </div>

          <div className="space-y-3">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-semibold text-muted-foreground">Agendamentos ativos</h3>
                <Button
                  variant="ghost"
                  size="sm"
                  className="border border-border/60"
                  onClick={() => loadSchedules()}
                  disabled={isLoading}
                >
                  Atualizar
                </Button>
              </div>
            {schedules.length === 0 ? (
              <div className="rounded-2xl border border-dashed border-border/60 bg-muted/30 px-4 py-6 text-center text-sm text-muted-foreground">
                Nenhum agendamento criado ainda.
              </div>
            ) : (
              <div className="space-y-3">
                {schedules.map((schedule) => (
                  <div
                    key={schedule.id}
                    className="rounded-2xl border border-border/60 bg-white px-4 py-3 shadow-sm"
                  >
                    <div className="flex flex-wrap items-center justify-between gap-2">
                      <div>
                        <p className="text-sm font-semibold text-neutral-900">{schedule.name}</p>
                        <p className="text-xs text-neutral-500">
                          Próxima execução {nextRunLabel(schedule)}
                        </p>
                      </div>
                      <div className="flex items-center gap-2">
                        <Badge variant={schedule.status === "ACTIVE" ? "default" : "outline"}>
                          {schedule.status === "ACTIVE" ? "Ativo" : "Pausado"}
                        </Badge>
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={() => handleRunNow(schedule.id)}
                          title="Executar agora"
                        >
                          <Play className="size-4" />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={() => handleToggleStatus(schedule)}
                          title={schedule.status === "ACTIVE" ? "Pausar" : "Retomar"}
                        >
                          <CalendarClock className="size-4" />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon"
                          onClick={() => handleDelete(schedule.id)}
                          title="Excluir"
                        >
                          <Trash2 className="size-4 text-destructive" />
                        </Button>
                      </div>
                    </div>
                    <div className="mt-2 flex flex-wrap gap-2 text-xs text-muted-foreground">
                      {schedule.reportKeys.map((key) => (
                        <Badge key={key} variant="outline">
                          {REPORT_EXPORT_DEFINITIONS[key]?.label ?? key}
                        </Badge>
                      ))}
                      <span>• Período: {schedule.range}</span>
                      {schedule.companyName ? (
                        <span>• Empresa: {schedule.companyName}</span>
                      ) : null}
                      <span>
                        • Próxima execução às {String(schedule.hour).padStart(2, "0")}:
                        {String(schedule.minute).padStart(2, "0")}
                      </span>
                    </div>
                    <div className="mt-3 space-y-2 border-t border-border/60 pt-3">
                      <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                        Execuções recentes
                      </p>
                      {schedule.runs?.length ? (
                        schedule.runs.slice(0, 3).map((run) => (
                          <div
                            key={run.id}
                            className="rounded-xl border border-border/50 bg-muted/30 px-3 py-2 text-xs text-neutral-600"
                          >
                            <div className="flex flex-wrap items-center gap-2">
                              <Badge variant={runStatusVariant(run.status)}>{runStatusLabel(run.status)}</Badge>
                              <span className="text-[11px] text-neutral-500">
                                {formatDistanceToNow(
                                  new Date(run.completedAt ?? run.startedAt),
                                  { addSuffix: true, locale: ptBR }
                                )}
                              </span>
                              {run.error ? (
                                <span className="text-[11px] text-destructive">Erro: {run.error}</span>
                              ) : null}
                            </div>
                            {run.artifacts?.length ? (
                              <div className="mt-2 flex flex-wrap gap-2">
                                {run.artifacts.map((artifact) => (
                                  <Button
                                    key={`${run.id}-${artifact.index}`}
                                    variant="ghost"
                                    size="sm"
                                    asChild
                                  >
                                    <a
                                      href={`/api/reports/schedules/runs/${run.id}?artifact=${artifact.index}`}
                                      target="_blank"
                                      rel="noreferrer"
                                    >
                                      {artifact.fileName ?? `Arquivo ${artifact.index + 1}`}
                                    </a>
                                  </Button>
                                ))}
                              </div>
                            ) : null}
                          </div>
                        ))
                      ) : (
                        <p className="text-[11px] text-neutral-500">Nenhuma execução registrada ainda.</p>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
        <SheetFooter className="border-t border-border/60 px-6 py-4">
          <Button variant="ghost" onClick={() => onOpenChange(false)}>
            Fechar
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  )
}
