import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
import { LogOut, Star, Shield } from "lucide-react";
import { AppShell } from "@/components/AppShell";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/lib/use-auth";
import type { TablesInsert, TablesUpdate } from "@/integrations/supabase/types";

export const Route = createFileRoute("/_authenticated/dashboard")({
  head: () => ({
    meta: [
      { title: "My account | Emma Mold Inspection Services" },
      { name: "description", content: "Track your bookings, saved AI checks, quotations and inspection reports." },
      { property: "og:title", content: "My account | Emma Mold Inspection Services" },
      { property: "og:description", content: "Your bookings, quotes, reports and saved mold checks in one place." },
    ],
  }),
  component: Dashboard,
});

const tabs = ["Bookings", "Reports", "Quotes", "Scans", "Profile"] as const;

function Dashboard() {
  const { user, isAdmin } = useAuth();
  const navigate = useNavigate();
  const qc = useQueryClient();
  const [tab, setTab] = useState<(typeof tabs)[number]>("Bookings");

  const bookings = useQuery({
    queryKey: ["my-bookings", user?.id],
    enabled: !!user,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("bookings")
        .select("*")
        .eq("user_id", user!.id)
        .order("created_at", { ascending: false });
      if (error) throw error;
      return data;
    },
  });

  const reports = useQuery({
    queryKey: ["my-reports", user?.id],
    enabled: !!user,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("inspection_reports")
        .select("*")
        .order("inspection_date", { ascending: false });
      if (error) throw error;
      return data;
    },
  });

  const quotes = useQuery({
    queryKey: ["my-quotes", user?.id],
    enabled: !!user,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("quotations")
        .select("*, quotation_items(*)")
        .order("created_at", { ascending: false });
      if (error) throw error;
      return data;
    },
  });

  const scans = useQuery({
    queryKey: ["my-scans", user?.id],
    enabled: !!user,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("mold_scans")
        .select("*")
        .order("created_at", { ascending: false });
      if (error) throw error;
      return data;
    },
  });

  async function respondToQuote(id: string, status: "accepted" | "declined") {
    const { error } = await supabase.from("quotations").update({ status }).eq("id", id);
    if (error) return toast.error("Could not update the quotation.");
    toast.success(`Quotation ${status}.`);
    qc.invalidateQueries({ queryKey: ["my-quotes"] });
  }

  return (
    <AppShell>
      <div className="flex items-start justify-between gap-3">
        <div>
          <h1 className="text-2xl font-bold">My account</h1>
          <p className="mt-1 text-sm text-muted-foreground">{user?.email}</p>
        </div>
        <button
          onClick={async () => {
            await supabase.auth.signOut();
            qc.clear();
            navigate({ to: "/" });
          }}
          className="flex items-center gap-1.5 rounded-xl border border-border px-3 py-2 text-xs font-semibold"
        >
          <LogOut className="h-3.5 w-3.5" /> Sign out
        </button>
      </div>

      {isAdmin ? (
        <Link
          to="/admin"
          className="mt-4 flex items-center gap-2 rounded-2xl bg-brand px-4 py-3 text-sm font-semibold text-primary-foreground shadow-card"
        >
          <Shield className="h-4 w-4" /> Open admin dashboard
        </Link>
      ) : null}

      <div className="mt-5 flex gap-2 overflow-x-auto pb-1">
        {tabs.map((t) => (
          <button
            key={t}
            onClick={() => setTab(t)}
            className={`shrink-0 rounded-full px-4 py-2 text-xs font-semibold ${
              tab === t ? "bg-brand text-primary-foreground" : "bg-muted text-muted-foreground"
            }`}
          >
            {t}
          </button>
        ))}
      </div>

      <div className="mt-4 space-y-3">
        {tab === "Bookings" ? (
          <>
            {bookings.data?.length ? (
              bookings.data.map((b) => (
                <article key={b.id} className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
                  <div className="flex items-center justify-between gap-3">
                    <h2 className="text-sm font-semibold">{b.service_name}</h2>
                    <span className="rounded-full bg-muted px-2.5 py-1 text-[11px] font-semibold text-primary">
                      {b.status.replaceAll("_", " ")}
                    </span>
                  </div>
                  <p className="mt-1 text-xs text-muted-foreground">
                    {b.preferred_date ?? "Date to confirm"} • {b.preferred_time} • {b.address}
                  </p>
                  {b.inspector_name ? (
                    <p className="mt-1 text-xs text-muted-foreground">Inspector: {b.inspector_name}</p>
                  ) : null}
                </article>
              ))
            ) : (
              <Empty text="No bookings yet." action={{ to: "/book", label: "Book a service" }} />
            )}
          </>
        ) : null}

        {tab === "Reports" ? (
          <>
            {reports.data?.length ? (
              reports.data.map((r) => (
                <Link
                  key={r.id}
                  to="/reports/$id"
                  params={{ id: r.id }}
                  className="block rounded-2xl border border-border/60 bg-card p-4 shadow-card"
                >
                  <h2 className="text-sm font-semibold">{r.reference}</h2>
                  <p className="mt-1 text-xs text-muted-foreground">
                    {r.inspection_date} • Inspector {r.inspector_name} • Severity {r.severity ?? "—"}
                  </p>
                </Link>
              ))
            ) : (
              <Empty text="No reports published yet." />
            )}
          </>
        ) : null}

        {tab === "Quotes" ? (
          <>
            {quotes.data?.length ? (
              quotes.data.map((q) => (
                <article key={q.id} className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
                  <div className="flex items-center justify-between gap-3">
                    <h2 className="text-sm font-semibold">{q.reference}</h2>
                    <span className="rounded-full bg-muted px-2.5 py-1 text-[11px] font-semibold text-primary">
                      {q.status}
                    </span>
                  </div>
                  <ul className="mt-2 space-y-1 text-xs text-muted-foreground">
                    {q.quotation_items?.map((item) => (
                      <li key={item.id}>
                        {item.description} — {item.quantity} × ${item.unit_price}
                      </li>
                    ))}
                  </ul>
                  <p className="mt-2 text-sm font-semibold">Total ${q.total}</p>
                  {q.notes ? <p className="mt-1 text-xs text-muted-foreground">{q.notes}</p> : null}
                  {q.status === "sent" ? (
                    <div className="mt-3 grid grid-cols-2 gap-2">
                      <button
                        onClick={() => respondToQuote(q.id, "accepted")}
                        className="rounded-xl bg-brand py-2.5 text-xs font-semibold text-primary-foreground"
                      >
                        Accept
                      </button>
                      <button
                        onClick={() => respondToQuote(q.id, "declined")}
                        className="rounded-xl border border-border py-2.5 text-xs font-semibold"
                      >
                        Decline
                      </button>
                    </div>
                  ) : null}
                </article>
              ))
            ) : (
              <Empty text="No quotations yet." action={{ to: "/book", label: "Request a quote" }} />
            )}
          </>
        ) : null}

        {tab === "Scans" ? (
          <>
            {scans.data?.length ? (
              scans.data.map((s) => (
                <article key={s.id} className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
                  <div className="flex items-center justify-between gap-3">
                    <h2 className="text-sm font-semibold">{s.verdict}</h2>
                    <span className="rounded-full bg-muted px-2.5 py-1 text-[11px] font-semibold">{s.severity}</span>
                  </div>
                  <p className="mt-1 text-xs text-muted-foreground">{s.summary}</p>
                  <div className="mt-2 flex items-center justify-between gap-3">
                    <span className="text-[11px] text-muted-foreground">
                      {s.report_no ?? "No report number"} · {new Date(s.created_at).toLocaleDateString()}
                    </span>
                    {s.pdf_path ? <OpenReportButton path={s.pdf_path} /> : null}
                  </div>
                </article>
              ))
            ) : (
              <Empty text="No saved AI checks yet." action={{ to: "/check", label: "Run an AI check" }} />
            )}
          </>
        ) : null}

        {tab === "Profile" ? <ProfileCard /> : null}
      </div>
    </AppShell>
  );
}

