import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { toast } from "sonner";

import { ListPage } from "@/components/app/ListPage";
import { formatDate } from "@/components/app/Primitives";
import { StatusPill } from "@/components/app/StatusPill";
import type { TableColumn } from "@/components/table/DataTable";
import type { GridColumn } from "@/components/grid/types";
import { validators } from "@/components/grid/types";
import { Button } from "@/components/ui/button";
import { useItinerariesAcrossTrips, type ItineraryDayWithTrip } from "@/features/trips/api";

export const Route = createFileRoute("/itineraries")({
  head: () => ({
    meta: [
      { title: "Itineraries | KareVoyage Operations" },
      {
        name: "description",
        content:
          "Every trip's day-by-day plan, in one grid — pulled live from each trip's own itinerary.",
      },
      { property: "og:title", content: "Itineraries | KareVoyage Operations" },
      { property: "og:description", content: "Cross-trip view of day-by-day travel schedules." },
    ],
  }),
  component: ItinerariesPage,
});

/** A day's calendar date isn't stored — it's derived from its trip's departure date + day number,
 * same "compute it, don't store it" pattern as a Trip's own returnDate. */
function dayDate(tripDepartureDate: string, dayNumber: number) {
  const d = new Date(`${tripDepartureDate}T00:00:00Z`);
  if (Number.isNaN(d.getTime())) return null;
  d.setUTCDate(d.getUTCDate() + (dayNumber - 1));
  return d.toISOString().slice(0, 10);
}

const titleCase = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);

const gridColumns: GridColumn<ItineraryDayWithTrip>[] = [
  {
    key: "tripCode",
    header: "Trip",
    width: 130,
    frozen: true,
    validate: validators.required("Trip"),
  },
  { key: "dayNumber", header: "Day", width: 70, type: "number", align: "right" },
  { key: "city", header: "City", width: 130 },
  { key: "hotelName", header: "Hotel", width: 180 },
  { key: "activitiesShort", header: "Activity", width: 220 },
  { key: "startTime", header: "Start", width: 90 },
  { key: "endTime", header: "End", width: 90 },
  { key: "meetingPoint", header: "Meeting point", width: 160 },
  { key: "transport", header: "Transport", width: 130 },
  { key: "meals", header: "Meals", width: 150 },
  { key: "tourManagerName", header: "Tour manager", width: 150 },
  { key: "tourManagerContact", header: "Contact", width: 150 },
  { key: "walkingLevel", header: "Walking", width: 110, options: ["low", "moderate", "high"] },
  { key: "dressCode", header: "Dress code", width: 140 },
  { key: "whatToCarry", header: "What to carry", width: 170 },
  { key: "notes", header: "Notes", width: 200 },
];

function ItinerariesPage() {
  const navigate = useNavigate();
  const { data, isLoading } = useItinerariesAcrossTrips({ limit: 200 });
  const rows = data?.rows ?? [];

  const columns: TableColumn<ItineraryDayWithTrip>[] = [
    {
      key: "day",
      header: "Day",
      sortValue: (r) => `${r.tripDepartureDate}-${String(r.dayNumber).padStart(3, "0")}`,
      cell: (r) => {
        const date = dayDate(r.tripDepartureDate, r.dayNumber);
        return (
          <div>
            <p className="font-medium">
              Day {String(r.dayNumber).padStart(2, "0")} · {r.city || r.tripDestination}
            </p>
            <p className="text-xs text-muted-foreground">
              {r.tripCode} · {date ? formatDate(date) : "—"}
            </p>
          </div>
        );
      },
    },
    {
      key: "activity",
      header: "Activity",
      sortValue: (r) => r.activitiesShort ?? "",
      cell: (r) => <span className="text-sm">{r.activitiesShort || r.title}</span>,
    },
    {
      key: "time",
      header: "Time",
      responsive: "hidden lg:table-cell",
      cell: (r) =>
        r.startTime || r.endTime ? (
          <span className="font-mono text-xs">
            {r.startTime ?? "—"}–{r.endTime ?? "—"}
          </span>
        ) : (
          "—"
        ),
    },
    {
      key: "hotel",
      header: "Hotel",
      responsive: "hidden xl:table-cell",
      sortValue: (r) => r.hotelName ?? "",
      cell: (r) => r.hotelName ?? "—",
    },
    {
      key: "meals",
      header: "Meals",
      responsive: "hidden xl:table-cell",
      cell: (r) => r.meals ?? "—",
    },
    {
      key: "walking",
      header: "Walking",
      cell: (r) => (r.walkingLevel ? <StatusPill value={titleCase(r.walkingLevel)} /> : "—"),
    },
  ];

  return (
    <ListPage
      title="Itineraries"
      description="Every trip's day-by-day plan, in one grid — seeded from each tour's template, then edited per trip."
      countLabel={(n) => (isLoading ? "Loading…" : `${n} itinerary days`)}
      searchPlaceholder="Search trip, city, activity…"
      actions={
        <Button onClick={() => toast.info("Switch to grid mode to paste an itinerary from Excel.")}>
          Bulk import
        </Button>
      }
      rows={rows}
      columns={columns}
      getId={(r) => r.id}
      searchText={(r) =>
        `${r.tripCode} ${r.tripTourTitle} ${r.city ?? ""} ${r.activitiesShort ?? ""} ${r.hotelName ?? ""} ${r.tourManagerName ?? ""}`
      }
      filters={[
        { key: "trip", label: "Trip", get: (r) => r.tripCode },
        { key: "city", label: "City", get: (r) => r.city ?? "" },
        {
          key: "walking",
          label: "Walking level",
          get: (r) => (r.walkingLevel ? titleCase(r.walkingLevel) : ""),
        },
      ]}
      onRowClick={(r) => navigate({ to: "/trips/$id", params: { id: r.tripId } })}
      rowActions={[
        {
          label: "Open trip",
          onSelect: (r) => navigate({ to: "/trips/$id", params: { id: r.tripId } }),
        },
      ]}
      gridColumns={gridColumns}
      gridModule="Itinerary"
      emptyTitle={isLoading ? "Loading itineraries…" : "No itinerary days yet"}
      emptyMessage={
        isLoading
          ? ""
          : "Days appear here automatically once a trip is created from a tour with an itinerary — or add one from a trip's own Itinerary tab."
      }
    />
  );
}
