import { useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/contexts/AuthContext";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import {
  Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,
} from "@/components/ui/dialog";
import { LogOut, Receipt, DollarSign, Anchor, AlertCircle, LogOut as Vacate, CalendarIcon } from "lucide-react";
import { format } from "date-fns";
import { parseLocalDate } from "@/lib/dateUtils";
import acmNavIcon from "@/assets/acm-nav-icon.png";
import { toast } from "sonner";
import { loadStripe } from "@stripe/stripe-js";
import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";

type Rental = {
  id: string;
  association_id: string;
  lot_id: string;
  owner_id: string | null;
  unit_id: string | null;
  renter_name: string;
  monthly_rate: number | null;
  start_date: string;
  status: string;
  is_owner: boolean | null;
};
type LedgerEntry = {
  id: string;
  date: string;
  description: string | null;
  transaction_type: string | null;
  debit: number | null;
  credit: number | null;
};
type IntentRow = {
  id: string;
  vacate_date: string;
  notes: string | null;
  status: string;
  created_at: string;
};

export default function RVRenterPortalPage() {
  const { user, loading: authLoading, signOut } = useAuth();
  const navigate = useNavigate();
  const [loading, setLoading] = useState(true);
  const [rental, setRental] = useState<Rental | null>(null);
  const [associationName, setAssociationName] = useState<string>("");
  const [lotNumber, setLotNumber] = useState<string>("");
  const [entries, setEntries] = useState<LedgerEntry[]>([]);
  const [intents, setIntents] = useState<IntentRow[]>([]);

  // Payment state
  const [payOpen, setPayOpen] = useState(false);
  const [payAmount, setPayAmount] = useState("");
  const [clientSecret, setClientSecret] = useState<string | null>(null);
  const [stripePromise, setStripePromise] = useState<ReturnType<typeof loadStripe> | null>(null);
  const [payLoading, setPayLoading] = useState(false);

  // Intent to Vacate state
  const [itvOpen, setItvOpen] = useState(false);
  const [vacateDate, setVacateDate] = useState("");
  const [vacateNotes, setVacateNotes] = useState("");

  useEffect(() => {
    if (authLoading) return;
    if (!user) { navigate("/auth"); return; }
    void load();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user, authLoading]);

  const load = async () => {
    setLoading(true);
    try {
      let { data: rentalData, error: rentalErr } = await supabase
        .from("rv_boat_lot_rentals")
        .select("id, association_id, lot_id, owner_id, unit_id, renter_name, monthly_rate, start_date, status, is_owner")
        .eq("user_id", user!.id)
        .eq("status", "active")
        .order("start_date", { ascending: false })
        .limit(1)
        .maybeSingle();
      if (rentalErr) throw rentalErr;

      // Fallback: link by email when no user_id was set on the rental yet
      // (renters often don't have an owner record, so they're matched by email)
      if (!rentalData && user?.email) {
        const { data: byEmail } = await supabase
          .from("rv_boat_lot_rentals")
          .select("id, association_id, lot_id, owner_id, unit_id, renter_name, monthly_rate, start_date, status, is_owner")
          .ilike("renter_email", user.email)
          .eq("status", "active")
          .is("user_id", null)
          .order("start_date", { ascending: false })
          .limit(1)
          .maybeSingle();
        if (byEmail) {
          // Backfill the user_id link so subsequent loads are fast
          await supabase
            .from("rv_boat_lot_rentals")
            .update({ user_id: user.id })
            .eq("id", byEmail.id);
          rentalData = byEmail as any;
        }
      }

      setRental(rentalData as Rental | null);

      if (rentalData) {
        const [assocRes, lotRes, ledgerRes, itvRes] = await Promise.all([
          supabase.from("associations").select("name").eq("id", rentalData.association_id).maybeSingle(),
          supabase.from("rv_boat_lots").select("lot_number").eq("id", rentalData.lot_id).maybeSingle(),
          rentalData.owner_id
            ? supabase.from("owner_ledger_entries")
                .select("id, date, description, transaction_type, debit, credit")
                .eq("owner_id", rentalData.owner_id)
                .order("date", { ascending: false })
            : Promise.resolve({ data: [], error: null } as any),
          supabase.from("rv_intent_to_vacate")
            .select("id, vacate_date, notes, status, created_at")
            .eq("rental_id", rentalData.id)
            .order("created_at", { ascending: false }),
        ]);
        setAssociationName(assocRes.data?.name || "");
        setLotNumber(lotRes.data?.lot_number || "");
        setEntries((ledgerRes.data || []) as LedgerEntry[]);
        setIntents((itvRes.data || []) as IntentRow[]);
      }
    } catch (e: any) {
      toast.error(e.message || "Failed to load");
    } finally {
      setLoading(false);
    }
  };

  const balance = useMemo(() => {
    return entries.reduce((sum, e) => sum + (Number(e.debit) || 0) - (Number(e.credit) || 0), 0);
  }, [entries]);

  const isOwner = !!rental?.is_owner;
  const hasPendingIntent = intents.some(i => i.status === "pending");

  const openPayment = () => {
    if (!rental || !rental.owner_id) {
      toast.error("Payments require a linked owner ledger. Please contact management.");
      return;
    }
    setPayAmount(balance > 0 ? balance.toFixed(2) : "");
    setClientSecret(null);
    setPayOpen(true);
  };

  const startPayment = async () => {
    if (!rental || !rental.owner_id) return;
    const amt = parseFloat(payAmount);
    if (!amt || amt <= 0) { toast.error("Enter a valid amount"); return; }
    setPayLoading(true);
    try {
      // Get Stripe public key for this association
      const { data: mapping } = await supabase
        .from("stripe_account_mappings")
        .select("stripe_public_key")
        .eq("association_id", rental.association_id)
        .eq("is_active", true)
        .maybeSingle();
      if (!mapping?.stripe_public_key) {
        throw new Error("Online payments are not configured for this association.");
      }
      setStripePromise(loadStripe(mapping.stripe_public_key));

      const { data, error } = await supabase.functions.invoke("create-payment-intent", {
        body: {
          amount_cents: Math.round(amt * 100),
          association_id: rental.association_id,
          owner_id: rental.owner_id,
          unit_id: rental.unit_id,
          payment_method_type: "card",
          description: `RV/Boat Lot ${lotNumber || ""} payment`,
        },
      });
      if (error) throw new Error(error.message);
      if ((data as any)?.error) throw new Error((data as any).error);
      if (!(data as any)?.clientSecret) throw new Error("Missing client secret.");
      setClientSecret((data as any).clientSecret);
    } catch (e: any) {
      toast.error(e.message || "Failed to start payment");
    } finally {
      setPayLoading(false);
    }
  };

  const submitVacate = async () => {
    if (!rental) return;
    if (!vacateDate) { toast.error("Please choose a vacate date"); return; }
    const { error } = await supabase.from("rv_intent_to_vacate").insert({
      rental_id: rental.id,
      association_id: rental.association_id,
      lot_id: rental.lot_id,
      owner_id: rental.owner_id,
      submitted_by_user_id: user!.id,
      vacate_date: vacateDate,
      notes: vacateNotes || null,
      status: "pending",
    });
    if (error) { toast.error(error.message); return; }
    toast.success("Intent to Vacate submitted. Management has been notified.");
    setItvOpen(false);
    setVacateDate(""); setVacateNotes("");
    void load();
  };

  if (authLoading || loading) {
    return <div className="min-h-screen flex items-center justify-center text-muted-foreground">Loading…</div>;
  }

  if (!rental) {
    return (
      <div className="min-h-screen bg-background flex flex-col">
        <Header onSignOut={() => signOut()} />
        <main className="flex-1 flex items-center justify-center p-6">
          <Card className="max-w-md w-full">
            <CardHeader>
              <CardTitle className="flex items-center gap-2"><AlertCircle className="h-5 w-5" /> No active lot</CardTitle>
              <CardDescription>Your account isn't currently linked to an active RV/Boat lot. Please contact management.</CardDescription>
            </CardHeader>
          </Card>
        </main>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-background flex flex-col">
      <Header onSignOut={() => signOut()} isOwner={isOwner} />
      <main className="flex-1 max-w-5xl w-full mx-auto p-6 space-y-6">
        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <Card>
            <CardHeader className="pb-2">
              <CardDescription>Lot</CardDescription>
              <CardTitle className="flex items-center gap-2"><Anchor className="h-5 w-5" /> {lotNumber || "—"}</CardTitle>
            </CardHeader>
            <CardContent className="text-sm text-muted-foreground">{associationName}</CardContent>
          </Card>
          <Card>
            <CardHeader className="pb-2">
              <CardDescription>Monthly rate</CardDescription>
              <CardTitle>${Number(rental.monthly_rate || 0).toFixed(2)}</CardTitle>
            </CardHeader>
            <CardContent className="text-sm text-muted-foreground">Active since {format(parseLocalDate(rental.start_date), "MMM d, yyyy")}</CardContent>
          </Card>
          <Card>
            <CardHeader className="pb-2">
              <CardDescription>Current balance</CardDescription>
              <CardTitle className={balance > 0 ? "text-destructive" : ""}>${balance.toFixed(2)}</CardTitle>
            </CardHeader>
            <CardContent className="flex flex-wrap gap-2">
              <Button size="sm" onClick={openPayment}>
                <DollarSign className="h-4 w-4 mr-1" /> Pay now
              </Button>
              {isOwner && (
                <Button size="sm" variant="outline" onClick={() => setItvOpen(true)} disabled={hasPendingIntent}>
                  <Vacate className="h-4 w-4 mr-1" /> {hasPendingIntent ? "Intent submitted" : "Intent to Vacate"}
                </Button>
              )}
            </CardContent>
          </Card>
        </div>

        {intents.length > 0 && (
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2"><CalendarIcon className="h-5 w-5" /> Intent to Vacate</CardTitle>
              <CardDescription>Your submitted intents.</CardDescription>
            </CardHeader>
            <CardContent>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Submitted</TableHead>
                    <TableHead>Vacate date</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead>Notes</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {intents.map(i => (
                    <TableRow key={i.id}>
                      <TableCell>{format(new Date(i.created_at), "MMM d, yyyy")}</TableCell>
                      <TableCell>{format(parseLocalDate(i.vacate_date), "MMM d, yyyy")}</TableCell>
                      <TableCell><Badge variant={i.status === "pending" ? "secondary" : "outline"}>{i.status}</Badge></TableCell>
                      <TableCell className="text-sm text-muted-foreground">{i.notes || "—"}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </CardContent>
          </Card>
        )}

        <Card>
          <CardHeader>
            <CardTitle className="flex items-center gap-2"><Receipt className="h-5 w-5" /> Ledger</CardTitle>
            <CardDescription>All charges and payments on your account.</CardDescription>
          </CardHeader>
          <CardContent>
            {entries.length === 0 ? (
              <p className="text-sm text-muted-foreground py-8 text-center">No ledger entries yet.</p>
            ) : (
              <div className="overflow-x-auto">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Date</TableHead>
                      <TableHead>Description</TableHead>
                      <TableHead>Type</TableHead>
                      <TableHead className="text-right">Charge</TableHead>
                      <TableHead className="text-right">Payment</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {entries.map((e) => (
                      <TableRow key={e.id}>
                        <TableCell>{e.date ? format(parseLocalDate(e.date), "MMM d, yyyy") : "—"}</TableCell>
                        <TableCell>{e.description || "—"}</TableCell>
                        <TableCell><Badge variant="outline">{e.transaction_type || "—"}</Badge></TableCell>
                        <TableCell className="text-right">{Number(e.debit) ? `$${Number(e.debit).toFixed(2)}` : ""}</TableCell>
                        <TableCell className="text-right">{Number(e.credit) ? `$${Number(e.credit).toFixed(2)}` : ""}</TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>
            )}
          </CardContent>
        </Card>
      </main>

      {/* Payment Dialog */}
      <Dialog open={payOpen} onOpenChange={(o) => { setPayOpen(o); if (!o) { setClientSecret(null); setStripePromise(null); } }}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Make a Payment</DialogTitle>
            <DialogDescription>Securely pay your balance via Stripe.</DialogDescription>
          </DialogHeader>
          {!clientSecret ? (
            <div className="space-y-4">
              <div>
                <Label>Amount (USD)</Label>
                <Input
                  type="number" step="0.01" min="0.01"
                  value={payAmount}
                  onChange={(e) => setPayAmount(e.target.value)}
                  placeholder="0.00"
                />
              </div>
              <DialogFooter>
                <Button variant="outline" onClick={() => setPayOpen(false)}>Cancel</Button>
                <Button onClick={startPayment} disabled={payLoading}>
                  {payLoading ? "Preparing…" : "Continue"}
                </Button>
              </DialogFooter>
            </div>
          ) : stripePromise ? (
            <Elements stripe={stripePromise} options={{ clientSecret }}>
              <StripePaymentForm
                onSuccess={() => {
                  setPayOpen(false); setClientSecret(null); setStripePromise(null);
                  toast.success("Payment submitted");
                  void load();
                }}
              />
            </Elements>
          ) : null}
        </DialogContent>
      </Dialog>

      {/* Intent to Vacate Dialog */}
      <Dialog open={itvOpen} onOpenChange={setItvOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Intent to Vacate</DialogTitle>
            <DialogDescription>
              Notify management of your intent to vacate this lot. Pick the date you plan to vacate.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div>
              <Label>Vacate date *</Label>
              <Input type="date" value={vacateDate} onChange={(e) => setVacateDate(e.target.value)} min={new Date().toISOString().slice(0, 10)} />
            </div>
            <div>
              <Label>Notes (optional)</Label>
              <Textarea value={vacateNotes} onChange={(e) => setVacateNotes(e.target.value)} rows={3} placeholder="Anything management should know…" />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setItvOpen(false)}>Cancel</Button>
            <Button onClick={submitVacate}>Submit</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

function StripePaymentForm({ onSuccess }: { onSuccess: () => void }) {
  const stripe = useStripe();
  const elements = useElements();
  const [submitting, setSubmitting] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!stripe || !elements) return;
    setSubmitting(true);
    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: { return_url: window.location.href },
      redirect: "if_required",
    });
    setSubmitting(false);
    if (error) {
      toast.error(error.message || "Payment failed");
      return;
    }
    onSuccess();
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <PaymentElement />
      <DialogFooter>
        <Button type="submit" disabled={!stripe || submitting}>
          {submitting ? "Processing…" : "Pay"}
        </Button>
      </DialogFooter>
    </form>
  );
}

function Header({ onSignOut, isOwner }: { onSignOut: () => void; isOwner?: boolean }) {
  return (
    <header className="border-b bg-card">
      <div className="max-w-5xl mx-auto flex items-center justify-between px-6 py-3">
        <div className="flex items-center gap-2">
          <div className="flex h-8 w-8 items-center justify-center rounded-sm bg-foreground overflow-hidden">
            <img src={acmNavIcon} alt="ACM" className="h-5 w-5 object-contain" />
          </div>
          <span className="font-semibold">RV / Boat Lot Portal</span>
          {isOwner && <Badge variant="default" className="ml-2">Owner</Badge>}
        </div>
        <Button variant="ghost" size="sm" onClick={onSignOut}>
          <LogOut className="h-4 w-4 mr-1" /> Sign out
        </Button>
      </div>
    </header>
  );
}
