<script lang="ts">
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
  import CreateTripModal from '$lib/components/trips/CreateTripModal.svelte';

  interface Trip {
    id: string;
    name: string;
    dates: string;
    daysAway: string;
    status: 'active' | 'upcoming' | 'completed';
    cover: string;
    duration: string;
    cities: string[];
    points?: number;
    cash?: number;
    shareToken?: string;
    sortDate: string;
  }

  let createOpen = $state(false);
  let searchQuery = $state('');
  let upcoming = $state<Trip[]>([]);
  let past = $state<Trip[]>([]);
  let stats = $state({ trips: 0, cities: 0, countries: 0, points: 0 });
  let loading = $state(true);

  const allTrips = $derived([...upcoming, ...past]);
  const nextTrip = $derived(upcoming.find((trip) => trip.status === 'upcoming') || upcoming[0] || null);
  const activeTrip = $derived(upcoming.find((trip) => trip.status === 'active') || null);
  const leadTrip = $derived(activeTrip || nextTrip);
  const searchResults = $derived(
    searchQuery.trim()
      ? allTrips.filter((trip) =>
          trip.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
          trip.cities.some((city) => city.toLowerCase().includes(searchQuery.toLowerCase()))
        )
      : null
  );
  const completedCount = $derived(past.length);
  const openTripCount = $derived(upcoming.length);
  function formatPoints(n: number): string {
    if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
    if (n >= 1000) return Math.round(n / 1000) + 'K';
    return n.toString();
  }

  function formatDateRange(start: string, end: string): string {
    if (!start) return '';
    const s = new Date(start + 'T00:00:00');
    const e = new Date(end + 'T00:00:00');
    const sMonth = s.toLocaleDateString('en-US', { month: 'short' });
    const eMonth = e.toLocaleDateString('en-US', { month: 'short' });
    const sYear = s.getFullYear();
    const eYear = e.getFullYear();
    if (sMonth === eMonth && sYear === eYear) {
      return `${sMonth} ${s.getDate()} – ${e.getDate()}, ${sYear}`;
    }
    if (sYear === eYear) {
      return `${sMonth} ${s.getDate()} – ${eMonth} ${e.getDate()}, ${sYear}`;
    }
    return `${sMonth} ${s.getDate()}, ${sYear} – ${eMonth} ${e.getDate()}, ${eYear}`;
  }

  function daysBetween(dateStr: string): string {
    const d = new Date(dateStr + 'T00:00:00');
    const now = new Date();
    now.setHours(0, 0, 0, 0);
    const diff = Math.ceil((d.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
    if (diff <= 0) return '';
    if (diff === 1) return '1 day';
    return `${diff} days`;
  }

  function durationDays(start: string, end: string): string {
    if (!start || !end) return '';
    const s = new Date(start + 'T00:00:00');
    const e = new Date(end + 'T00:00:00');
    const days = Math.ceil((e.getTime() - s.getTime()) / (1000 * 60 * 60 * 24)) + 1;
    return `${days} days`;
  }

  function coverUrl(trip: any): string {
    if (trip.cover_image) return trip.cover_image;
    return '';
  }

  function mapTrip(raw: any): Trip {
    const now = new Date().toISOString().slice(0, 10);
    const isActive = raw.start_date <= now && raw.end_date >= now;
    const isUpcoming = raw.start_date > now;
    return {
      id: raw.id,
      name: raw.name,
      dates: formatDateRange(raw.start_date, raw.end_date),
      daysAway: isUpcoming ? daysBetween(raw.start_date) : '',
      status: isActive ? 'active' : isUpcoming ? 'upcoming' : 'completed',
      cover: coverUrl(raw),
      duration: durationDays(raw.start_date, raw.end_date),
      cities: [],
      points: 0,
      cash: 0,
      shareToken: raw.share_token || '',
      sortDate: raw.start_date || ''
    };
  }

  async function loadTrips() {
    loading = true;
    try {
      const [tripsRes, statsRes] = await Promise.all([
        fetch('/api/trips/trips', { credentials: 'include' }),
        fetch('/api/trips/stats', { credentials: 'include' })
      ]);

      if (tripsRes.ok) {
        const data = await tripsRes.json();
        const all = (data.trips || []).map(mapTrip);
        upcoming = all
          .filter((trip) => trip.status === 'active' || trip.status === 'upcoming')
          .sort((a, b) => a.sortDate.localeCompare(b.sortDate));
        past = all
          .filter((trip) => trip.status === 'completed')
          .sort((a, b) => b.sortDate.localeCompare(a.sortDate));
      }

      if (statsRes.ok) {
        const data = await statsRes.json();
        stats = {
          trips: data.total_trips || 0,
          cities: data.cities_visited || 0,
          countries: data.countries_visited || 0,
          points: data.total_points_redeemed || 0
        };
      }
    } catch {
      // keep route stable
    } finally {
      loading = false;
    }
  }

  onMount(loadTrips);
</script>

<div class="trips-page">
  <section class="journey-hero reveal">
    <div class="hero-copy">
      <h1>Trips</h1>
    </div>

    <div class="hero-actions">
      <button class="hero-button primary" onclick={() => (createOpen = true)}>Plan trip</button>
    </div>
  </section>

  <section class="stats-grid reveal">
    <div class="stat-tile">
      <div class="stat-value">{loading ? '…' : stats.trips}</div>
      <div class="stat-label">Trips</div>
    </div>
    <div class="stat-tile">
      <div class="stat-value">{loading ? '…' : stats.cities}</div>
      <div class="stat-label">Cities</div>
    </div>
    <div class="stat-tile">
      <div class="stat-value">{loading ? '…' : stats.countries}</div>
      <div class="stat-label">Countries</div>
    </div>
    <div class="stat-tile">
      <div class="stat-value">{loading ? '…' : formatPoints(stats.points)}</div>
      <div class="stat-label">Points used</div>
    </div>
  </section>

  <section class="search-band reveal">
    <div class="search-wrap">
      <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
      <input class="search-input" type="text" placeholder="Search trips, cities, hotels, routes..." bind:value={searchQuery} />
      {#if searchQuery}
        <button class="search-clear" onclick={() => (searchQuery = '')}>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      {/if}
    </div>
  </section>

  <div class="trips-grid">
    <section class="journey-column reveal">
      {#if searchResults}
        <div class="section-head">
          <div>
            <div class="section-label">Search</div>
            <h2>Matching trips</h2>
          </div>
        </div>

        <div class="journey-list">
          {#each searchResults as trip (trip.id)}
            <a class="journey-row" class:muted={trip.status === 'completed'} href={`/trips/trip?id=${trip.id}`}>
              <div class="journey-cover" style={trip.cover ? `background-image:url('${trip.cover}')` : ''}>
                {#if !trip.cover}
                  <div class="journey-cover-empty">{trip.name.charAt(0)}</div>
                {/if}
              </div>
              <div class="journey-main">
                <div class="journey-meta">
                  <span class={`status-pill ${trip.status}`}>{trip.status === 'completed' ? 'Completed' : trip.status === 'active' ? 'Active now' : 'Upcoming'}</span>
                  <span>{trip.dates}</span>
                  {#if trip.daysAway}<span>{trip.daysAway}</span>{/if}
                </div>
                <div class="journey-name">{trip.name}</div>
                <div class="journey-notes">{trip.duration}{#if trip.points} · {formatPoints(trip.points)} pts{/if}</div>
              </div>
            </a>
          {/each}
        </div>
      {:else}
        <div class="section-head">
          <div>
            <h2>Upcoming</h2>
          </div>
        </div>

        <div class="journey-list">
          {#if upcoming.length === 0}
            <div class="journey-empty">No live itinerary. Start a new trip to build the travel board.</div>
          {:else}
            {#each upcoming as trip (trip.id)}
              <a class="journey-row featured" href={`/trips/trip?id=${trip.id}`}>
                <div class="journey-cover large" style={trip.cover ? `background-image:url('${trip.cover}')` : ''}>
                  {#if !trip.cover}
                    <div class="journey-cover-empty">{trip.name.charAt(0)}</div>
                  {/if}
                </div>
                <div class="journey-main">
                  <div class="journey-meta">
                    <span class={`status-pill ${trip.status}`}>{trip.status === 'active' ? 'Active now' : 'Upcoming'}</span>
                    <span>{trip.dates}</span>
                    {#if trip.daysAway}<span>{trip.daysAway}</span>{/if}
                  </div>
                  <div class="journey-name">{trip.name}</div>
                  <div class="journey-notes">{trip.duration}{#if trip.points} · {formatPoints(trip.points)} pts{/if}</div>
                  <div class="journey-open">Open itinerary</div>
                </div>
              </a>
            {/each}
          {/if}
        </div>

        <div class="section-head archive">
          <div>
            <h2>Past trips</h2>
          </div>
        </div>

        <div class="journey-list compact">
          {#each past as trip (trip.id)}
            <a class="journey-row muted compact-row" href={`/trips/trip?id=${trip.id}`}>
              <div class="journey-cover compact" style={trip.cover ? `background-image:url('${trip.cover}')` : ''}>
                {#if !trip.cover}
                  <div class="journey-cover-empty">{trip.name.charAt(0)}</div>
                {/if}
              </div>
              <div class="journey-main">
                <div class="journey-meta">
                  <span class="status-pill completed">Completed</span>
                  <span>{trip.dates}</span>
                </div>
                <div class="journey-name">{trip.name}</div>
                <div class="journey-notes">{trip.duration}{#if trip.cash} · ${trip.cash.toLocaleString()}{/if}</div>
              </div>
            </a>
          {/each}
        </div>
      {/if}
    </section>

  </div>
</div>

<CreateTripModal bind:open={createOpen} onCreated={(id) => goto(`/trips/trip?id=${id}`)} />

<style>
  .trips-page {
    display: grid;
    gap: 18px;
    color: #1f1811;
  }

  .journey-hero,
  .search-band {
    background: rgba(250, 244, 236, 0.72);
    border: 1px solid rgba(35, 26, 17, 0.08);
    border-radius: 28px;
    backdrop-filter: blur(16px);
  }

  .journey-hero {
    padding: 22px 24px;
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 18px;
    background:
      radial-gradient(circle at top left, rgba(214, 126, 59, 0.14), transparent 30%),
      linear-gradient(135deg, rgba(252, 246, 239, 0.96), rgba(241, 231, 220, 0.88));
  }

  .hero-copy {
    display: grid;
    gap: 0;
    max-width: 42rem;
  }

  .section-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: #8a7868;
  }

  .journey-hero h1,
  .section-head h2 {
    margin: 0;
    letter-spacing: -0.055em;
    color: #1c140c;
  }

  .journey-hero h1 {
    font-size: clamp(2.6rem, 5vw, 4.2rem);
    line-height: 0.92;
  }

  .hero-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
  }

  .hero-button,
  .inline-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    text-decoration: none;
    transition: all 160ms ease;
  }

  .hero-button {
    padding: 11px 16px;
    font-size: 0.92rem;
    font-weight: 600;
    border: 1px solid rgba(35, 26, 17, 0.08);
  }

  .hero-button.primary {
    background: #2f241c;
    color: #fff7ee;
  }

  .stats-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
  }

  .stat-tile {
    display: grid;
    gap: 4px;
    padding: 14px 12px;
    border-radius: 20px;
    background: rgba(255, 251, 246, 0.7);
    border: 1px solid rgba(35, 26, 17, 0.07);
    text-align: center;
  }

  .stat-value {
    font-size: 1.3rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
    color: #1f1811;
  }

  .stat-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #7c6b5c;
  }

  .search-band {
    padding: 14px 18px;
  }

  .search-wrap {
    position: relative;
    flex: 1;
  }

  .search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    width: 16px;
    height: 16px;
    color: #857464;
    transform: translateY(-50%);
    pointer-events: none;
  }

  .search-input {
    width: 100%;
    padding: 13px 44px 13px 42px;
    border-radius: 18px;
    border: 1px solid rgba(35, 26, 17, 0.08);
    background: rgba(255, 251, 246, 0.88);
    color: #241c15;
    font-size: 0.98rem;
  }

  .search-clear {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: #857464;
  }

  .search-clear svg {
    width: 16px;
    height: 16px;
  }

  .trips-grid {
    display: block;
  }

  .journey-column {
    padding: 0;
  }

  .section-head {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
  }

  .section-head h2 {
    font-size: 1.7rem;
    line-height: 0.98;
  }

  .section-head.archive {
    margin-top: 22px;
  }

  .journey-list {
    display: grid;
    gap: 12px;
  }

  .journey-row {
    display: grid;
    grid-template-columns: 200px minmax(0, 1fr);
    gap: 16px;
    padding: 14px;
    border-radius: 22px;
    background: linear-gradient(135deg, rgba(255, 249, 243, 0.94), rgba(241, 230, 219, 0.86));
    border: 1px solid rgba(35, 26, 17, 0.07);
    color: inherit;
    text-decoration: none;
    transition: transform 160ms ease, box-shadow 160ms ease;
  }

  .journey-row:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 30px rgba(41, 28, 17, 0.07);
  }

  .journey-row.muted {
    opacity: 0.72;
  }

  .journey-row.compact-row {
    grid-template-columns: 92px minmax(0, 1fr);
    padding: 12px;
  }

  .journey-cover {
    border-radius: 18px;
    background: rgba(229, 218, 206, 0.84) center/cover no-repeat;
    min-height: 128px;
    overflow: hidden;
  }

  .journey-cover.large {
    min-height: 152px;
  }

  .journey-cover.compact {
    min-height: 84px;
  }

  .journey-cover-empty {
    width: 100%;
    height: 100%;
    display: grid;
    place-items: center;
    font-size: 2rem;
    font-weight: 700;
    color: #8a7868;
  }

  .journey-main {
    min-width: 0;
    display: grid;
    align-content: start;
    gap: 8px;
  }

  .journey-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.78rem;
    color: #7c6b5c;
  }

  .status-pill {
    display: inline-flex;
    align-items: center;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .status-pill.active {
    background: rgba(74, 101, 83, 0.14);
    color: #465f50;
  }

  .status-pill.upcoming {
    background: rgba(167, 111, 67, 0.14);
    color: #8d5b35;
  }

  .status-pill.completed {
    background: rgba(35, 26, 17, 0.08);
    color: #685c51;
  }

  .journey-name {
    font-size: 1.46rem;
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.04em;
    color: #1c140c;
  }

  .journey-notes,
  .journey-open,
  .journey-empty {
    color: #605447;
  }

  .journey-open {
    font-size: 0.88rem;
    font-weight: 600;
  }

  .journey-empty {
    padding: 20px;
    border-radius: 20px;
    background: rgba(255, 250, 245, 0.7);
    border: 1px dashed rgba(35, 26, 17, 0.11);
  }

  @media (max-width: 1100px) {
    .trips-grid { display: block; }
  }

  @media (max-width: 768px) {
    .trips-page {
      gap: 16px;
      padding-inline: 16px;
    }

    .journey-hero,
    .search-band {
      border-radius: 24px;
    }

    .journey-hero {
      padding: 16px;
      align-items: start;
      gap: 14px;
    }

    .stats-grid {
      grid-template-columns: 1fr 1fr;
      gap: 8px;
    }

    .stat-tile {
      padding: 12px 10px;
      border-radius: 18px;
    }

    .stat-value {
      font-size: 1.12rem;
    }

    .hero-actions,
    .search-band {
      display: grid;
    }

    .hero-actions {
      width: auto;
      gap: 8px;
    }

    .hero-copy {
      gap: 0;
      max-width: none;
    }

    .journey-hero h1 {
      font-size: clamp(2.2rem, 10vw, 3rem);
      line-height: 0.95;
    }

    .hero-button {
      min-height: 44px;
      padding: 0 14px;
      font-size: 0.88rem;
    }

    .search-band {
      padding: 14px 16px;
    }

    .journey-row,
    .journey-row.compact-row {
      grid-template-columns: 1fr;
      padding: 12px;
    }

    .journey-cover,
    .journey-cover.large,
    .journey-cover.compact {
      min-height: 160px;
    }

    .journey-name {
      font-size: 1.2rem;
    }

    .section-head {
      align-items: start;
      gap: 10px;
    }

    .journey-column { padding: 0; }
  }
</style>
