import { useState, useRef, useCallback, useEffect } from "react";
import { supabase } from "@/integrations/supabase/client";
import { saveBillInvoiceToDocuments } from "@/lib/saveBillToDocuments";
import { useToast } from "@/hooks/use-toast";
import { useBoardAssociations } from "@/contexts/BoardAssociationContext";
import { useNavigate } from "react-router-dom";
import { Upload, FileText, Loader2, Sparkles, CheckCircle2, AlertCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert";

function toBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => resolve((r.result as string).split(",")[1]);
    r.onerror = reject;
    r.readAsDataURL(file);
  });
}

type Stage = "idle" | "uploading" | "parsing" | "saving" | "done" | "error";

export default function BoardSubmitInvoicePage() {
  const { toast } = useToast();
  const navigate = useNavigate();
  const { associations, selectedAssociationId, setSelectedAssociationId, loading: assocLoading } =
    useBoardAssociations();

  const [associationId, setAssociationId] = useState<string>("");
  const [file, setFile] = useState<File | null>(null);
  const [stage, setStage] = useState<Stage>("idle");
  const [errorMsg, setErrorMsg] = useState<string>("");
  const [dragOver, setDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (!associationId && selectedAssociationId) setAssociationId(selectedAssociationId);
    if (!associationId && !selectedAssociationId && associations.length === 1) {
      setAssociationId(associations[0].id);
    }
  }, [selectedAssociationId, associations, associationId]);

  const pickFile = (f: File | null) => {
    if (!f) return;
    if (f.type !== "application/pdf") {
      toast({ variant: "destructive", title: "PDF only", description: "Please upload a PDF invoice." });
      return;
    }
    setFile(f);
    setStage("idle");
    setErrorMsg("");
  };

  const handleSubmit = useCallback(async () => {
    if (!file || !associationId) {
      toast({ variant: "destructive", title: "Missing info", description: "Select an association and a PDF invoice." });
      return;
    }

    setStage("uploading");
    setErrorMsg("");

    try {
      // 1. Upload PDF to invoices bucket
      const path = `${Date.now()}_${file.name}`;
      const { data: upData, error: upErr } = await supabase.storage.from("invoices").upload(path, file);
      if (upErr) throw upErr;
      const { data: { publicUrl } } = supabase.storage.from("invoices").getPublicUrl(upData.path);

      // 2. AI parse
      setStage("parsing");
      const pdf_base64 = await toBase64(file);
      const fnUrl = `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/parse-invoice`;
      const res = await fetch(fnUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY}`,
          apikey: import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
        },
        body: JSON.stringify({ pdf_base64, filename: file.name }),
      });
      if (!res.ok) {
        const e = await res.json().catch(() => ({ error: res.statusText }));
        throw new Error(e.error || `Parse failed (${res.status})`);
      }
      const { data: extracted, error: extractErr } = await res.json();
      if (extractErr) throw new Error(extractErr);

      const vendorName = extracted?.vendor_name || "Unknown Vendor";
      const totalAmount = Number(extracted?.total_amount || 0);
      const billDate = extracted?.invoice_date || new Date().toISOString().split("T")[0];
      const dueDate = extracted?.due_date || null;
      const invoiceNumber = extracted?.invoice_number || null;
      const lineItems = extracted?.line_items || [];
      const description =
        (lineItems.map((li: any) => li.description || li.name).filter(Boolean).join("; ")) ||
        extracted?.notes ||
        `Bill from ${vendorName}`;

      // 3. Save invoice + bill
      setStage("saving");
      const { data: userData } = await supabase.auth.getUser();
      const userId = userData?.user?.id || null;

      const { data: invoice, error: invErr } = await supabase
        .from("invoices")
        .insert({
          vendor_name: vendorName,
          invoice_number: invoiceNumber,
          issue_date: extracted?.invoice_date || null,
          due_date: dueDate,
          amount: totalAmount,
          description,
          association_id: associationId,
          status: "pending",
          created_by: userId,
          raw_pdf_url: publicUrl,
          line_items: lineItems,
        })
        .select()
        .single();
      if (invErr) throw invErr;

      const { data: newBill, error: billErr } = await supabase
        .from("bills")
        .insert({
          association_id: associationId,
          description,
          amount: totalAmount,
          bill_date: billDate,
          due_date: dueDate,
          invoice_number: invoiceNumber,
          attachment_url: publicUrl,
          status: "pending",
          created_by: userId,
          notes: vendorName,
          source_invoice_id: invoice.id,
        })
        .select("id")
        .single();
      if (billErr) throw billErr;

      // File invoice PDF into Documents > Vendor Invoices for this association
      saveBillInvoiceToDocuments({
        associationId,
        attachmentUrl: publicUrl,
        vendorName,
        invoiceNumber,
        invoiceDate: extracted?.invoice_date || billDate,
        uploadedBy: userId,
      });

      // 4. Notify staff (admins/managers) that a board member submitted a bill for approval
      try {
        const associationName = associations.find((a) => a.id === associationId)?.name || "an association";
        const { data: staffRoles } = await supabase
          .from("user_roles")
          .select("user_id")
          .in("role", ["admin", "manager"]);
        const uniqueStaffIds = Array.from(
          new Set((staffRoles || []).map((r: any) => r.user_id).filter(Boolean))
        );
        await Promise.allSettled(
          uniqueStaffIds.map((uid: string) =>
            supabase.rpc("insert_notification", {
              p_user_id: uid,
              p_type: "bill_submitted",
              p_title: "Bill Submitted by Board Member",
              p_message: `A board member submitted an invoice from ${vendorName} for ${associationName}.`,
              p_related_item_id: newBill?.id || null,
              p_related_item_type: "bill",
              p_link: `/dashboard/bill-approvals/${newBill?.id || ""}`,
            })
          )
        );
      } catch (nerr) {
        console.error("Failed to notify staff:", nerr);
      }

      setStage("done");
      toast({
        title: "Invoice Submitted",
        description: `${vendorName} — sent for approval.`,
      });

      // Reset for next upload
      setFile(null);
      if (inputRef.current) inputRef.current.value = "";

      // Redirect to bill approvals after a short delay
      setTimeout(() => {
        navigate("/homeowner/board/bill-approvals");
      }, 1200);
    } catch (err: any) {
      console.error("Submit invoice failed:", err);
      setStage("error");
      setErrorMsg(err.message || "Failed to submit invoice.");
      toast({ variant: "destructive", title: "Submission failed", description: err.message });
    }
  }, [file, associationId, associations, navigate, toast]);

  const submitting = stage === "uploading" || stage === "parsing" || stage === "saving";

  return (
    <div className="container mx-auto py-8 px-4 max-w-2xl">
      <div className="mb-6">
        <h1 className="text-3xl font-bold flex items-center gap-2">
          <Sparkles className="h-7 w-7 text-primary" />
          Submit Invoice for Approval
        </h1>
        <p className="text-muted-foreground mt-1">
          Upload a PDF invoice. AI will read the details and route it to staff for approval — no manual entry required.
        </p>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>New Invoice</CardTitle>
          <CardDescription>Choose the association and attach the invoice PDF.</CardDescription>
        </CardHeader>
        <CardContent className="space-y-5">
          {/* Association */}
          <div className="space-y-2">
            <Label>Association</Label>
            <Select
              value={associationId || undefined}
              onValueChange={(v) => {
                setAssociationId(v);
                setSelectedAssociationId(v);
              }}
              disabled={assocLoading || submitting}
            >
              <SelectTrigger>
                <SelectValue placeholder="Select association" />
              </SelectTrigger>
              <SelectContent>
                {associations.map((a) => (
                  <SelectItem key={a.id} value={a.id}>
                    {a.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* Drop zone */}
          <div className="space-y-2">
            <Label>Invoice PDF</Label>
            <div
              onClick={() => !submitting && inputRef.current?.click()}
              onDragOver={(e) => {
                e.preventDefault();
                if (!submitting) setDragOver(true);
              }}
              onDragLeave={() => setDragOver(false)}
              onDrop={(e) => {
                e.preventDefault();
                setDragOver(false);
                if (submitting) return;
                const dropped = Array.from(e.dataTransfer.files).find((f) => f.type === "application/pdf");
                if (dropped) pickFile(dropped);
              }}
              className={`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${
                dragOver ? "border-primary bg-primary/5" : "border-border hover:border-primary/50 hover:bg-muted/30"
              } ${submitting ? "opacity-60 cursor-not-allowed" : ""}`}
            >
              <input
                ref={inputRef}
                type="file"
                accept="application/pdf"
                className="hidden"
                onChange={(e) => pickFile(e.target.files?.[0] || null)}
              />
              {file ? (
                <div className="flex items-center justify-center gap-2 text-foreground">
                  <FileText className="h-5 w-5 text-primary" />
                  <span className="font-medium">{file.name}</span>
                </div>
              ) : (
                <div className="flex flex-col items-center gap-2 text-muted-foreground">
                  <Upload className="h-8 w-8" />
                  <p className="text-sm">Click or drag a PDF invoice here</p>
                </div>
              )}
            </div>
          </div>

          {/* Status */}
          {stage !== "idle" && (
            <Alert variant={stage === "error" ? "destructive" : "default"}>
              <AlertDescription className="flex items-center gap-2">
                {stage === "uploading" && (<><Loader2 className="h-4 w-4 animate-spin" /> Uploading PDF…</>)}
                {stage === "parsing" && (<><Sparkles className="h-4 w-4 animate-pulse" /> AI is reading the invoice…</>)}
                {stage === "saving" && (<><Loader2 className="h-4 w-4 animate-spin" /> Saving & sending for approval…</>)}
                {stage === "done" && (<><CheckCircle2 className="h-4 w-4 text-green-600" /> Submitted! Redirecting to Bill Approvals…</>)}
                {stage === "error" && (<><AlertCircle className="h-4 w-4" /> {errorMsg}</>)}
              </AlertDescription>
            </Alert>
          )}

          <div className="flex justify-end gap-2 pt-2">
            <Button
              variant="outline"
              onClick={() => {
                setFile(null);
                setStage("idle");
                setErrorMsg("");
                if (inputRef.current) inputRef.current.value = "";
              }}
              disabled={submitting}
            >
              Clear
            </Button>
            <Button onClick={handleSubmit} disabled={!file || !associationId || submitting}>
              {submitting ? <Loader2 className="h-4 w-4 mr-2 animate-spin" /> : <Sparkles className="h-4 w-4 mr-2" />}
              Submit for Approval
            </Button>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}
