import { createFileRoute } from "@tanstack/react-router";
import { useEffect, useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { toast } from "sonner";
import { AlertTriangle, Plus, Paperclip, X, FileIcon, Trash2, Search, Pencil } from "lucide-react";
import { useRoles } from "@/hooks/use-roles";

export const Route = createFileRoute("/_authenticated/incidents")({
  ssr: false,
  component: IncidentsPage,
});

type Incident = {
  id: string;
  reporter_id: string;
  title: string;
  description: string;
  severity: string;
  status: string;
  location: string | null;
  occurred_at: string;
  resolution_notes: string | null;
  resolved_at: string | null;
  created_at: string;
  attachments: { path: string; name: string; type: string }[];
};

const SEVERITIES = ["low", "medium", "high", "critical"] as const;
const STATUSES = ["open", "investigating", "resolved", "closed"] as const;

function IncidentsPage() {
  const qc = useQueryClient();
  const { isSupervisor, isAdmin } = useRoles();
  const [me, setMe] = useState<string | null>(null);
  useEffect(() => {
    supabase.auth.getUser().then(({ data }) => setMe(data.user?.id ?? null));
  }, []);
  const [open, setOpen] = useState(false);
  const [form, setForm] = useState({
    title: "",
    description: "",
    severity: "low",
    location: "",
  });
  const [files, setFiles] = useState<File[]>([]);
  const [uploading, setUploading] = useState(false);
  const [search, setSearch] = useState("");
  const [statusFilter, setStatusFilter] = useState<string>("all");
  const [severityFilter, setSeverityFilter] = useState<string>("all");
  const [editing, setEditing] = useState<Incident | null>(null);
  const [editStatus, setEditStatus] = useState<string>("open");
  const [editNotes, setEditNotes] = useState<string>("");

  const { data, isLoading } = useQuery({
    queryKey: ["incident-reports"],
    queryFn: async (): Promise<Incident[]> => {
      const { data, error } = await supabase
        .from("incident_reports")
        .select("id,reporter_id,title,description,severity,status,location,occurred_at,resolution_notes,resolved_at,created_at,attachments")
        .order("created_at", { ascending: false })
        .limit(200);
      if (error) throw error;
      return (data ?? []).map((r) => ({
        ...r,
        attachments: Array.isArray(r.attachments) ? (r.attachments as Incident["attachments"]) : [],
      })) as Incident[];
    },
  });

  useEffect(() => {
    const ch = supabase
      .channel("incident_reports_realtime")
      .on(
        "postgres_changes",
        { event: "*", schema: "public", table: "incident_reports" },
        (payload) => {
          qc.invalidateQueries({ queryKey: ["incident-reports"] });
          if (payload.eventType === "INSERT") {
            const row = payload.new as { title?: string };
            toast.message("New incident reported", { description: row.title });
          }
        },
      )
      .subscribe();
    return () => {
      supabase.removeChannel(ch);
    };
  }, [qc]);

  const create = useMutation({
    mutationFn: async () => {
      const { data: u } = await supabase.auth.getUser();
      if (!u.user) throw new Error("Not authenticated");
      setUploading(true);
      const uploaded: { path: string; name: string; type: string }[] = [];
      try {
        for (const f of files) {
          if (f.size > 10 * 1024 * 1024) throw new Error(`${f.name} exceeds 10MB`);
          const path = `${u.user.id}/${Date.now()}-${f.name.replace(/[^\w.\-]/g, "_")}`;
          const { error: upErr } = await supabase.storage
            .from("incident-attachments")
            .upload(path, f, { contentType: f.type, upsert: false });
          if (upErr) throw upErr;
          uploaded.push({ path, name: f.name, type: f.type });
        }
      } finally {
        setUploading(false);
      }
      const { error } = await supabase.from("incident_reports").insert({
        reporter_id: u.user.id,
        title: form.title,
        description: form.description,
        severity: form.severity,
        location: form.location || null,
        attachments: uploaded,
      });
      if (error) throw error;
    },
    onSuccess: () => {
      toast.success("Incident reported");
      setOpen(false);
      setForm({ title: "", description: "", severity: "low", location: "" });
      setFiles([]);
      qc.invalidateQueries({ queryKey: ["incident-reports"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const updateStatus = useMutation({
    mutationFn: async ({ id, status, notes }: { id: string; status: string; notes: string }) => {
      const { data: u } = await supabase.auth.getUser();
      const isClosed = status === "resolved" || status === "closed";
      const { error } = await supabase
        .from("incident_reports")
        .update({
          status,
          resolution_notes: notes || null,
          resolved_at: isClosed ? new Date().toISOString() : null,
          resolved_by: isClosed ? u.user?.id : null,
        })
        .eq("id", id);
      if (error) throw error;
    },
    onSuccess: () => {
      toast.success("Status updated");
      setEditing(null);
      qc.invalidateQueries({ queryKey: ["incident-reports"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const remove = useMutation({
    mutationFn: async (i: Incident) => {
      if (i.attachments?.length) {
        await supabase.storage
          .from("incident-attachments")
          .remove(i.attachments.map((a) => a.path));
      }
      const { error } = await supabase.from("incident_reports").delete().eq("id", i.id);
      if (error) throw error;
    },
    onSuccess: () => {
      toast.success("Incident deleted");
      qc.invalidateQueries({ queryKey: ["incident-reports"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    return (data ?? []).filter((i) => {
      if (statusFilter !== "all" && i.status !== statusFilter) return false;
      if (severityFilter !== "all" && i.severity !== severityFilter) return false;
      if (q && !`${i.title} ${i.description} ${i.location ?? ""}`.toLowerCase().includes(q))
        return false;
      return true;
    });
  }, [data, search, statusFilter, severityFilter]);

  const severityVariant = (s: string) =>
    s === "critical" || s === "high" ? "destructive" : s === "medium" ? "default" : "secondary";

  const openAttachment = async (path: string) => {
    const { data, error } = await supabase.storage
      .from("incident-attachments")
      .createSignedUrl(path, 60 * 10);
    if (error || !data?.signedUrl) {
      toast.error(error?.message || "Could not open file");
      return;
    }
    window.open(data.signedUrl, "_blank", "noopener,noreferrer");
  };

  const openEdit = (i: Incident) => {
    setEditing(i);
    setEditStatus(i.status);
    setEditNotes(i.resolution_notes ?? "");
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <AlertTriangle className="h-6 w-6 text-amber-600" />
          <h1 className="text-2xl font-bold">Incident Reports</h1>
        </div>
        <Dialog open={open} onOpenChange={setOpen}>
          <DialogTrigger asChild>
            <Button><Plus className="h-4 w-4 mr-1" /> New Report</Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader><DialogTitle>Report Incident</DialogTitle></DialogHeader>
            <div className="space-y-3">
              <div>
                <Label>Title</Label>
                <Input value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} />
              </div>
              <div>
                <Label>Description</Label>
                <Textarea rows={4} value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div>
                  <Label>Severity</Label>
                  <Select value={form.severity} onValueChange={(v) => setForm({ ...form, severity: v })}>
                    <SelectTrigger><SelectValue /></SelectTrigger>
                    <SelectContent>
                      {SEVERITIES.map((s) => <SelectItem key={s} value={s}>{s}</SelectItem>)}
                    </SelectContent>
                  </Select>
                </div>
                <div>
                  <Label>Location</Label>
                  <Input value={form.location} onChange={(e) => setForm({ ...form, location: e.target.value })} />
                </div>
              </div>
              <div>
                <Label>Attachments (photos / files, max 10MB each)</Label>
                <Input
                  type="file"
                  multiple
                  accept="image/*,application/pdf,video/*"
                  onChange={(e) => setFiles(Array.from(e.target.files ?? []))}
                />
                {files.length > 0 && (
                  <ul className="mt-2 space-y-1 text-sm">
                    {files.map((f, i) => (
                      <li key={i} className="flex items-center justify-between gap-2">
                        <span className="truncate flex items-center gap-1">
                          <Paperclip className="h-3 w-3" /> {f.name}
                        </span>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          className="h-6 w-6"
                          onClick={() => setFiles(files.filter((_, j) => j !== i))}
                        >
                          <X className="h-3 w-3" />
                        </Button>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            </div>
            <DialogFooter>
              <Button
                onClick={() => create.mutate()}
                disabled={!form.title || !form.description || create.isPending || uploading}
              >
                {uploading ? "Uploading…" : create.isPending ? "Submitting…" : "Submit"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      </div>

      <div className="flex flex-col sm:flex-row gap-2">
        <div className="relative flex-1">
          <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
          <Input
            placeholder="Search title, description, location…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="pl-8"
          />
        </div>
        <Select value={statusFilter} onValueChange={setStatusFilter}>
          <SelectTrigger className="w-full sm:w-40"><SelectValue /></SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All statuses</SelectItem>
            {STATUSES.map((s) => <SelectItem key={s} value={s}>{s}</SelectItem>)}
          </SelectContent>
        </Select>
        <Select value={severityFilter} onValueChange={setSeverityFilter}>
          <SelectTrigger className="w-full sm:w-40"><SelectValue /></SelectTrigger>
          <SelectContent>
            <SelectItem value="all">All severities</SelectItem>
            {SEVERITIES.map((s) => <SelectItem key={s} value={s}>{s}</SelectItem>)}
          </SelectContent>
        </Select>
      </div>

      {isLoading ? (
        <p className="text-muted-foreground">Loading…</p>
      ) : !filtered.length ? (
        <p className="text-muted-foreground">No incident reports match.</p>
      ) : (
        <div className="grid gap-3">
          {filtered.map((i) => (
            <Card key={i.id}>
              <CardHeader className="pb-2 flex flex-row items-start justify-between gap-2">
                <div className="space-y-1">
                  <CardTitle className="text-base">{i.title}</CardTitle>
                  <div className="flex items-center gap-2 flex-wrap">
                    <Badge variant={severityVariant(i.severity)}>{i.severity}</Badge>
                    <Badge variant={i.status === "resolved" || i.status === "closed" ? "secondary" : "outline"}>
                      {i.status}
                    </Badge>
                    <span className="text-xs text-muted-foreground">
                      {new Date(i.created_at).toLocaleString()}
                    </span>
                  </div>
                </div>
                <div className="flex gap-1 shrink-0">
                  {isSupervisor && (
                    <Button size="sm" variant="outline" onClick={() => openEdit(i)}>
                      <Pencil className="h-4 w-4 mr-1" /> Update
                    </Button>
                  )}
                  {(isAdmin || i.reporter_id === me) && (
                    <Button
                      size="icon"
                      variant="ghost"
                      onClick={() => {
                        if (confirm("Delete this incident?")) remove.mutate(i);
                      }}
                      disabled={remove.isPending}
                      aria-label="Delete"
                    >
                      <Trash2 className="h-4 w-4 text-destructive" />
                    </Button>
                  )}
                </div>
              </CardHeader>
              <CardContent className="text-sm space-y-1">
                <p className="whitespace-pre-wrap">{i.description}</p>
                {i.location && <p className="text-muted-foreground">📍 {i.location}</p>}
                {i.resolution_notes && (
                  <p className="rounded bg-muted/50 px-2 py-1 text-xs">
                    <span className="font-medium">Resolution:</span> {i.resolution_notes}
                  </p>
                )}
                {i.attachments?.length > 0 && (
                  <div className="flex flex-wrap gap-2 pt-2">
                    {i.attachments.map((a, idx) => (
                      <button
                        key={idx}
                        type="button"
                        onClick={() => openAttachment(a.path)}
                        className="inline-flex items-center gap-1 rounded border px-2 py-1 text-xs hover:bg-accent"
                      >
                        <FileIcon className="h-3 w-3" /> {a.name}
                      </button>
                    ))}
                  </div>
                )}
              </CardContent>
            </Card>
          ))}
        </div>
      )}

      <Dialog open={!!editing} onOpenChange={(o) => !o && setEditing(null)}>
        <DialogContent>
          <DialogHeader><DialogTitle>Update Incident</DialogTitle></DialogHeader>
          <div className="space-y-3">
            <div>
              <Label>Status</Label>
              <Select value={editStatus} onValueChange={setEditStatus}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  {STATUSES.map((s) => <SelectItem key={s} value={s}>{s}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label>Resolution notes</Label>
              <Textarea
                rows={4}
                value={editNotes}
                onChange={(e) => setEditNotes(e.target.value)}
                placeholder="What actions were taken?"
              />
            </div>
          </div>
          <DialogFooter>
            <Button
              onClick={() =>
                editing &&
                updateStatus.mutate({ id: editing.id, status: editStatus, notes: editNotes })
              }
              disabled={updateStatus.isPending}
            >
              {updateStatus.isPending ? "Saving…" : "Save"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}