function Empty({ text, action }: { text: string; action?: { to: string; label: string } }) {
  return EmptyState({ text, action });
}

function OpenReportButton({ path }: { path: string }) {
  return (
    <button
      onClick={async () => {
        const { reportPdfUrl } = await import("@/lib/report-actions");
        const url = await reportPdfUrl(path);
        if (!url) return toast.error("Could not open that report.");
        window.open(url, "_blank", "noopener");
      }}
      className="rounded-xl border border-border px-3 py-1.5 text-[11px] font-semibold text-primary"
    >
      Open PDF report
    </button>
  );
}

function EmptyState({ text, action }: { text: string; action?: { to: string; label: string } }) {
  return (
    <div className="rounded-2xl bg-muted p-6 text-center text-sm text-muted-foreground">
      {text}
      {action ? (
        <Link to={action.to} className="mt-3 block text-xs font-semibold text-primary">
          {action.label}
        </Link>
      ) : null}
    </div>
  );
}

function ProfileCard() {
  const { user } = useAuth();
  const qc = useQueryClient();
  const [form, setForm] = useState({ full_name: "", phone: "", address: "" });
  const [loaded, setLoaded] = useState(false);
  const [rating, setRating] = useState(5);
  const [comment, setComment] = useState("");

  useQuery({
    queryKey: ["profile", user?.id],
    enabled: !!user && !loaded,
    queryFn: async () => {
      const { data } = await supabase.from("profiles").select("*").eq("id", user!.id).maybeSingle();
      setForm({ full_name: data?.full_name ?? "", phone: data?.phone ?? "", address: data?.address ?? "" });
      setLoaded(true);
      return data;
    },
  });

  async function save() {
    if (!user) return;
    const { error } = await supabase.from("profiles").upsert({ id: user.id, ...form });
    if (error) return toast.error("Could not save your profile.");
    toast.success("Profile updated.");
    qc.invalidateQueries({ queryKey: ["profile"] });
  }

  async function submitReview() {
    if (!user) return;
    const { error } = await supabase.from("reviews").insert({
      user_id: user.id,
      author_name: form.full_name || "Customer",
      rating,
      comment,
    });
    if (error) return toast.error("Could not submit your review.");
    setComment("");
    toast.success("Thanks! Your review will appear once approved.");
  }

  const inputClass =
    "mt-1 w-full rounded-xl border border-input bg-background px-3 py-2.5 text-sm outline-none focus:border-primary";

  return (
    <>
      <PropertiesPanel />

      <section className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
        <h2 className="text-sm font-semibold">Profile details</h2>
        <label className="mt-3 block">
          <span className="text-xs font-medium text-muted-foreground">Full name</span>
          <input className={inputClass} value={form.full_name} onChange={(e) => setForm({ ...form, full_name: e.target.value })} />
        </label>
        <label className="mt-2 block">
          <span className="text-xs font-medium text-muted-foreground">Phone</span>
          <input className={inputClass} value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })} />
        </label>
        <label className="mt-2 block">
          <span className="text-xs font-medium text-muted-foreground">Address</span>
          <input className={inputClass} value={form.address} onChange={(e) => setForm({ ...form, address: e.target.value })} />
        </label>
        <button onClick={save} className="mt-3 w-full rounded-2xl bg-brand py-3 text-sm font-semibold text-primary-foreground">
          Save profile
        </button>
      </section>

      <section className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
        <h2 className="text-sm font-semibold">Leave a review</h2>
        <div className="mt-2 flex gap-1">
          {[1, 2, 3, 4, 5].map((n) => (
            <button key={n} onClick={() => setRating(n)} aria-label={`${n} stars`}>
              <Star className={`h-6 w-6 ${n <= rating ? "fill-warning text-warning" : "text-border"}`} />
            </button>
          ))}
        </div>
        <textarea
          className={inputClass}
          rows={3}
          value={comment}
          placeholder="How did we do?"
          onChange={(e) => setComment(e.target.value)}
        />
        <button onClick={submitReview} className="mt-3 w-full rounded-2xl border border-border py-3 text-sm font-semibold">
          Submit review
        </button>
      </section>
    </>
  );
}

