import { createFileRoute } from "@tanstack/react-router";
import { useCallback, useEffect, useState } from "react";
import { supabase } from "@/integrations/supabase/client";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import { Skeleton } from "@/components/ui/skeleton";
import { toast } from "sonner";
import { Download, FileText, Search, Upload, X as XIcon } from "lucide-react";
import { STATUS_LABEL, kes, type OrderStatus, type PaymentStatus } from "@/lib/portal";

export const Route = createFileRoute("/admin/orders")({ component: OrdersAdmin });

type Order = {
  id: string;
  order_no: string;
  user_id: string;
  service_name: string;
  contact_name: string;
  contact_phone: string;
  contact_email: string | null;
  whatsapp: string | null;
  details: Record<string, unknown>;
  notes: string | null;
  admin_notes: string | null;
  delivery_notes: string | null;
  status: OrderStatus;
  payment_status: PaymentStatus;
  price: number | null;
  discount: number;
  created_at: string;
};

type OrderPatch = Partial<Omit<Order, "details">>;

type Doc = { id: string; order_id: string; name: string; path: string; kind: string; mime_type: string | null };

const STATUSES: OrderStatus[] = ["submitted", "in_review", "processing", "awaiting_info", "completed", "cancelled"];

function OrdersAdmin() {
  const [orders, setOrders] = useState<Order[]>([]);
  const [docs, setDocs] = useState<Doc[]>([]);
  const [loading, setLoading] = useState(true);
  const [filter, setFilter] = useState<"all" | OrderStatus>("all");
  const [q, setQ] = useState("");

  const load = useCallback(async () => {
    const [o, d] = await Promise.all([
      supabase
        .from("orders")
        .select(
          "id, order_no, user_id, service_name, contact_name, contact_phone, contact_email, whatsapp, details, notes, admin_notes, delivery_notes, status, payment_status, price, discount, created_at",
        )
        .order("created_at", { ascending: false }),
      supabase.from("order_documents").select("id, order_id, name, path, kind, mime_type"),
    ]);
    if (o.error) toast.error(o.error.message);
    setOrders((o.data ?? []) as unknown as Order[]);
    setDocs((d.data ?? []) as Doc[]);
    setLoading(false);
  }, []);

  useEffect(() => {
    load();
  }, [load]);

  const patch = async (id: string, values: OrderPatch) => {
    const { error } = await supabase.from("orders").update(values).eq("id", id);
    if (error) return toast.error(error.message);
    setOrders((rows) => rows.map((r) => (r.id === id ? { ...r, ...values } : r)));
    toast.success("Order updated");
  };

  const term = q.trim().toLowerCase();
  const visible = orders.filter(
    (o) =>
      (filter === "all" || o.status === filter) &&
      (!term ||
        [o.order_no, o.service_name, o.contact_name, o.contact_phone, o.contact_email ?? ""]
          .join(" ")
          .toLowerCase()
          .includes(term)),
  );

  const revenue = orders.filter((o) => o.payment_status === "paid").reduce((s, o) => s + Math.max(Number(o.price ?? 0) - Number(o.discount ?? 0), 0), 0);

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold tracking-tight">Orders</h1>
        <p className="text-sm text-muted-foreground">
          Price, progress and deliver every customer order. Paid revenue so far: <span className="font-semibold text-foreground">{kes(revenue)}</span>
        </p>
      </div>

      <div className="flex flex-wrap items-center gap-2">
        <div className="relative min-w-[220px] grow sm:max-w-xs">
          <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
          <Input className="pl-9" placeholder="Search order no, service, customer" value={q} onChange={(e) => setQ(e.target.value)} />
        </div>
        {(["all", ...STATUSES] as const).map((s) => (
          <Button key={s} size="sm" variant={filter === s ? "default" : "outline"} onClick={() => setFilter(s)}>
            {s === "all" ? "All" : STATUS_LABEL[s]}
          </Button>
        ))}
      </div>

      {loading ? (
        <div className="grid gap-3">
          {[0, 1, 2].map((i) => (
            <Skeleton key={i} className="h-44 w-full rounded-xl" />
          ))}
        </div>
      ) : visible.length === 0 ? (
        <p className="text-sm text-muted-foreground">No orders match this view.</p>
      ) : (
        <div className="grid gap-3">
          {visible.map((o) => (
            <OrderCard key={o.id} order={o} docs={docs.filter((d) => d.order_id === o.id)} onPatch={patch} onReload={load} />
          ))}
        </div>
      )}
    </div>
  );
}

