"use client";

import { useState, useCallback, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/hooks/useAuth";
import { searchEmails, exportMailsZIP, uploadMailFilesUser, getUploadProgressUser, type SearchHit, type UploadJob } from "@/lib/api";
import { Navbar } from "@/components/navbar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardContent } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Progress } from "@/components/ui/progress";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Skeleton } from "@/components/ui/skeleton";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";

const PAGE_SIZE = 25;

function formatBytes(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

export default function SearchPage() {
  const { user, loading: authLoading } = useAuth();
  const router = useRouter();

  const [query, setQuery] = useState("");
  const [fromFilter, setFromFilter] = useState("");
  const [toFilter, setToFilter] = useState("");
  const [dateFrom, setDateFrom] = useState("");
  const [dateTo, setDateTo] = useState("");
  const [sort, setSort] = useState("date_desc");
  const [hasAttachment, setHasAttachment] = useState<boolean | undefined>(undefined);

  const [results, setResults] = useState<SearchHit[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [searching, setSearching] = useState(false);
  const [searched, setSearched] = useState(false);

  // Selection state
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [exportOpen, setExportOpen] = useState(false);
  const [exportAttachments, setExportAttachments] = useState(false);
  const [exporting, setExporting] = useState(false);

  // Upload state
  const [uploadOpen, setUploadOpen] = useState(false);
  const [uploadDragging, setUploadDragging] = useState(false);
  const [uploadJob, setUploadJob] = useState<UploadJob | null>(null);
  const [uploadError, setUploadError] = useState("");
  const [uploadLoading, setUploadLoading] = useState(false);
  const uploadPollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // Clear selection when results change
  useEffect(() => {
    setSelected(new Set());
  }, [results]);

  const doSearch = useCallback(
    async (p: number) => {
      setSearching(true);
      try {
        const res = await searchEmails({
          q: query || undefined,
          from: fromFilter || undefined,
          to: toFilter || undefined,
          date_from: dateFrom || undefined,
          date_to: dateTo || undefined,
          sort: sort !== "date_desc" ? sort : undefined,
          has_attachment: hasAttachment,
          page: p,
          page_size: PAGE_SIZE,
        });
        setResults(res.hits || []);
        setTotal(res.total);
        setPage(p);
        setSearched(true);
      } catch {
        setResults([]);
        setTotal(0);
      } finally {
        setSearching(false);
      }
    },
    [query, fromFilter, toFilter, dateFrom, dateTo, sort, hasAttachment]
  );

  // Alle Mails beim Öffnen der Seite laden — direkt, ohne useCallback-Closure
  useEffect(() => {
    if (!user) return;
    setSearching(true);
    searchEmails({ page: 1, page_size: PAGE_SIZE })
      .then((res) => {
        setResults(res.hits || []);
        setTotal(res.total);
        setPage(1);
        setSearched(true);
      })
      .catch(() => {
        setResults([]);
        setTotal(0);
      })
      .finally(() => setSearching(false));
  }, [user]);

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    doSearch(1);
  }

  async function handleExportZIP() {
    setExporting(true);
    try {
      const { blob } = await exportMailsZIP(Array.from(selected), exportAttachments);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "archivmail-export.zip";
      a.click();
      URL.revokeObjectURL(url);
      setExportOpen(false);
      setSelected(new Set());
    } catch (e) {
      alert(`Export fehlgeschlagen: ${e instanceof Error ? e.message : e}`);
    } finally {
      setExporting(false);
    }
  }

  async function handleUploadFiles(files: FileList | File[]) {
    const allowed = Array.from(files).filter((f) => {
      const n = f.name.toLowerCase();
      return n.endsWith(".eml") || n.endsWith(".mbox");
    });
    if (allowed.length === 0) {
      setUploadError("Nur .eml und .mbox Dateien erlaubt.");
      return;
    }
    setUploadError("");
    setUploadJob(null);
    setUploadLoading(true);
    try {
      const { job_id } = await uploadMailFilesUser(allowed);
      uploadPollRef.current = setInterval(async () => {
        try {
          const job = await getUploadProgressUser(job_id);
          setUploadJob(job);
          if (job.status !== "running") {
            clearInterval(uploadPollRef.current!);
            uploadPollRef.current = null;
            setUploadLoading(false);
            // Refresh search results after successful import
            if (job.status === "done") doSearch(1);
          }
        } catch {
          clearInterval(uploadPollRef.current!);
          uploadPollRef.current = null;
          setUploadLoading(false);
        }
      }, 1500);
    } catch (e) {
      setUploadError(e instanceof Error ? e.message : "Upload fehlgeschlagen.");
      setUploadLoading(false);
    }
  }

  function handleUploadClose() {
    if (uploadPollRef.current) {
      clearInterval(uploadPollRef.current);
      uploadPollRef.current = null;
    }
    setUploadOpen(false);
    setUploadJob(null);
    setUploadError("");
    setUploadLoading(false);
  }

  const totalPages = Math.ceil(total / PAGE_SIZE);
  const allSelected = results.length > 0 && results.every((h) => selected.has(h.id));

  return (
    <div className="min-h-screen">
      <Navbar username={user?.username ?? ""} role={user?.role ?? ""} />
      <main className="mx-auto max-w-7xl px-4 py-6">
        {(authLoading || !user) && (
          <div className="space-y-4">
            <Skeleton className="h-10 w-full" />
            <Skeleton className="h-4 w-2/3" />
            <Skeleton className="h-64 w-full" />
          </div>
        )}
        {!authLoading && user && (<>
        <form onSubmit={handleSubmit} className="space-y-4">
          <div className="flex gap-2">
            <Input
              placeholder="Volltextsuche..."
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              className="flex-1"
              aria-label="Suchbegriff"
            />
            <Button type="submit" disabled={searching}>
              {searching ? "Suche..." : "Suchen"}
            </Button>
            <Button type="button" variant="outline" onClick={() => setUploadOpen(true)}>
              Importieren
            </Button>
          </div>

          <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
            <div className="space-y-1">
              <Label htmlFor="from-filter" className="text-xs">
                Von (Absender)
              </Label>
              <Input
                id="from-filter"
                placeholder="absender@example.com"
                value={fromFilter}
                onChange={(e) => setFromFilter(e.target.value)}
                aria-label="Absender filtern"
              />
            </div>
            <div className="space-y-1">
              <Label htmlFor="to-filter" className="text-xs">
                An (Empfänger)
              </Label>
              <Input
                id="to-filter"
                placeholder="empfaenger@example.com"
                value={toFilter}
                onChange={(e) => setToFilter(e.target.value)}
                aria-label="Empfänger filtern"
              />
            </div>
            <div className="space-y-1">
              <Label htmlFor="date-from" className="text-xs">
                Datum von
              </Label>
              <Input
                id="date-from"
                type="date"
                value={dateFrom}
                onChange={(e) => setDateFrom(e.target.value)}
                aria-label="Datum von"
              />
            </div>
            <div className="space-y-1">
              <Label htmlFor="date-to" className="text-xs">
                Datum bis
              </Label>
              <Input
                id="date-to"
                type="date"
                value={dateTo}
                onChange={(e) => setDateTo(e.target.value)}
                aria-label="Datum bis"
              />
            </div>
          </div>

          <div className="flex flex-wrap items-center gap-4">
            <div className="flex items-center gap-2">
              <Label htmlFor="sort-select" className="text-xs whitespace-nowrap">Sortierung</Label>
              <Select value={sort} onValueChange={setSort}>
                <SelectTrigger id="sort-select" className="h-8 w-40 text-xs">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="date_desc">Datum (neu → alt)</SelectItem>
                  <SelectItem value="date_asc">Datum (alt → neu)</SelectItem>
                  <SelectItem value="relevance">Relevanz</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="flex items-center gap-2">
              <Switch
                id="attach-toggle"
                checked={hasAttachment === true}
                onCheckedChange={(checked) =>
                  setHasAttachment(checked ? true : undefined)
                }
              />
              <Label htmlFor="attach-toggle" className="text-xs cursor-pointer">
                Nur mit Anhang
              </Label>
            </div>
          </div>
        </form>

        <div className="mt-6">
          {searching ? (
            <Card>
              <CardContent className="p-4 space-y-3">
                {Array.from({ length: 5 }).map((_, i) => (
                  <Skeleton key={i} className="h-10 w-full" />
                ))}
              </CardContent>
            </Card>
          ) : searched && results.length === 0 ? (
            <Card>
              <CardContent className="p-8 text-center text-muted-foreground">
                Keine E-Mails gefunden.
              </CardContent>
            </Card>
          ) : results.length > 0 ? (
            <>
              <div className="mb-2 text-sm text-muted-foreground">
                {query || fromFilter || toFilter || dateFrom || dateTo
                  ? `${total} Ergebnis${total !== 1 ? "se" : ""} gefunden`
                  : `${total} E-Mail${total !== 1 ? "s" : ""} im Archiv`}
              </div>

              {selected.size > 0 && (
                <div className="mb-2 flex items-center gap-2">
                  <span className="text-sm text-muted-foreground">{selected.size} ausgewählt</span>
                  <Button size="sm" onClick={() => setExportOpen(true)}>Als ZIP exportieren</Button>
                  <Button size="sm" variant="outline" onClick={() => setSelected(new Set())}>Auswahl aufheben</Button>
                </div>
              )}

              <Card>
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-10">
                        <Checkbox
                          checked={allSelected}
                          onCheckedChange={(checked) => {
                            if (checked) setSelected(new Set(results.map((h) => h.id)));
                            else setSelected(new Set());
                          }}
                          aria-label="Alle auswählen"
                        />
                      </TableHead>
                      <TableHead className="w-32">Datum</TableHead>
                      <TableHead className="w-56">Von</TableHead>
                      <TableHead>Betreff</TableHead>
                      <TableHead className="w-48">An</TableHead>
                      <TableHead className="w-8 text-center" title="Anhang">📎</TableHead>
                      <TableHead className="w-20 text-right">Größe</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {results.map((hit) => (
                      <TableRow
                        key={hit.id}
                        className="cursor-pointer hover:bg-muted/50"
                        onClick={() => router.push(`/mail/${hit.id}`)}
                        role="link"
                        tabIndex={0}
                        onKeyDown={(e) => {
                          if (e.key === "Enter") router.push(`/mail/${hit.id}`);
                        }}
                        aria-label={`E-Mail von ${hit.from || "unbekannt"}: ${hit.subject || "Kein Betreff"}`}
                      >
                        <TableCell onClick={(e) => e.stopPropagation()}>
                          <Checkbox
                            checked={selected.has(hit.id)}
                            onCheckedChange={(checked) => {
                              setSelected((prev) => {
                                const next = new Set(prev);
                                if (checked) next.add(hit.id);
                                else next.delete(hit.id);
                                return next;
                              });
                            }}
                            aria-label="Mail auswählen"
                          />
                        </TableCell>
                        <TableCell className="whitespace-nowrap text-sm text-muted-foreground">
                          {hit.date
                            ? new Date(hit.date).toLocaleDateString("de-DE")
                            : "-"}
                        </TableCell>
                        <TableCell className="max-w-[14rem] truncate text-sm">{hit.from || "-"}</TableCell>
                        <TableCell className="font-medium">{hit.subject || "(kein Betreff)"}</TableCell>
                        <TableCell className="max-w-[12rem] truncate text-sm text-muted-foreground">{hit.to || "-"}</TableCell>
                        <TableCell className="text-center text-sm">
                          {hit.has_attachments ? "📎" : ""}
                        </TableCell>
                        <TableCell className="text-right text-xs text-muted-foreground whitespace-nowrap">
                          {hit.size ? formatBytes(hit.size) : ""}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </Card>

              {totalPages > 1 && (
                <div className="mt-4 flex items-center justify-center gap-2">
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={page <= 1}
                    onClick={() => doSearch(page - 1)}
                  >
                    Zurueck
                  </Button>
                  <span className="text-sm text-muted-foreground">
                    Seite {page} von {totalPages}
                  </span>
                  <Button
                    variant="outline"
                    size="sm"
                    disabled={page >= totalPages}
                    onClick={() => doSearch(page + 1)}
                  >
                    Weiter
                  </Button>
                </div>
              )}
            </>
          ) : null}
        </div>

        <Dialog open={exportOpen} onOpenChange={setExportOpen}>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>E-Mails exportieren</DialogTitle>
              <DialogDescription>
                {selected.size} E-Mail{selected.size !== 1 ? "s" : ""} als ZIP herunterladen
              </DialogDescription>
            </DialogHeader>
            <div className="flex items-center gap-3 py-2">
              <Switch
                id="attachments"
                checked={exportAttachments}
                onCheckedChange={setExportAttachments}
              />
              <Label htmlFor="attachments">Anhänge einschließen</Label>
            </div>
            <DialogFooter>
              <Button variant="outline" onClick={() => setExportOpen(false)}>
                Abbrechen
              </Button>
              <Button onClick={handleExportZIP} disabled={exporting}>
                {exporting ? "Wird exportiert..." : "ZIP herunterladen"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
        {/* Upload Dialog */}
        <Dialog open={uploadOpen} onOpenChange={(open) => { if (!open) handleUploadClose(); else setUploadOpen(true); }}>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>E-Mails importieren</DialogTitle>
              <DialogDescription>
                EML- oder MBOX-Dateien in das Archiv hochladen
              </DialogDescription>
            </DialogHeader>

            {!uploadJob && (
              <div
                className={`flex flex-col items-center justify-center rounded-lg border-2 border-dashed p-8 text-center transition-colors ${
                  uploadDragging ? "border-primary bg-primary/5" : "border-muted-foreground/30"
                }`}
                onDragOver={(e) => { e.preventDefault(); setUploadDragging(true); }}
                onDragLeave={() => setUploadDragging(false)}
                onDrop={(e) => {
                  e.preventDefault();
                  setUploadDragging(false);
                  if (e.dataTransfer.files.length > 0) handleUploadFiles(e.dataTransfer.files);
                }}
              >
                <p className="text-sm text-muted-foreground mb-3">
                  Dateien hierher ziehen oder auswählen
                </p>
                <label>
                  <input
                    type="file"
                    accept=".eml,.mbox"
                    multiple
                    className="hidden"
                    onChange={(e) => { if (e.target.files) handleUploadFiles(e.target.files); }}
                  />
                  <Button type="button" variant="outline" size="sm" asChild>
                    <span>Dateien auswählen</span>
                  </Button>
                </label>
                <p className="mt-2 text-xs text-muted-foreground">.eml · .mbox</p>
              </div>
            )}

            {uploadError && (
              <p className="text-sm text-destructive">{uploadError}</p>
            )}

            {uploadJob && (
              <div className="space-y-3">
                <Progress
                  value={uploadJob.total > 0 ? Math.round(((uploadJob.imported + uploadJob.skipped + uploadJob.errors) / uploadJob.total) * 100) : 0}
                />
                <div className="grid grid-cols-3 gap-2 text-center text-sm">
                  <div>
                    <div className="font-semibold text-green-600">{uploadJob.imported}</div>
                    <div className="text-xs text-muted-foreground">Importiert</div>
                  </div>
                  <div>
                    <div className="font-semibold text-yellow-600">{uploadJob.skipped}</div>
                    <div className="text-xs text-muted-foreground">Duplikate</div>
                  </div>
                  <div>
                    <div className="font-semibold text-red-600">{uploadJob.errors}</div>
                    <div className="text-xs text-muted-foreground">Fehler</div>
                  </div>
                </div>
                {uploadJob.status === "running" && (
                  <p className="text-xs text-center text-muted-foreground">
                    Verarbeite {uploadJob.imported + uploadJob.skipped + uploadJob.errors} / {uploadJob.total} …
                  </p>
                )}
                {uploadJob.status === "done" && (
                  <p className="text-xs text-center text-green-600 font-medium">Abgeschlossen</p>
                )}
              </div>
            )}

            <DialogFooter>
              <Button variant="outline" onClick={handleUploadClose} disabled={uploadLoading && uploadJob?.status === "running"}>
                {uploadJob?.status === "done" ? "Schließen" : "Abbrechen"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
        </>)}
      </main>
    </div>
  );
}
