"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import { useParams, useRouter } from "next/navigation";
import { useAuth } from "@/components/AuthProvider";
import { c2api } from "@/lib/c2api";
import type { TripEvent, TripRecord, PlaceResult } from "@/lib/types";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function uid(): string {
  try { return crypto.randomUUID(); } catch { return Math.random().toString(36).slice(2) + Date.now().toString(36); }
}

function toMin(t: string): number {
  const [h, m] = t.split(":").map(Number);
  return h * 60 + (m ?? 0);
}

function fmtDate(iso: string) {
  return new Date(`${iso}T12:00:00`).toLocaleDateString("en-US", {
    month: "short", day: "numeric", year: "numeric",
  });
}

function fmtDayTab(iso: string) {
  const d = new Date(`${iso}T12:00:00`);
  return {
    short: d.toLocaleDateString("en-US", { weekday: "short" }),
    date:  d.toLocaleDateString("en-US", { month: "short", day: "numeric" }),
  };
}

function fmtDayHeading(iso: string) {
  return new Date(`${iso}T12:00:00`).toLocaleDateString("en-US", {
    weekday: "long", month: "long", day: "numeric",
  });
}

function fmtTime(t: string | null | undefined): string {
  if (!t) return "";
  const [h, m] = t.split(":").map(Number);
  const d = new Date(); d.setHours(h, m, 0, 0);
  return d.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" });
}

function dateRange(start: string, end: string): string[] {
  const dates: string[] = [];
  const cur = new Date(`${start}T12:00:00`);
  const endDate = new Date(`${end}T12:00:00`);
  while (cur <= endDate) {
    dates.push(cur.toISOString().slice(0, 10));
    cur.setDate(cur.getDate() + 1);
  }
  return dates;
}

function detectConflicts(events: TripEvent[]): Set<string> {
  const timed = events.filter((e) => e.start_time);
  const conflicts = new Set<string>();
  for (let i = 0; i < timed.length; i++) {
    for (let j = i + 1; j < timed.length; j++) {
      const aS = toMin(timed[i].start_time!);
      const aE = timed[i].end_time ? toMin(timed[i].end_time!) : aS + 60;
      const bS = toMin(timed[j].start_time!);
      const bE = timed[j].end_time ? toMin(timed[j].end_time!) : bS + 60;
      if (aS < bE && bS < aE) {
        conflicts.add(timed[i].event_id);
        conflicts.add(timed[j].event_id);
      }
    }
  }
  return conflicts;
}

// ---------------------------------------------------------------------------
// Places search dropdown (reusable within modal)
// ---------------------------------------------------------------------------