const propertyTypes = [
  "Residential",
  "Apartment",
  "Office",
  "Hotel",
  "School",
  "Hospital",
  "Church",
  "Warehouse",
  "Commercial Building",
  "Other",
] as const;

type PropertyForm = {
  name: string;
  property_type: (typeof propertyTypes)[number];
  street_address: string;
  city: string;
  state_region: string;
  postcode: string;
  notes: string;
};

const emptyProperty: PropertyForm = {
  name: "",
  property_type: "Residential",
  street_address: "",
  city: "",
  state_region: "",
  postcode: "",
  notes: "",
};

function PropertiesPanel() {
  const { user } = useAuth();
  const qc = useQueryClient();
  const [form, setForm] = useState<PropertyForm>(emptyProperty);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [open, setOpen] = useState(false);
  const [busy, setBusy] = useState(false);

  const properties = useQuery({
    queryKey: ["my-properties", user?.id],
    enabled: Boolean(user),
    queryFn: async () => {
      if (!user) return [];
      const { data, error } = await supabase
        .from("properties")
        .select("*")
        .eq("owner_id", user.id)
        .order("created_at", { ascending: false });
      if (error) throw error;
      return data;
    },
  });

  const inputClass =
    "mt-1 w-full rounded-xl border border-input bg-background px-3 py-2.5 text-sm outline-none focus:border-primary";

  function startNew() {
    setEditingId(null);
    setForm(emptyProperty);
    setOpen(true);
  }

  function startEdit(property: NonNullable<typeof properties.data>[number]) {
    setEditingId(property.id);
    setForm({
      name: property.name,
      property_type: propertyTypes.includes(property.property_type as (typeof propertyTypes)[number])
        ? (property.property_type as (typeof propertyTypes)[number])
        : "Other",
      street_address: property.street_address,
      city: property.city ?? "",
      state_region: property.state_region ?? "",
      postcode: property.postcode ?? "",
      notes: property.notes ?? "",
    });
    setOpen(true);
  }

  async function saveProperty(event: React.FormEvent) {
    event.preventDefault();
    if (!user) return;
    setBusy(true);
    try {
      const values = {
        name: form.name.trim(),
        property_type: form.property_type,
        street_address: form.street_address.trim(),
        city: form.city.trim() || null,
        state_region: form.state_region.trim() || null,
        postcode: form.postcode.trim() || null,
        notes: form.notes.trim() || null,
      };
      if (!values.name || !values.street_address) {
        toast.error("Add a property name and street address.");
        return;
      }

      const result = editingId
        ? await supabase.from("properties").update(values satisfies TablesUpdate<"properties">).eq("id", editingId)
        : await supabase.from("properties").insert({
            ...values,
            owner_id: user.id,
            country: "NG",
            currency: "NGN",
            timezone: "Africa/Lagos",
            measurement_system: "metric",
          } satisfies TablesInsert<"properties">);
      if (result.error) throw result.error;
      toast.success(editingId ? "Property updated." : "Property added.");
      setOpen(false);
      setForm(emptyProperty);
      setEditingId(null);
      await qc.invalidateQueries({ queryKey: ["my-properties", user.id] });
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "Could not save the property.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <section className="rounded-2xl border border-border/60 bg-card p-4 shadow-card">
      <div className="flex items-start justify-between gap-3">
        <div>
          <h2 className="text-sm font-semibold">My properties</h2>
          <p className="mt-1 text-xs text-muted-foreground">Save the places you want to inspect or maintain.</p>
        </div>
        <button onClick={startNew} className="rounded-xl bg-brand px-3 py-2 text-xs font-semibold text-primary-foreground">
          Add property
        </button>
      </div>

      {open ? (
        <form onSubmit={saveProperty} className="mt-4 space-y-3 rounded-xl bg-muted/60 p-3">
          <div className="flex items-center justify-between gap-3">
            <h3 className="text-sm font-semibold">{editingId ? "Edit property" : "Add a property"}</h3>
            <button type="button" onClick={() => setOpen(false)} className="text-xs font-semibold text-muted-foreground">
              Cancel
            </button>
          </div>
          <label className="block text-xs font-medium text-muted-foreground">
            Property name
            <input required className={inputClass} value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="Family home" />
          </label>
          <label className="block text-xs font-medium text-muted-foreground">
            Property type
            <select className={inputClass} value={form.property_type} onChange={(e) => setForm({ ...form, property_type: e.target.value as PropertyForm["property_type"] })}>
              {propertyTypes.map((type) => <option key={type}>{type}</option>)}
            </select>
          </label>
          <label className="block text-xs font-medium text-muted-foreground">
            Street address
            <input required className={inputClass} value={form.street_address} onChange={(e) => setForm({ ...form, street_address: e.target.value })} placeholder="12 Example Street" />
          </label>
          <div className="grid grid-cols-2 gap-3">
            <label className="block text-xs font-medium text-muted-foreground">
              City / LGA
              <input className={inputClass} value={form.city} onChange={(e) => setForm({ ...form, city: e.target.value })} />
            </label>
            <label className="block text-xs font-medium text-muted-foreground">
              State
              <input className={inputClass} value={form.state_region} onChange={(e) => setForm({ ...form, state_region: e.target.value })} />
            </label>
          </div>
          <label className="block text-xs font-medium text-muted-foreground">
            Postcode
            <input className={inputClass} value={form.postcode} onChange={(e) => setForm({ ...form, postcode: e.target.value })} />
          </label>
          <label className="block text-xs font-medium text-muted-foreground">
            Notes (optional)
            <textarea rows={2} className={inputClass} value={form.notes} onChange={(e) => setForm({ ...form, notes: e.target.value })} />
          </label>
          <button disabled={busy} className="w-full rounded-xl bg-brand py-3 text-sm font-semibold text-primary-foreground disabled:opacity-60">
            {busy ? "Saving…" : editingId ? "Save changes" : "Add property"}
          </button>
        </form>
      ) : null}

      <div className="mt-4 space-y-2">
        {properties.data?.map((property) => (
          <article key={property.id} className="flex items-start justify-between gap-3 rounded-xl border border-border/60 p-3">
            <div className="min-w-0">
              <h3 className="truncate text-sm font-semibold">{property.name}</h3>
              <p className="mt-1 text-xs text-muted-foreground">{property.property_type} · {property.street_address}</p>
              {property.city || property.state_region ? <p className="text-xs text-muted-foreground">{[property.city, property.state_region].filter(Boolean).join(", ")}</p> : null}
            </div>
            <button onClick={() => startEdit(property)} className="shrink-0 rounded-lg border border-border px-2.5 py-1.5 text-xs font-semibold">
              Edit
            </button>
          </article>
        ))}
        {!properties.data?.length && !properties.isLoading ? <p className="rounded-xl bg-muted p-3 text-xs text-muted-foreground">No properties saved yet.</p> : null}
      </div>
    </section>
  );
}