import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { toast } from "sonner";
import { MapPin } from "lucide-react";
import { AppShell } from "@/components/AppShell";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/lib/use-auth";

export const Route = createFileRoute("/book")({
  validateSearch: (search: Record<string, unknown>) => ({
    service: typeof search.service === "string" ? search.service : undefined,
    company: typeof search.company === "string" ? search.company : undefined,
  }),
  head: () => ({
    meta: [
      { title: "Book a service | Emma Mold Inspection Services" },
      {
        name: "description",
        content: "Book a mold inspection, treatment, cleaning or fumigation visit and request a quotation online.",
      },
      { property: "og:title", content: "Book a service | Emma Mold Inspection Services" },
      { property: "og:description", content: "Choose a service, pick a date and our team will confirm your visit." },
    ],
  }),
  component: BookPage,
});

function BookPage() {
  const navigate = useNavigate();
  const { service: preselected, company: preselectedCompany } = Route.useSearch();
  const { user, loading } = useAuth();
  const [form, setForm] = useState({
    full_name: "",
    phone: "",
    email: "",
    address: "",
    gps_location: "",
    property_type: "House",
    rooms: "1",
    service: preselected ?? "",
    preferred_date: "",
    preferred_time: "Morning",
    notes: "",
  });
  const [files, setFiles] = useState<File[]>([]);
  const [busy, setBusy] = useState(false);
  const [companyId, setCompanyId] = useState(preselectedCompany ?? "");
  const [propertyId, setPropertyId] = useState("");

  const { data: providers } = useQuery({
    queryKey: ["providers", "booking"],
    queryFn: async () => {
      const { data, error } = await supabase.from("companies").select("id,name").eq("status", "approved").order("name");
      if (error) throw error;
      return data;
    },
  });

  const { data: services } = useQuery({
    queryKey: ["services", "booking"],
    queryFn: async () => {
      const { data, error } = await supabase.from("services").select("id,slug,name").order("sort_order");
      if (error) throw error;
      return data;
    },
  });

  const { data: properties } = useQuery({
    queryKey: ["my-properties", "booking", user?.id],
    enabled: Boolean(user),
    queryFn: async () => {
      if (!user) return [];
      const { data, error } = await supabase
        .from("properties")
        .select("id,name,property_type,street_address,city,state_region")
        .eq("owner_id", user.id)
        .order("name");
      if (error) throw error;
      return data;
    },
  });

  useEffect(() => {
    if (!user) return;
    supabase
      .from("profiles")
      .select("full_name,phone,address")
      .eq("id", user.id)
      .maybeSingle()
      .then(({ data }) => {
        setForm((f) => ({
          ...f,
          full_name: f.full_name || data?.full_name || "",
          phone: f.phone || data?.phone || "",
          address: f.address || data?.address || "",
          email: f.email || user.email || "",
        }));
      });
  }, [user]);

  useEffect(() => {
    if (preselected) setForm((f) => ({ ...f, service: preselected }));
  }, [preselected]);

  function selectProperty(id: string) {
    setPropertyId(id);
    const property = properties?.find((item) => item.id === id);
    if (!property) return;
    const address = [property.street_address, property.city, property.state_region].filter(Boolean).join(", ");
    setForm((current) => ({ ...current, address, property_type: property.property_type }));
  }

  function useGps() {
    if (!navigator.geolocation) return toast.error("Location is not available on this device.");
    navigator.geolocation.getCurrentPosition(
      (pos) =>
        setForm((f) => ({
          ...f,
          gps_location: `${pos.coords.latitude.toFixed(5)}, ${pos.coords.longitude.toFixed(5)}`,
        })),
      () => toast.error("Could not read your location."),
    );
  }

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    if (!user) return navigate({ to: "/auth" });
    const chosen = services?.find((s) => s.slug === form.service);
    if (!chosen) return toast.error("Please choose a service.");
    setBusy(true);
    try {
      const photo_urls: string[] = [];
      for (const file of files.slice(0, 5)) {
        const path = `${user.id}/bookings/${crypto.randomUUID()}-${file.name.replace(/[^\w.-]/g, "")}`;
        const { error } = await supabase.storage.from("mold-photos").upload(path, file);
        if (!error) photo_urls.push(path);
      }
      const { error } = await supabase.from("bookings").insert({
        user_id: user.id,
        property_id: propertyId || null,
        service_id: chosen.id,
        service_name: chosen.name,
        company_id: companyId || null,
        full_name: form.full_name,
        phone: form.phone,
        email: form.email,
        address: form.address,
        gps_location: form.gps_location || null,
        property_type: form.property_type,
        rooms: Number(form.rooms) || null,
        preferred_date: form.preferred_date || null,
        preferred_time: form.preferred_time,
        notes: form.notes || null,
        photo_urls,
      });
      if (error) throw error;
      await supabase.from("notifications").insert({
        user_id: user.id,
        title: "Booking received",
        body: `We received your ${chosen.name} request and will confirm shortly.`,
      });
      toast.success("Booking received. We'll confirm shortly.");
      navigate({ to: "/dashboard" });
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "Could not submit booking.");
    } finally {
      setBusy(false);
    }
  }

  const set = (key: keyof typeof form) => (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) =>
    setForm((f) => ({ ...f, [key]: e.target.value }));

  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 (
    <AppShell>
      <h1 className="text-2xl font-bold">Book a service</h1>
      <p className="mt-1 text-sm text-muted-foreground">Tell us what you need and we'll confirm your visit.</p>

      {!loading && !user ? (
        <div className="mt-4 rounded-2xl bg-muted p-4 text-sm">
          <p className="text-muted-foreground">Sign in so we can attach this booking to your account.</p>
          <Link to="/auth" className="mt-3 inline-block rounded-xl bg-brand px-4 py-2 text-xs font-semibold text-primary-foreground">
            Sign in or register
          </Link>
        </div>
      ) : null}

      <form className="mt-5 space-y-3" onSubmit={submit}>
        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Service required</span>
          <select className={inputClass} value={form.service} onChange={set("service")} required>
            <option value="">Choose a service</option>
            {services?.map((s) => (
              <option key={s.slug} value={s.slug}>
                {s.name}
              </option>
            ))}
          </select>
        </label>

        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Service provider (optional)</span>
          <select className={inputClass} value={companyId} onChange={(e) => setCompanyId(e.target.value)}>
            <option value="">Emma Mold Inspection Services</option>
            {providers?.map((p) => (
              <option key={p.id} value={p.id}>
                {p.name}
              </option>
            ))}
          </select>
        </label>

        {user ? (
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Saved property (optional)</span>
            <select className={inputClass} value={propertyId} onChange={(e) => selectProperty(e.target.value)}>
              <option value="">Enter a property manually</option>
              {properties?.map((property) => (
                <option key={property.id} value={property.id}>
                  {property.name} · {property.street_address}
                </option>
              ))}
            </select>
            <span className="mt-1 block text-[11px] text-muted-foreground">
              Choose a saved property to fill in its address details.
            </span>
          </label>
        ) : null}

        <div className="grid grid-cols-2 gap-3">
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Name</span>
            <input className={inputClass} value={form.full_name} onChange={set("full_name")} required />
          </label>
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Phone</span>
            <input className={inputClass} type="tel" value={form.phone} onChange={set("phone")} required />
          </label>
        </div>

        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Email</span>
          <input className={inputClass} type="email" value={form.email} onChange={set("email")} required />
        </label>

        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Address</span>
          <input className={inputClass} value={form.address} onChange={set("address")} required />
        </label>

        <div className="flex items-end gap-2">
          <label className="block flex-1">
            <span className="text-xs font-medium text-muted-foreground">GPS location (optional)</span>
            <input className={inputClass} value={form.gps_location} onChange={set("gps_location")} />
          </label>
          <button type="button" onClick={useGps} className="rounded-xl border border-border p-3" aria-label="Use my location">
            <MapPin className="h-4 w-4" />
          </button>
        </div>

        <div className="grid grid-cols-2 gap-3">
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Property type</span>
            <select className={inputClass} value={form.property_type} onChange={set("property_type")}>
              {["Residential", "Apartment", "Office", "Hotel", "School", "Hospital", "Church", "Warehouse", "Commercial Building", "Other"].map((t) => (
                <option key={t}>{t}</option>
              ))}
            </select>
          </label>
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Number of rooms</span>
            <input className={inputClass} type="number" min="1" value={form.rooms} onChange={set("rooms")} />
          </label>
        </div>

        <div className="grid grid-cols-2 gap-3">
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Preferred date</span>
            <input className={inputClass} type="date" value={form.preferred_date} onChange={set("preferred_date")} />
          </label>
          <label className="block">
            <span className="text-xs font-medium text-muted-foreground">Preferred time</span>
            <select className={inputClass} value={form.preferred_time} onChange={set("preferred_time")}>
              {["Morning", "Afternoon", "Evening"].map((t) => (
                <option key={t}>{t}</option>
              ))}
            </select>
          </label>
        </div>

        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Additional notes</span>
          <textarea className={inputClass} rows={3} value={form.notes} onChange={set("notes")} />
        </label>

        <label className="block">
          <span className="text-xs font-medium text-muted-foreground">Upload photos (up to 5)</span>
          <input
            className={inputClass}
            type="file"
            accept="image/*"
            multiple
            onChange={(e) => setFiles(Array.from(e.target.files ?? []))}
          />
        </label>

        <button
          disabled={busy}
          className="w-full rounded-2xl bg-brand py-3.5 text-sm font-semibold text-primary-foreground shadow-float disabled:opacity-60"
        >
          {busy ? "Submitting…" : "Submit booking"}
        </button>
      </form>
    </AppShell>
  );
}