function PlaceSearch({
  near,
  onSelect,
}: {
  near: string;
  onSelect: (p: PlaceResult) => void;
}) {
  const [query, setQuery]     = useState("");
  const [results, setResults] = useState<PlaceResult[]>([]);
  const [loading, setLoading] = useState(false);

  async function search() {
    if (!query.trim()) return;
    setLoading(true);
    try {
      const r = await c2api.searchPlaces(query, near);
      setResults(r);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="space-y-2">
      <div className="flex gap-2">
        <input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && (e.preventDefault(), search())}
          placeholder="Search a place…"
          className="flex-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
        />
        <button
          type="button"
          onClick={search}
          disabled={loading}
          className="bg-gray-700 hover:bg-gray-600 disabled:opacity-50 text-white text-sm rounded-lg px-3 py-2 transition-colors"
        >
          {loading ? "…" : "Search"}
        </button>
      </div>
      {results.length > 0 && (
        <div className="bg-gray-800 border border-gray-700 rounded-lg overflow-hidden divide-y divide-gray-700">
          {results.map((p) => (
            <button
              key={p.place_id}
              type="button"
              onClick={() => { onSelect(p); setResults([]); setQuery(""); }}
              className="w-full text-left px-3 py-2 hover:bg-gray-700 transition-colors"
            >
              <p className="text-white text-sm font-medium">{p.name}</p>
              <p className="text-gray-400 text-xs">{p.address}</p>
              {p.rating && (
                <p className="text-yellow-400 text-xs">★ {p.rating}</p>
              )}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Add Event modal
// ---------------------------------------------------------------------------

function AddEventModal({
  trip,
  onClose,
  onAdd,
  prefill,
}: {
  trip: TripRecord;
  onClose: () => void;
  onAdd: (body: object) => Promise<void>;
  prefill?: Partial<TripEvent>;
}) {
  const [title,     setTitle]     = useState(prefill?.title ?? "");
  const [date,      setDate]      = useState(prefill?.date ?? trip.start_date);
  const [startTime, setStartTime] = useState(prefill?.start_time ?? "");
  const [endTime,   setEndTime]   = useState(prefill?.end_time ?? "");
  const [location,  setLocation]  = useState(prefill?.location ?? "");
  const [mapsLink,  setMapsLink]  = useState(prefill?.maps_link ?? "");
  const [placeId,   setPlaceId]   = useState(prefill?.place_id ?? "");
  const [notes,     setNotes]     = useState(prefill?.notes ?? "");
  const [saving,    setSaving]    = useState(false);
  const [error,     setError]     = useState<string | null>(null);

  function handlePlaceSelect(p: PlaceResult) {
    if (!title) setTitle(p.name);
    setLocation(p.address);
    setMapsLink(p.maps_link);
    setPlaceId(p.place_id);
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    setError(null);
    try {
      await onAdd({
        title,
        date,
        start_time: startTime || null,
        end_time:   endTime || null,
        location:   location || null,
        maps_link:  mapsLink || null,
        place_id:   placeId || null,
        notes:      notes || null,
      });
      onClose();
    } catch {
      setError("Failed to add event. Check the date is within the trip range.");
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
      <form
        onSubmit={handleSubmit}
        className="bg-gray-900 border border-gray-700 rounded-xl p-6 w-full max-w-lg space-y-4 max-h-[90vh] overflow-y-auto"
      >
        <h2 className="text-white font-bold text-lg">Add Event</h2>

        <div>
          <label className="text-xs text-gray-400 block mb-1">Title</label>
          <input
            required value={title} onChange={(e) => setTitle(e.target.value)}
            placeholder="Dinner at the bar"
            className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
          />
        </div>

        <div className="grid grid-cols-3 gap-3">
          <div>
            <label className="text-xs text-gray-400 block mb-1">Date</label>
            <input
              required type="date"
              min={trip.start_date} max={trip.end_date}
              value={date} onChange={(e) => setDate(e.target.value)}
              className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
            />
          </div>
          <div>
            <label className="text-xs text-gray-400 block mb-1">Start</label>
            <input
              type="time" value={startTime} onChange={(e) => setStartTime(e.target.value)}
              className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
            />
          </div>
          <div>
            <label className="text-xs text-gray-400 block mb-1">End</label>
            <input
              type="time" value={endTime} onChange={(e) => setEndTime(e.target.value)}
              min={startTime}
              className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
            />
          </div>
        </div>

        <div>
          <label className="text-xs text-gray-400 block mb-1">Find a place</label>
          <PlaceSearch near={trip.location} onSelect={handlePlaceSelect} />
        </div>

        <div>
          <label className="text-xs text-gray-400 block mb-1">
            Location{" "}
            <span className="text-gray-600">(auto-filled from search, or type manually)</span>
          </label>
          <input
            value={location} onChange={(e) => setLocation(e.target.value)}
            placeholder={`Inherits: ${trip.location}`}
            className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500"
          />
        </div>

        {mapsLink && (
          <p className="text-xs text-indigo-400">
            Maps link attached —{" "}
            <a href={mapsLink} target="_blank" rel="noopener noreferrer" className="underline">
              preview
            </a>
          </p>
        )}

        <div>
          <label className="text-xs text-gray-400 block mb-1">Notes (optional)</label>
          <textarea
            value={notes} onChange={(e) => setNotes(e.target.value)} rows={2}
            className="w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none resize-none"
          />
        </div>

        {error && <p className="text-red-400 text-xs">{error}</p>}

        <div className="flex gap-3 justify-end pt-1">
          <button type="button" onClick={onClose} className="text-sm text-gray-400 hover:text-gray-200 px-4 py-2">
            Cancel
          </button>
          <button
            type="submit" disabled={saving}
            className="bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white text-sm rounded-lg px-4 py-2"
          >
            {saving ? "Adding…" : "Add Event"}
          </button>
        </div>
      </form>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Day timeline
// ---------------------------------------------------------------------------

const PX_PER_MIN = 1.3; // 78px per hour

function DayTimeline({
  events,
  isAdmin,
  onDelete,
  driveSegments,
}: {
  events: TripEvent[];
  isAdmin: boolean;
  onDelete: (id: string) => void;
  driveSegments: { fromId: string; toId: string; text: string }[];
}) {
  const timed = [...events.filter((e) => e.start_time)].sort(
    (a, b) => toMin(a.start_time!) - toMin(b.start_time!)
  );
  const untimed = events.filter((e) => !e.start_time);
  const conflicts = detectConflicts(events);

  if (timed.length === 0 && untimed.length === 0) {
    return (
      <p className="text-gray-600 text-sm font-mono py-8 text-center">
        No events on this day yet.
      </p>
    );
  }

  // Dynamic time range, clamped to 0–1440, min 8h window
  let rangeStart = 7 * 60;
  let rangeEnd   = 22 * 60;
  if (timed.length > 0) {
    const starts = timed.map((e) => toMin(e.start_time!));
    const ends   = timed.map((e) => (e.end_time ? toMin(e.end_time) : toMin(e.start_time!) + 60));
    rangeStart = Math.max(0, Math.floor(Math.min(...starts) / 60) * 60 - 60);
    rangeEnd   = Math.min(24 * 60, Math.ceil(Math.max(...ends) / 60) * 60 + 60);
    if (rangeEnd - rangeStart < 8 * 60) rangeEnd = Math.min(24 * 60, rangeStart + 8 * 60);
  }

  const hours: number[] = [];
  for (let h = Math.ceil(rangeStart / 60); h <= Math.floor(rangeEnd / 60); h++) hours.push(h);
  const totalHeight = (rangeEnd - rangeStart) * PX_PER_MIN;

  const driveMap = new Map(driveSegments.map((s) => [s.fromId, s.text]));

  return (
    <div className="space-y-6">
      {/* Timed events — visual timeline */}
      {timed.length > 0 && (
        <div className="relative select-none" style={{ height: totalHeight }}>
          {/* Hour gridlines */}
          {hours.map((h) => (
            <div
              key={h}
              style={{ top: (h * 60 - rangeStart) * PX_PER_MIN }}
              className="absolute inset-x-0 flex items-center pointer-events-none"
            >
              <span className="w-14 text-right pr-3 text-xs text-gray-600 font-mono shrink-0 -translate-y-2">
                {h === 0 ? "12 AM" : h < 12 ? `${h} AM` : h === 12 ? "12 PM" : `${h - 12} PM`}
              </span>
              <div className="flex-1 border-t border-gray-800/70" />
            </div>
          ))}

          {/* Event blocks */}
          {timed.map((e) => {
            const startMin  = toMin(e.start_time!);
            const endMin    = e.end_time ? toMin(e.end_time) : startMin + 60;
            const top       = (startMin - rangeStart) * PX_PER_MIN;
            const height    = Math.max(36, (endMin - startMin) * PX_PER_MIN);
            const isConflict = conflicts.has(e.event_id);
            const drive     = driveMap.get(e.event_id);

            return (
              <div key={e.event_id}>
                <div
                  style={{ top, height, left: 60, right: 0 }}
                  className={`absolute rounded-lg px-3 py-2 overflow-hidden group transition-colors ${
                    isConflict
                      ? "bg-red-950/70 border border-red-700/70"
                      : "bg-indigo-950/60 border border-indigo-800/50 hover:border-indigo-600/70"
                  }`}
                >
                  <div className="flex items-start justify-between gap-2 h-full">
                    <div className="min-w-0 flex-1">
                      <p className="text-white text-xs font-semibold leading-tight truncate">{e.title}</p>
                      {height >= 44 && (
                        <p className={`text-xs font-mono mt-0.5 ${isConflict ? "text-red-400" : "text-indigo-400"}`}>
                          {fmtTime(e.start_time)}
                          {e.end_time ? ` – ${fmtTime(e.end_time)}` : ""}
                          {isConflict ? "  ⚠ conflict" : ""}
                        </p>
                      )}
                      {height >= 60 && !e.location_inherited && e.location && (
                        <p className="text-gray-500 text-xs mt-0.5 truncate">{e.location}</p>
                      )}
                      {height >= 60 && e.notes && (
                        <p className="text-gray-600 text-xs mt-0.5 italic truncate">{e.notes}</p>
                      )}
                    </div>
                    <div className="flex items-center gap-1 shrink-0">
                      {e.maps_link && (
                        <a
                          href={e.maps_link}
                          target="_blank"
                          rel="noopener noreferrer"
                          onClick={(ev) => ev.stopPropagation()}
                          className="text-indigo-400 hover:text-indigo-300 text-xs opacity-0 group-hover:opacity-100 transition-opacity"
                        >
                          Maps
                        </a>
                      )}
                      {isAdmin && (
                        <button
                          onClick={() => onDelete(e.event_id)}
                          className="text-gray-600 hover:text-red-400 text-base leading-none opacity-0 group-hover:opacity-100 transition-opacity"
                        >
                          ×
                        </button>
                      )}
                    </div>
                  </div>
                </div>
                {/* Drive time badge below this event, if present */}
                {drive && (
                  <div
                    style={{ top: top + height + 2, left: 60 }}
                    className="absolute text-xs text-gray-600 font-mono flex items-center gap-1"
                  >
                    <span className="text-gray-700">↓</span> {drive} drive
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}

      {/* Untimed / all-day events */}
      {untimed.length > 0 && (
        <div className="space-y-1.5">
          <p className="text-xs font-mono text-gray-600 uppercase tracking-wider">Unscheduled</p>
          {untimed.map((e) => (
            <div
              key={e.event_id}
              className="bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 flex items-center justify-between group"
            >
              <div className="min-w-0">
                <p className="text-white text-sm">{e.title}</p>
                {!e.location_inherited && e.location && (
                  <p className="text-gray-500 text-xs mt-0.5">{e.location}</p>
                )}
                {e.notes && <p className="text-gray-600 text-xs italic mt-0.5">{e.notes}</p>}
              </div>
              <div className="flex items-center gap-2 shrink-0">
                {e.maps_link && (
                  <a href={e.maps_link} target="_blank" rel="noopener noreferrer"
                    className="text-xs text-indigo-400 hover:text-indigo-300 opacity-0 group-hover:opacity-100 transition-opacity">
                    Maps
                  </a>
                )}
                {isAdmin && (
                  <button onClick={() => onDelete(e.event_id)}
                    className="text-gray-600 hover:text-red-400 text-sm opacity-0 group-hover:opacity-100 transition-opacity">
                    ×
                  </button>
                )}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// AI Assistant panel
// ---------------------------------------------------------------------------

interface ChatMessage {
  id: string;
  role: "user" | "assistant";
  content: string;
  suggestions?: SuggestionCard[];
}

interface SuggestionCard {
  title: string;
  date?: string;
  start_time?: string;
  end_time?: string;
  location?: string;
  maps_link?: string;
  notes?: string;
  dismissed?: boolean;
  added?: boolean;
}

const CHAT_STORAGE_KEY = (tripId: string) => `drb-trip-chat-${tripId}`;

function AssistantPanel({
  trip,
  onAddEvent,
}: {
  trip: TripRecord & { events: TripEvent[] };
  onAddEvent: (event: TripEvent) => void;
}) {
  const storageKey = CHAT_STORAGE_KEY(trip.trip_id);
  const [messages,  setMessages]  = useState<ChatMessage[]>(() => {
    try {
      const saved = localStorage.getItem(storageKey);
      return saved ? JSON.parse(saved) : [];
    } catch { return []; }
  });
  const [input,     setInput]     = useState("");
  const [loading,   setLoading]   = useState(false);
  const bottomRef  = useRef<HTMLDivElement>(null);
  const inputRef   = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  useEffect(() => {
    try { localStorage.setItem(storageKey, JSON.stringify(messages)); } catch { /* quota */ }
  }, [messages, storageKey]);

  async function send() {
    const text = input.trim();
    if (!text || loading) return;
    setInput("");

    const userMsg: ChatMessage = { id: uid(), role: "user", content: text };
    setMessages((prev) => [...prev, userMsg]);
    setLoading(true);

    const history = messages.map((m) => ({ role: m.role, content: m.content }));

    try {
      const res = await c2api.tripChat(trip.trip_id, text, history);
      const assistantMsg: ChatMessage = {
        id: uid(),
        role: "assistant",
        content: res.reply,
        suggestions: (res.suggestions as unknown as SuggestionCard[]) ?? [],
      };
      setMessages((prev) => [...prev, assistantMsg]);
    } catch {
      setMessages((prev) => [
        ...prev,
        { id: uid(), role: "assistant", content: "Something went wrong. Try again." },
      ]);
    } finally {
      setLoading(false);
      inputRef.current?.focus();
    }
  }

  async function approveSuggestion(msgId: string, idx: number, s: SuggestionCard) {
    try {
      const event = await c2api.createTripEvent(trip.trip_id, {
        title:      s.title,
        date:       s.date ?? trip.start_date,
        start_time: s.start_time ?? null,
        end_time:   s.end_time ?? null,
        location:   s.location ?? null,
        maps_link:  s.maps_link ?? null,
        notes:      s.notes ?? null,
      });
      onAddEvent(event);
      setMessages((prev) =>
        prev.map((m) =>
          m.id !== msgId ? m :
          { ...m, suggestions: m.suggestions?.map((sg, i) => i === idx ? { ...sg, added: true } : sg) }
        )
      );
    } catch {
      // fail silently — user can try again
    }
  }

  function dismissSuggestion(msgId: string, idx: number) {
    setMessages((prev) =>
      prev.map((m) =>
        m.id !== msgId ? m :
        { ...m, suggestions: m.suggestions?.map((sg, i) => i === idx ? { ...sg, dismissed: true } : sg) }
      )
    );
  }

  return (
    <div className="flex flex-col h-full">
      {/* Header */}
      <div className="px-4 py-3 border-b border-gray-800 shrink-0">
        <p className="text-white text-sm font-semibold">Trip Assistant</p>
        <p className="text-gray-500 text-xs mt-0.5">
          Tell me what you want to do — I can search places and suggest events.
        </p>
      </div>

      {/* Messages */}
      <div className="flex-1 overflow-y-auto px-4 py-4 space-y-4">
        {messages.length === 0 && (
          <div className="space-y-2">
            {[
              `Find dinner spots near ${trip.location}`,
              "Plan a full day for us on the first day",
              "Everyone needs to be at the hotel by 6 PM, what should we do before?",
              "Suggest some bars or nightlife for the last night",
            ].map((prompt) => (
              <button
                key={prompt}
                onClick={() => { setInput(prompt); }}
                className="w-full text-left bg-gray-800/60 hover:bg-gray-800 border border-gray-700/50 rounded-lg px-3 py-2 text-gray-400 text-xs transition-colors"
              >
                {prompt}
              </button>
            ))}
          </div>
        )}

        {messages.map((msg) => (
          <div key={msg.id} className={`flex flex-col ${msg.role === "user" ? "items-end" : "items-start"} gap-2`}>
            <div
              className={`rounded-xl px-3 py-2 text-sm max-w-[90%] ${
                msg.role === "user"
                  ? "bg-indigo-600 text-white"
                  : "bg-gray-800 text-gray-200"
              }`}
            >
              {msg.role === "user" ? msg.content : (
                <ReactMarkdown
                  components={{
                    p: ({ children }) => <p className="mb-1 last:mb-0">{children}</p>,
                    ul: ({ children }) => <ul className="list-disc list-inside space-y-0.5 my-1">{children}</ul>,
                    ol: ({ children }) => <ol className="list-decimal list-inside space-y-0.5 my-1">{children}</ol>,
                    li: ({ children }) => <li>{children}</li>,
                    strong: ({ children }) => <strong className="font-semibold text-white">{children}</strong>,
                    a: ({ href, children }) => (
                      <a href={href} target="_blank" rel="noopener noreferrer" className="text-indigo-400 hover:text-indigo-300 underline">
                        {children}
                      </a>
                    ),
                  }}
                >
                  {msg.content}
                </ReactMarkdown>
              )}
            </div>

            {/* Suggestion cards */}
            {msg.suggestions?.map((s, idx) => {
              if (s.dismissed) return null;
              return (
                <div
                  key={idx}
                  className={`w-full border rounded-xl p-3 space-y-1.5 transition-all ${
                    s.added
                      ? "border-green-800/50 bg-green-950/30"
                      : "border-gray-700 bg-gray-900"
                  }`}
                >
                  <p className="text-white text-sm font-semibold">{s.title}</p>
                  <div className="text-xs text-gray-400 space-y-0.5">
                    {s.date && (
                      <p>
                        {fmtDate(s.date)}
                        {s.start_time && ` · ${fmtTime(s.start_time)}`}
                        {s.end_time && ` – ${fmtTime(s.end_time)}`}
                      </p>
                    )}
                    {s.location && <p className="truncate">{s.location}</p>}
                    {s.notes && <p className="text-gray-500 italic">{s.notes}</p>}
                  </div>
                  {s.maps_link && (
                    <a href={s.maps_link} target="_blank" rel="noopener noreferrer"
                      className="text-xs text-indigo-400 hover:text-indigo-300">
                      View on Maps
                    </a>
                  )}
                  {!s.added ? (
                    <div className="flex gap-2 pt-1">
                      <button
                        onClick={() => approveSuggestion(msg.id, idx, s)}
                        className="flex-1 bg-indigo-600 hover:bg-indigo-500 text-white text-xs rounded-lg py-1.5 transition-colors"
                      >
                        Add to Itinerary
                      </button>
                      <button
                        onClick={() => dismissSuggestion(msg.id, idx)}
                        className="px-3 text-gray-500 hover:text-gray-300 text-xs transition-colors"
                      >
                        Skip
                      </button>
                    </div>
                  ) : (
                    <p className="text-green-400 text-xs pt-1">Added to itinerary</p>
                  )}
                </div>
              );
            })}
          </div>
        ))}

        {loading && (
          <div className="flex items-start">
            <div className="bg-gray-800 rounded-xl px-3 py-2 text-gray-400 text-sm">
              <span className="animate-pulse">Thinking…</span>
            </div>
          </div>
        )}
        <div ref={bottomRef} />
      </div>

      {/* Input */}
      <div className="px-3 py-3 border-t border-gray-800 shrink-0">
        <div className="flex gap-2">
          <textarea
            ref={inputRef}
            value={input}
            onChange={(e) => { setInput(e.target.value); e.target.style.height = "auto"; e.target.style.height = `${Math.min(e.target.scrollHeight, 120)}px`; }}
            onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && (e.preventDefault(), send())}
            placeholder="What do you want to do?"
            disabled={loading}
            rows={1}
            className="flex-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-indigo-500 disabled:opacity-50 resize-none overflow-hidden"
          />
          <button
            onClick={send}
            disabled={loading || !input.trim()}
            className="bg-indigo-600 hover:bg-indigo-500 disabled:opacity-40 text-white text-sm rounded-lg px-4 py-2 transition-colors shrink-0"
          >
            Send
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Main page
// ---------------------------------------------------------------------------

type FullTrip = TripRecord & { events: TripEvent[] };

export default function TripDetailPage() {
  const { id }      = useParams<{ id: string }>();
  const router      = useRouter();
  const { isAdmin, user } = useAuth();

  const [trip,        setTrip]        = useState<FullTrip | null>(null);
  const [loading,     setLoading]     = useState(true);
  const [selectedDay, setSelectedDay] = useState<string>("");
  const [showAdd,     setShowAdd]     = useState(false);
  const [driveTimes,  setDriveTimes]  = useState<Record<string, { fromId: string; toId: string; text: string }[]>>({});

  const load = useCallback(async () => {
    try {
      const data = await c2api.getTrip(id);
      setTrip(data as FullTrip);
      if (!selectedDay) {
        setSelectedDay(data.start_date);
      }
    } catch (e) {
      console.error(e);
    } finally {
      setLoading(false);
    }
  }, [id, selectedDay]);

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

  // Fetch drive times for a given day
  useEffect(() => {
    if (!trip || !selectedDay || driveTimes[selectedDay]) return;

    const dayEvents = trip.events
      .filter((e) => e.date === selectedDay && e.start_time && !e.location_inherited && e.location)
      .sort((a, b) => toMin(a.start_time!) - toMin(b.start_time!));

    if (dayEvents.length < 2) return;

    (async () => {
      const segments: { fromId: string; toId: string; text: string }[] = [];
      for (let i = 0; i < dayEvents.length - 1; i++) {
        try {
          const r = await c2api.getDirections(dayEvents[i].location, dayEvents[i + 1].location);
          if (r.duration_text) {
            segments.push({ fromId: dayEvents[i].event_id, toId: dayEvents[i + 1].event_id, text: r.duration_text });
          }
        } catch { /* skip on error */ }
      }
      if (segments.length > 0) {
        setDriveTimes((prev) => ({ ...prev, [selectedDay]: segments }));
      }
    })();
  }, [trip, selectedDay]);

  async function handleDeleteTrip() {
    if (!trip) return;
    try { await c2api.deleteTrip(trip.trip_id); router.push("/trips"); }
    catch (e) { console.error(e); }
  }

  async function handleDeleteEvent(eventId: string) {
    if (!trip) return;
    try {
      await c2api.deleteTripEvent(trip.trip_id, eventId);
      setTrip((prev) => prev ? { ...prev, events: prev.events.filter((e) => e.event_id !== eventId) } : prev);
    } catch (e) { console.error(e); }
  }

  async function handleAddEvent(body: object) {
    if (!trip) return;
    const event = await c2api.createTripEvent(trip.trip_id, body);
    setTrip((prev) => {
      if (!prev) return prev;
      const events = [...prev.events, event].sort(
        (a, b) => a.date.localeCompare(b.date) || (a.start_time ?? "").localeCompare(b.start_time ?? "")
      );
      return { ...prev, events };
    });
    // Switch to the event's day
    if ((body as { date?: string }).date) {
      setSelectedDay((body as { date: string }).date);
    }
  }

  function handleAssistantAddEvent(event: TripEvent) {
    setTrip((prev) => {
      if (!prev) return prev;
      const events = [...prev.events, event].sort(
        (a, b) => a.date.localeCompare(b.date) || (a.start_time ?? "").localeCompare(b.start_time ?? "")
      );
      return { ...prev, events };
    });
  }

  if (loading) return <p className="text-gray-500 text-sm font-mono">Loading…</p>;
  if (!trip)   return <p className="text-gray-500 text-sm font-mono">Trip not found.</p>;

  const days       = dateRange(trip.start_date, trip.end_date);
  const attendees  = Object.values(trip.attendees ?? {});
  const dayEvents  = trip.events.filter((e) => e.date === selectedDay);
  const hasConflict = (day: string) =>
    detectConflicts(trip.events.filter((e) => e.date === day)).size > 0;

  return (
    <div className="space-y-6">
      {/* Back + header */}
      <div className="space-y-4">
        <button
          onClick={() => router.push("/trips")}
          className="text-sm font-mono text-gray-500 hover:text-gray-300 transition-colors"
        >
          ← Trips
        </button>

        <div className="flex items-start justify-between gap-4 flex-wrap">
          <div className="space-y-1">
            <h1 className="text-white text-2xl font-bold">{trip.name}</h1>
            <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-gray-400">
              <span>{trip.location}</span>
              {trip.maps_link && (
                <a href={trip.maps_link} target="_blank" rel="noopener noreferrer"
                  className="text-indigo-400 hover:text-indigo-300 text-xs transition-colors">
                  Maps
                </a>
              )}
              <span className="text-gray-700">•</span>
              <span className="font-mono text-xs">{fmtDate(trip.start_date)} — {fmtDate(trip.end_date)}</span>
              {attendees.length > 0 && (
                <>
                  <span className="text-gray-700">•</span>
                  <span className="text-xs">{attendees.join(", ")}</span>
                </>
              )}
            </div>
          </div>

          <div className="flex items-center gap-3">
            {isAdmin && (
              <>
                <button
                  onClick={() => setShowAdd(true)}
                  className="bg-indigo-600 hover:bg-indigo-500 text-white text-sm rounded-lg px-4 py-2 transition-colors"
                >
                  + Add Event
                </button>
                <button
                  onClick={handleDeleteTrip}
                  className="text-xs text-red-500 hover:text-red-400 transition-colors"
                >
                  Delete trip
                </button>
              </>
            )}
          </div>
        </div>
      </div>

      {/* Two-column layout */}
      <div className="flex gap-5 items-start">
        {/* Left: Itinerary */}
        <div className="flex-1 min-w-0 space-y-5">
          {/* Day tabs */}
          <div className="flex gap-1 flex-wrap">
            {days.map((day) => {
              const { short, date } = fmtDayTab(day);
              const count    = trip.events.filter((e) => e.date === day).length;
              const conflict = hasConflict(day);
              return (
                <button
                  key={day}
                  onClick={() => setSelectedDay(day)}
                  className={`flex flex-col items-center px-3 py-2 rounded-xl text-xs transition-colors relative ${
                    day === selectedDay
                      ? "bg-indigo-600 text-white"
                      : "bg-gray-900 border border-gray-800 text-gray-400 hover:border-gray-700 hover:text-gray-200"
                  }`}
                >
                  <span className="font-mono font-bold">{short}</span>
                  <span className="font-mono">{date}</span>
                  {count > 0 && (
                    <span className={`text-xs mt-0.5 ${day === selectedDay ? "text-indigo-200" : "text-gray-600"}`}>
                      {count}
                    </span>
                  )}
                  {conflict && (
                    <span className="absolute -top-1 -right-1 w-2 h-2 bg-red-500 rounded-full" />
                  )}
                </button>
              );
            })}
          </div>

          {/* Selected day */}
          <div className="space-y-4">
            <p className="text-sm font-mono text-gray-400 uppercase tracking-wider">
              {fmtDayHeading(selectedDay)}
            </p>
            <DayTimeline
              events={dayEvents}
              isAdmin={isAdmin}
              onDelete={handleDeleteEvent}
              driveSegments={driveTimes[selectedDay] ?? []}
            />
          </div>
        </div>

        {/* Right: AI Assistant — sticky */}
        <div className="w-80 xl:w-96 shrink-0 sticky top-20 h-[calc(100vh-240px)] flex flex-col bg-gray-900 border border-gray-800 rounded-xl overflow-hidden">
          <AssistantPanel trip={trip} onAddEvent={handleAssistantAddEvent} />
        </div>
      </div>

      {/* Add event modal */}
      {showAdd && (
        <AddEventModal
          trip={trip}
          onClose={() => setShowAdd(false)}
          onAdd={handleAddEvent}
          prefill={selectedDay ? { date: selectedDay } : undefined}
        />
      )}
    </div>
  );
}