function OrderCard({
  order,
  docs,
  onPatch,
  onReload,
}: {
  order: Order;
  docs: Doc[];
  onPatch: (id: string, values: OrderPatch) => void;
  onReload: () => void;
}) {
  const [price, setPrice] = useState(order.price != null ? String(order.price) : "");
  const [discount, setDiscount] = useState(String(order.discount ?? 0));
  const [adminNotes, setAdminNotes] = useState(order.admin_notes ?? "");
  const [deliveryNotes, setDeliveryNotes] = useState(order.delivery_notes ?? "");
  const [files, setFiles] = useState<File[]>([]);
  const [busy, setBusy] = useState(false);

  const detailEntries = Object.entries(order.details ?? {}).filter(([, v]) => v !== null && v !== "");
  const total = Math.max(Number(order.price ?? 0) - Number(order.discount ?? 0), 0);
  const unpaid = order.payment_status !== "paid" && (order.price ?? 0) > 0;

  const openDoc = async (doc: Doc) => {
    const { data, error } = await supabase.storage.from("request-attachments").createSignedUrl(doc.path, 1800);
    if (error || !data) return toast.error("Could not open this file");
    window.open(data.signedUrl, "_blank", "noopener,noreferrer");
  };

  const deliver = async (markCompleted: boolean) => {
    setBusy(true);
    try {
      for (const f of files) {
        if (f.size > 25 * 1024 * 1024) {
          toast.error(`${f.name} exceeds 25MB`);
          continue;
        }
        const safe = f.name.replace(/[^a-zA-Z0-9._-]/g, "_");
        const path = `${order.user_id}/orders/${order.id}/delivery/${Date.now()}-${safe}`;
        const up = await supabase.storage.from("request-attachments").upload(path, f, {
          contentType: f.type || "application/octet-stream",
        });
        if (up.error) {
          toast.error(`Upload failed: ${f.name}`);
          continue;
        }
        const ins = await supabase.from("order_documents").insert({
          order_id: order.id,
          user_id: order.user_id,
          kind: "delivery",
          name: f.name,
          path,
          mime_type: f.type || null,
          size_bytes: f.size,
        });
        if (ins.error) toast.error(ins.error.message);
      }

      const values: OrderPatch = { delivery_notes: deliveryNotes || null };
      if (markCompleted) values.status = "completed";
      const { error } = await supabase.from("orders").update(values).eq("id", order.id);
      if (error) throw error;
      toast.success(markCompleted ? "Delivered to the customer" : "Delivery draft saved");
      setFiles([]);
      onReload();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "Failed to deliver");
    } finally {
      setBusy(false);
    }
  };

  const removeDoc = async (doc: Doc) => {
    if (!confirm(`Remove ${doc.name}?`)) return;
    await supabase.storage.from("request-attachments").remove([doc.path]);
    const { error } = await supabase.from("order_documents").delete().eq("id", doc.id);
    if (error) return toast.error(error.message);
    onReload();
  };

  return (
    <Card className="glass">
      <CardHeader className="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-3 space-y-0">
        <div className="min-w-0">
          <div className="truncate font-semibold">{order.service_name}</div>
          <div className="text-xs text-muted-foreground">
            {order.order_no} · {new Date(order.created_at).toLocaleString()}
          </div>
          <div className="truncate text-xs text-muted-foreground">
            {order.contact_name} · {order.contact_phone}
            {order.contact_email ? ` · ${order.contact_email}` : ""}
          </div>
        </div>
        <div className="flex shrink-0 flex-col items-end gap-1">
          <select
            value={order.status}
            onChange={(e) => onPatch(order.id, { status: e.target.value as OrderStatus })}
            className="rounded-md border bg-background px-2 py-1 text-xs"
          >
            {STATUSES.map((s) => (
              <option key={s} value={s}>
                {STATUS_LABEL[s]}
              </option>
            ))}
          </select>
          <Badge variant={order.payment_status === "paid" ? "default" : "secondary"} className="capitalize">
            {order.payment_status}
          </Badge>
        </div>
      </CardHeader>

      <CardContent className="space-y-3 text-sm">
        {detailEntries.length > 0 && (
          <div className="grid gap-1 rounded-lg border bg-background/50 p-3 sm:grid-cols-2">
            {detailEntries.map(([k, v]) => (
              <div key={k} className="min-w-0 text-xs">
                <span className="text-muted-foreground">{k.replace(/_/g, " ")}: </span>
                <span className="font-medium break-words">{String(v)}</span>
              </div>
            ))}
          </div>
        )}
        {order.notes && (
          <p className="rounded-lg border bg-background/50 p-3">
            <span className="font-medium">Customer notes: </span>
            {order.notes}
          </p>
        )}

        <div className="flex flex-wrap items-end gap-2 rounded-lg border bg-background/50 p-3">
          <div className="grow space-y-1">
            <Label className="text-xs text-muted-foreground">Price (KSh)</Label>
            <Input type="number" min="0" value={price} onChange={(e) => setPrice(e.target.value)} placeholder="e.g. 500" />
          </div>
          <div className="grow space-y-1">
            <Label className="text-xs text-muted-foreground">Discount (KSh)</Label>
            <Input type="number" min="0" value={discount} onChange={(e) => setDiscount(e.target.value)} />
          </div>
          <Button
            size="sm"
            variant="outline"
            onClick={() =>
              onPatch(order.id, {
                price: price === "" ? null : Number(price),
                discount: Number(discount || 0),
              })
            }
          >
            Save pricing
          </Button>
          <div className="self-center text-xs text-muted-foreground">Due: {order.price == null ? "—" : kes(total)}</div>
        </div>

        {docs.length > 0 && (
          <div className="grid gap-2 sm:grid-cols-2">
            {docs.map((d) => (
              <div key={d.id} className="flex items-center gap-2 rounded-lg border bg-background p-2 text-xs">
                <FileText className="h-4 w-4 shrink-0 text-primary" />
                <button type="button" onClick={() => openDoc(d)} className="min-w-0 flex-1 truncate text-left hover:underline">
                  {d.name}
                </button>
                <Badge variant="outline" className="shrink-0 text-[10px]">
                  {d.kind === "delivery" ? "Delivered" : "Uploaded"}
                </Badge>
                <button type="button" onClick={() => openDoc(d)} title="Open">
                  <Download className="h-3.5 w-3.5 text-muted-foreground" />
                </button>
                {d.kind === "delivery" && (
                  <button type="button" onClick={() => removeDoc(d)} className="text-destructive" title="Remove">
                    <XIcon className="h-3.5 w-3.5" />
                  </button>
                )}
              </div>
            ))}
          </div>
        )}

        <div className="space-y-2 rounded-lg border border-primary/20 bg-primary/5 p-3">
          <div className="text-sm font-semibold">Deliver order</div>
          <Textarea rows={2} placeholder="Message to the customer with the completed work" value={deliveryNotes} onChange={(e) => setDeliveryNotes(e.target.value)} />
          <label className="flex cursor-pointer items-center justify-center gap-2 rounded-md border border-dashed px-3 py-3 text-xs text-muted-foreground hover:bg-muted">
            <Upload className="h-4 w-4" />
            <span>Upload completed files (max 25MB each)</span>
            <input
              type="file"
              multiple
              className="hidden"
              onChange={(e) => {
                setFiles((p) => [...p, ...Array.from(e.target.files ?? [])]);
                e.target.value = "";
              }}
            />
          </label>
          {files.length > 0 && (
            <ul className="space-y-1 text-xs">
              {files.map((f, i) => (
                <li key={i} className="flex items-center justify-between rounded bg-muted/50 px-2 py-1">
                  <span className="truncate">{f.name}</span>
                  <button onClick={() => setFiles((p) => p.filter((_, j) => j !== i))}>
                    <XIcon className="h-3 w-3" />
                  </button>
                </li>
              ))}
            </ul>
          )}
          <div className="flex flex-wrap gap-2">
            <Button size="sm" variant="outline" onClick={() => deliver(false)} disabled={busy}>
              Save draft
            </Button>
            <Button size="sm" onClick={() => deliver(true)} disabled={busy || unpaid}>
              {busy ? "Delivering…" : "Deliver & mark complete"}
            </Button>
            {unpaid && <span className="self-center text-xs text-muted-foreground">Customer must pay first</span>}
          </div>
        </div>

        <div className="space-y-2">
          <Textarea rows={2} placeholder="Update visible to the customer" value={adminNotes} onChange={(e) => setAdminNotes(e.target.value)} />
          <Button size="sm" onClick={() => onPatch(order.id, { admin_notes: adminNotes || null })}>
            Save update
          </Button>
        </div>
      </CardContent>
    </Card>
  );
}
