"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useMutation, useQuery } from "convex/react";
import { FunctionReturnType } from "convex/server";
import { MapPin, Pencil, Play, RefreshCcw, Plus } from "lucide-react";

import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
import { campaignFormDefaults } from "@/lib/campaign-form";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { Separator } from "@/components/ui/separator";
import { CampaignFormDialog } from "@/components/campaigns/campaign-form-dialog";

type CampaignsListResult = FunctionReturnType<typeof api.campaigns.list>;
type CampaignRunsListResult = FunctionReturnType<typeof api.runs.list>;
type CampaignRow = NonNullable<CampaignsListResult>[number];
type CampaignRunRow = NonNullable<CampaignRunsListResult>[number];

type RecurrenceLabel = Record<CampaignRow["recurrence"], string>;
type CurrentRunStatusLabel = {
  [key: string]: string;
};

const recurrenceLabel: RecurrenceLabel = {
  manual: "manuell",
  daily: "täglich",
  weekly: "wöchentlich",
  monthly: "monatlich",
};

const statusLabel: CurrentRunStatusLabel = {
  running: "Läuft",
  pending: "Ausstehend",
  succeeded: "Erledigt",
  failed: "Fehlgeschlagen",
  canceled: "Abgebrochen",
  idle: "Leerlauf",
  paused: "Pausiert",
};

const stepLabel: Record<string, string> = {
  campaign_cron_queued: "Cron geplant",
  campaign_cron_skipped: "Cron übersprungen",
  campaign_cron_stale_pending: "Timeout bereinigt",
  lead_discovery: "Lead-Recherche",
};

const dateFormatter = new Intl.DateTimeFormat("de-DE", {
  dateStyle: "short",
  timeStyle: "short",
});

function formatDateTime(value?: number | null): string {
  if (!value) {
    return "Nicht gesetzt";
  }

  return dateFormatter.format(new Date(value));
}

const formPayloadFromCampaign = (campaign?: CampaignRow | null) => {
  if (!campaign) {
    return campaignFormDefaults;
  }

  return {
    status: campaign.status,
    categoryMode: campaign.categoryMode,
    recurrence: campaign.recurrence,
    radiusKm: campaign.radiusKm,
    maxNewLeadsPerRun: campaign.maxNewLeadsPerRun,
    maxAuditsPerRun: campaign.maxAuditsPerRun,
    name: campaign.name,
    category: campaign.category,
    customSearchTerm: campaign.customSearchTerm ?? "",
    postalCode: campaign.postalCode,
  };
};

const formatNiche = (campaign: CampaignRow): string => {
  if (campaign.category !== "Anderes") {
    return campaign.category;
  }

  return campaign.customSearchTerm?.trim()
    ? `${campaign.category}: ${campaign.customSearchTerm}`
    : campaign.category;
};

