import { createFileRoute } from "@tanstack/react-router";
import { invoke } from "@tauri-apps/api/core";
import { open } from "@tauri-apps/plugin-dialog";
import { readTextFile } from "@tauri-apps/plugin-fs";
import { FileUp, Filter, Search } from "lucide-react";
import * as React from "react";

import { AlertList } from "@/components/monitor/alert-list";
import { IncidentManager } from "@/components/monitor/incident-manager";
import { KpiDashboard } from "@/components/monitor/kpi-dashboard";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import type { Incident, KpiMetrics, ProcessedAlert } from "@/lib/types/alerts";

type StatusFilter = "all" | "resolved" | "unresolved";

export const Route = createFileRoute("/monitor")({
  component: MonitorPage,
});

function MonitorPage() {
  const [alerts, setAlerts] = React.useState<ProcessedAlert[]>([]);
  const [incidents, setIncidents] = React.useState<Incident[]>([]);
  const [kpis, setKpis] = React.useState<KpiMetrics | null>(null);
  const [selectedAlert, setSelectedAlert] =
    React.useState<ProcessedAlert | null>(null);
  const [isLoading, setIsLoading] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [searchQuery, setSearchQuery] = React.useState("");
  const [statusFilter, setStatusFilter] = React.useState<StatusFilter>("all");

  const filteredAlerts = React.useMemo(() => {
    return alerts.filter((alert) => {
      if (statusFilter === "resolved" && !alert.isResolved) return false;
      if (statusFilter === "unresolved" && alert.isResolved) return false;

      if (!searchQuery.trim()) return true;

      const query = searchQuery.toLowerCase();
      if (alert.alertName?.toLowerCase().includes(query)) return true;

      for (const value of Object.values(alert.labels)) {
        if (value.toLowerCase().includes(query)) return true;
      }

      return false;
    });
  }, [alerts, searchQuery, statusFilter]);

  const selectAllState = React.useMemo(() => {
    if (filteredAlerts.length === 0) return "none" as const;
    const invalidCount = filteredAlerts.filter((a) => a.isInvalid).length;
    if (invalidCount === 0) return "none" as const;
    if (invalidCount === filteredAlerts.length) return "all" as const;
    return "some" as const;
  }, [filteredAlerts]);

  const recalculateKpis = React.useCallback(
    async (currentAlerts: ProcessedAlert[], currentIncidents: Incident[]) => {
      try {
        const newKpis = await invoke<KpiMetrics>("calculate_kpis_command", {
          alerts: currentAlerts,
          incidents: currentIncidents,
        });
        setKpis(newKpis);
      } catch (err) {
        setError(err instanceof Error ? err.message : String(err));
      }
    },
    [],
  );

  const handleLoadFile = async () => {
    try {
      setIsLoading(true);
      setError(null);

      const filePath = await open({
        multiple: false,
        filters: [{ name: "JSON", extensions: ["json"] }],
      });

      if (!filePath) {
        setIsLoading(false);
        return;
      }

      const content = await readTextFile(filePath);

      const processedAlerts = await invoke<ProcessedAlert[]>(
        "process_alerts_json",
        { jsonContent: content },
      );

      setAlerts(processedAlerts);
      setSelectedAlert(null);
      await recalculateKpis(processedAlerts, incidents);
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setIsLoading(false);
    }
  };

  const handleToggleInvalid = (alertId: number, isInvalid: boolean) => {
    setAlerts((prev) => {
      const updated = prev.map((a) =>
        a.id === alertId ? { ...a, isInvalid } : a,
      );
      recalculateKpis(updated, incidents);
      return updated;
    });

    if (selectedAlert?.id === alertId) {
      setSelectedAlert((prev) => (prev ? { ...prev, isInvalid } : null));
    }
  };

  const handleToggleAllInvalid = (isInvalid: boolean) => {
    const filteredIds = new Set(filteredAlerts.map((a) => a.id));
    setAlerts((prev) => {
      const updated = prev.map((a) =>
        filteredIds.has(a.id) ? { ...a, isInvalid } : a,
      );
      recalculateKpis(updated, incidents);
      return updated;
    });

    if (selectedAlert && filteredIds.has(selectedAlert.id)) {
      setSelectedAlert((prev) => (prev ? { ...prev, isInvalid } : null));
    }
  };

  const handleSelectAlert = (alert: ProcessedAlert) => {
    setSelectedAlert(alert);
  };

  const handleAddIncident = (incident: Omit<Incident, "attachedAlertIds">) => {
    const newIncident: Incident = {
      ...incident,
      attachedAlertIds: [],
    };
    const newIncidents = [...incidents, newIncident];
    setIncidents(newIncidents);
    recalculateKpis(alerts, newIncidents);
  };

  const handleAttachAlert = (alertId: number, incidentId: string) => {
    const updatedAlerts = alerts.map((a) =>
      a.id === alertId ? { ...a, attachedIncidentId: incidentId } : a,
    );
    const updatedIncidents = incidents.map((i) =>
      i.id === incidentId && !i.attachedAlertIds.includes(alertId)
        ? { ...i, attachedAlertIds: [...i.attachedAlertIds, alertId] }
        : i,
    );

    setAlerts(updatedAlerts);
    setIncidents(updatedIncidents);
    recalculateKpis(updatedAlerts, updatedIncidents);

    if (selectedAlert?.id === alertId) {
      setSelectedAlert((prev) =>
        prev ? { ...prev, attachedIncidentId: incidentId } : null,
      );
    }
  };

  const handleDetachAlert = (alertId: number) => {
    const alert = alerts.find((a) => a.id === alertId);
    const incidentId = alert?.attachedIncidentId;

    const updatedAlerts = alerts.map((a) =>
      a.id === alertId ? { ...a, attachedIncidentId: null } : a,
    );
    const updatedIncidents = incidentId
      ? incidents.map((i) =>
          i.id === incidentId
            ? {
                ...i,
                attachedAlertIds: i.attachedAlertIds.filter(
                  (aid) => aid !== alertId,
                ),
              }
            : i,
        )
      : incidents;

    setAlerts(updatedAlerts);
    setIncidents(updatedIncidents);
    recalculateKpis(updatedAlerts, updatedIncidents);

    if (selectedAlert?.id === alertId) {
      setSelectedAlert((prev) =>
        prev ? { ...prev, attachedIncidentId: null } : null,
      );
    }
  };

  return (
    <div className="flex h-screen flex-col overflow-hidden">
      <header className="flex shrink-0 items-center justify-between border-b px-4 py-3">
        <h1 className="text-sm font-semibold">Alert Monitor</h1>
        <Button onClick={handleLoadFile} disabled={isLoading} size="sm">
          <FileUp className="mr-2 size-4" />
          {isLoading ? "Loading..." : "Load Alerts JSON"}
        </Button>
      </header>

      {error && (
        <div className="shrink-0 border-b border-destructive/50 bg-destructive/10 px-4 py-2 text-xs text-destructive">
          {error}
        </div>
      )}

      <div className="shrink-0 border-b p-4">
        <KpiDashboard kpis={kpis} isLoading={isLoading} />
      </div>

      <div className="grid min-h-0 flex-1 grid-cols-[1fr_360px]">
        <div className="flex min-h-0 flex-col border-r">
          <div className="flex shrink-0 items-center gap-2 border-b px-4 py-2">
            <Checkbox
              checked={selectAllState === "all"}
              indeterminate={selectAllState === "some"}
              onCheckedChange={(checked) =>
                handleToggleAllInvalid(checked === true)
              }
              disabled={filteredAlerts.length === 0}
              aria-label="Mark all filtered as invalid"
            />
            <span className="text-xs font-medium text-muted-foreground">
              {filteredAlerts.length}
              {(searchQuery || statusFilter !== "all") && ` / ${alerts.length}`}
            </span>
            <DropdownMenu>
              <DropdownMenuTrigger
                render={
                  <Button variant="ghost" size="sm" className="h-7 gap-1 px-2">
                    <Filter className="size-3" />
                    <span className="text-xs">
                      {statusFilter === "all"
                        ? "All"
                        : statusFilter === "resolved"
                          ? "Resolved"
                          : "Unresolved"}
                    </span>
                  </Button>
                }
              />
              <DropdownMenuContent align="start">
                <DropdownMenuRadioGroup
                  value={statusFilter}
                  onValueChange={(v) => setStatusFilter(v as StatusFilter)}
                >
                  <DropdownMenuRadioItem value="all">All</DropdownMenuRadioItem>
                  <DropdownMenuRadioItem value="resolved">
                    Resolved
                  </DropdownMenuRadioItem>
                  <DropdownMenuRadioItem value="unresolved">
                    Unresolved
                  </DropdownMenuRadioItem>
                </DropdownMenuRadioGroup>
              </DropdownMenuContent>
            </DropdownMenu>
            <div className="relative ml-auto flex-1 max-w-xs">
              <Search className="absolute left-2 top-1/2 size-3 -translate-y-1/2 text-muted-foreground" />
              <Input
                type="text"
                placeholder="Search alerts..."
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                className="h-7 pl-7 text-xs"
              />
            </div>
          </div>
          {alerts.length === 0 ? (
            <div className="flex flex-1 items-center justify-center">
              <Card className="max-w-sm">
                <CardHeader>
                  <CardTitle>No Alerts Loaded</CardTitle>
                </CardHeader>
                <CardContent className="text-xs text-muted-foreground">
                  Click "Load Alerts JSON" to import alert data from a Grafana
                  Alerts API export.
                </CardContent>
              </Card>
            </div>
          ) : (
            <AlertList
              alerts={filteredAlerts}
              incidents={incidents}
              onToggleInvalid={handleToggleInvalid}
              onSelectAlert={handleSelectAlert}
              selectedAlertId={selectedAlert?.id}
              className="flex-1"
            />
          )}
        </div>

        <div className="min-h-0 overflow-hidden">
          <IncidentManager
            incidents={incidents}
            selectedAlert={selectedAlert}
            onAddIncident={handleAddIncident}
            onAttachAlert={handleAttachAlert}
            onDetachAlert={handleDetachAlert}
          />
        </div>
      </div>
    </div>
  );
}