export function CampaignsBoard() {
  const campaigns = useQuery(api.campaigns.list, { limit: 100 });
  const recentCampaignRuns = useQuery(api.runs.list, {
    limit: 8,
    type: "campaign",
  });
  const createCampaign = useMutation(api.campaigns.create);
  const updateCampaign = useMutation(api.campaigns.update);
  const setStatus = useMutation(api.campaigns.setStatus);
  const requestRun = useMutation(api.campaigns.requestRun);

  const [editingCampaign, setEditingCampaign] = useState<CampaignRow | null>(null);
  const [isFormOpen, setIsFormOpen] = useState(false);
  const [actionBusyId, setActionBusyId] = useState<Id<"campaigns"> | null>(null);
  const [actionLabel, setActionLabel] = useState<string | null>(null);
  const [formError, setFormError] = useState<string | null>(null);
  const [rowError, setRowError] = useState<string | null>(null);
  const actionLabelTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const clearActionLabelTimer = () => {
    if (actionLabelTimerRef.current) {
      clearTimeout(actionLabelTimerRef.current);
      actionLabelTimerRef.current = null;
    }
  };

  const setActionLabelWithTimeout = (
    label: string,
    clearAfterMs = 1200,
  ) => {
    clearActionLabelTimer();
    setActionLabel(label);

    if (clearAfterMs > 0) {
      actionLabelTimerRef.current = setTimeout(() => setActionLabel(null), clearAfterMs);
    }
  };

  useEffect(() => {
    return () => {
      clearActionLabelTimer();
    };
  }, []);

  const campaignsSorted = useMemo(() => {
    if (!campaigns) {
      return [];
    }

    return [...campaigns].sort((a, b) => b.createdAt - a.createdAt);
  }, [campaigns]);

  const visibleRuns = useMemo<CampaignRunRow[]>(() => {
    return recentCampaignRuns ?? [];
  }, [recentCampaignRuns]);

  const closeDialog = () => {
    setEditingCampaign(null);
    setIsFormOpen(false);
    setFormError(null);
  };

  const openCreateDialog = () => {
    setEditingCampaign(null);
    setRowError(null);
    setIsFormOpen(true);
  };

  const openEditDialog = (campaign: CampaignRow) => {
    setEditingCampaign(campaign);
    setRowError(null);
    setIsFormOpen(true);
  };

  const submitCampaign = async (payload: {
    status: CampaignRow["status"];
    categoryMode: CampaignRow["categoryMode"];
    category: string;
    customSearchTerm?: string;
    postalCode: string;
    radiusKm: number;
    maxNewLeadsPerRun: number;
    maxAuditsPerRun: number;
    recurrence: CampaignRow["recurrence"];
    countryCode: "DE";
    country: "Deutschland";
    name: string;
  }) => {
    setActionLabel("Speichere...");
    setFormError(null);
    try {
      if (!editingCampaign) {
        await createCampaign(payload);
      } else {
        await updateCampaign({
          id: editingCampaign._id,
          ...payload,
        });
      }
      setActionLabelWithTimeout("Gespeichert");
      setIsFormOpen(false);
      setEditingCampaign(null);
    } catch {
      setFormError("Speichern fehlgeschlagen.");
      setActionLabelWithTimeout("Fehler", 2000);
    }
  };

  const runCampaign = async (campaign: CampaignRow) => {
    setActionBusyId(campaign._id);
    setRowError(null);
    try {
      await requestRun({ id: campaign._id });
      setActionLabelWithTimeout(`${campaign.name}: Lauf gestartet`);
    } catch {
      setRowError("Kampagne konnte nicht gestartet werden.");
      setActionLabelWithTimeout("Kampagne konnte nicht gestartet werden.", 2400);
    } finally {
      setActionBusyId(null);
    }
  };

  const toggleCampaign = async (campaign: CampaignRow) => {
    const nextStatus = campaign.status === "active" ? "paused" : "active";
    setActionBusyId(campaign._id);
    setRowError(null);
    try {
      await setStatus({ id: campaign._id, status: nextStatus });
      setActionLabelWithTimeout(
        `${campaign.name}: ${nextStatus === "active" ? "Aktiviert" : "Pausiert"}`,
      );
    } catch {
      setRowError("Status konnte nicht geändert werden.");
      setActionLabelWithTimeout("Status konnte nicht geändert werden.", 2400);
    } finally {
      setActionBusyId(null);
    }
  };

  if (campaigns === undefined) {
    return (
      <section className="space-y-3">
        <div className="flex items-center justify-between gap-3">
          <div className="h-7 w-48 rounded-md bg-muted" />
          <div className="h-8 w-24 rounded-md bg-muted" />
        </div>

        <div className="grid gap-3">
          {Array.from({ length: 4 }, (_, index) => (
            <Skeleton className="h-28 rounded-lg" key={index} />
          ))}
        </div>
      </section>
    );
  }

  return (
    <section className="space-y-4">
      <CampaignFormDialog
        campaign={editingCampaign ? formPayloadFromCampaign(editingCampaign) : null}
        open={isFormOpen}
        onOpenChange={closeDialog}
        onSubmit={submitCampaign}
      />

      <div className="flex flex-col gap-3 border-b pb-3 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <p className="text-sm text-muted-foreground">Lokale Kampagnenverwaltung</p>
          <h1 className="mt-2 text-3xl font-semibold tracking-normal">
            Kampagnen
          </h1>
        </div>

        <Button onClick={openCreateDialog} className="justify-start sm:w-auto">
          <Plus className="size-4" />
          Kampagne anlegen
        </Button>
      </div>

      {formError ? <p className="text-sm text-destructive" role="alert">{formError}</p> : null}
      {rowError ? <p className="text-sm text-destructive" role="alert">{rowError}</p> : null}
      {actionLabel ? <p className="text-sm" role="status">{actionLabel}</p> : null}

      {campaignsSorted.length === 0 ? (
        <Card>
          <CardHeader>
            <CardTitle>Keine Kampagnen</CardTitle>
            <CardDescription>
              Lege zuerst eine Kampagne mit Kategorie, PLZ und Limits an.
            </CardDescription>
          </CardHeader>
        </Card>
      ) : (
        <div className="grid gap-3">
          {campaignsSorted.map((campaign) => (
            <Card key={campaign._id}>
              <CardHeader>
                <div className="flex flex-wrap items-start justify-between gap-2">
                  <div className="min-w-0">
                    <CardTitle className="truncate">{campaign.name}</CardTitle>
                    <CardDescription className="truncate">
                      {formatNiche(campaign)}
                    </CardDescription>
                  </div>
                  <Badge
                    variant={campaign.status === "active" ? "default" : "secondary"}
                  >
                    {campaign.status === "active" ? "Aktiv" : "Pausiert"}
                  </Badge>
                </div>
              </CardHeader>

              <CardContent className="grid gap-2 text-sm">
                <div className="flex flex-wrap items-center justify-between gap-3">
                  <div className="inline-flex items-center gap-1 text-muted-foreground">
                    <MapPin className="size-3" />
                    <span>{campaign.postalCode}</span>
                  </div>
                  <span>{campaign.radiusKm} km</span>
                </div>
                <Separator className="bg-border" />
                <div>
                  <p>Cadence: {recurrenceLabel[campaign.recurrence]}</p>
                  <p>
                    Limits: L {campaign.maxNewLeadsPerRun}, A{" "}
                    {campaign.maxAuditsPerRun}
                  </p>
                </div>
                <div>
                  <p className="text-muted-foreground">Letzter Lauf: {formatDateTime(campaign.lastRunAt)}</p>
                  <p className="text-muted-foreground">Nächster Lauf: {formatDateTime(campaign.nextRunAt)}</p>
                  <p className="text-muted-foreground">
                    Run-Status: {statusLabel[campaign.currentRunStatus] ?? campaign.currentRunStatus}
                  </p>
                </div>

                <div className="grid gap-2">
                  <Button
                    variant="outline"
                    onClick={() => openEditDialog(campaign)}
                    disabled={actionBusyId === campaign._id}
                    className="w-full justify-start"
                  >
                    <Pencil className="size-4" />
                    Bearbeiten
                  </Button>
                  <Button
                    variant="outline"
                    onClick={() => toggleCampaign(campaign)}
                    disabled={actionBusyId === campaign._id}
                    className="w-full justify-start"
                  >
                    <RefreshCcw className="size-4" />
                    {campaign.status === "active" ? "Pausieren" : "Fortfahren"}
                  </Button>
                  <Button
                    onClick={() => runCampaign(campaign)}
                    disabled={actionBusyId === campaign._id}
                    className="w-full justify-start"
                  >
                    <Play className="size-4" />
                    Jetzt ausführen
                  </Button>
                </div>
              </CardContent>
            </Card>
          ))}
        </div>
      )}

      <Card>
        <CardHeader>
          <CardTitle>Aktuelle Run-Logs</CardTitle>
          <CardDescription>
            Letzte Kampagnenläufe inklusive Cron-Skips und Fehlerhinweisen.
          </CardDescription>
        </CardHeader>
        <CardContent className="grid gap-2 text-sm">
          {recentCampaignRuns === undefined ? (
            <Skeleton className="h-16 rounded-lg" />
          ) : visibleRuns.length === 0 ? (
            <p className="text-muted-foreground">Noch keine Kampagnenläufe.</p>
          ) : (
            visibleRuns.map((run) => (
              <div className="rounded-md border p-3" key={run._id}>
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <p className="font-medium">
                    {statusLabel[run.status] ?? run.status}
                  </p>
                  <p className="text-xs text-muted-foreground">
                    {formatDateTime(run.updatedAt)}
                  </p>
                </div>
                <p className="mt-1 text-muted-foreground">
                  {stepLabel[run.currentStep ?? ""] ?? run.currentStep ?? "Schritt offen"}
                </p>
                {run.currentStep === "campaign_cron_skipped" ? (
                  <p className="mt-1 text-xs text-muted-foreground">
                    Cron wurde übersprungen, weil bereits ein Agentenlauf aktiv war.
                  </p>
                ) : null}
                {run.errorSummary ? (
                  <p className="mt-1 text-xs text-destructive">
                    {run.errorSummary}
                  </p>
                ) : null}
              </div>
            ))
          )}
        </CardContent>
      </Card>
    </section>
  );
}
