import { useLoaderData, useSearchParams, Link, Form } from "react-router";
import { queryEvents, getVenues, type CapacityRange } from "~/lib/db.server";
import type { Event } from "~/lib/db.server";
import { useVenueFilter } from "~/lib/venue-filter";

function todayJst(): string {
  // JST = UTC+9
  const now = new Date();
  const jst = new Date(now.getTime() + 9 * 60 * 60 * 1000);
  return jst.toISOString().slice(0, 10);
}

function addDays(iso: string, delta: number): string {
  const d = new Date(`${iso}T00:00:00Z`);
  d.setUTCDate(d.getUTCDate() + delta);
  return d.toISOString().slice(0, 10);
}

function formatDateJa(iso: string): string {
  const [y, m, d] = iso.split("-");
  const days = ["日", "月", "火", "水", "木", "金", "土"];
  const dayIdx = new Date(`${iso}T00:00:00`).getDay();
  return `${y}/${m}/${d}（${days[dayIdx]}）`;
}

function buildTimeLabel(open: string | null, start: string | null): string {
  const parts: string[] = [];
  if (open) parts.push(`OPEN ${open}`);
  if (start) parts.push(`START ${start}`);
  return parts.join(" / ");
}

export async function loader({ request }: { request: Request }) {
  const url = new URL(request.url);
  const date = url.searchParams.get("date") ?? todayJst();
  const keyword = url.searchParams.get("keyword") ?? undefined;
  const venue_id = url.searchParams.get("venue_id") ?? undefined;
  const capacity_range = (url.searchParams.get("capacity_range") ?? undefined) as CapacityRange | undefined;
  const area = url.searchParams.get("area") ?? undefined;

  const events = queryEvents({ date_from: date, date_to: date, keyword, venue_id, capacity_range, area, limit: 500 });
  const venues = getVenues();
  const areas = [...new Set(venues.filter((v) => v.area).map((v) => v.area as string))].sort();

  const byVenue = new Map<string, Event[]>();
  for (const event of events) {
    if (!byVenue.has(event.venue_id)) byVenue.set(event.venue_id, []);
    byVenue.get(event.venue_id)!.push(event);
  }

  const groups = venues
    .filter((v) => byVenue.has(v.id))
    .map((v) => ({ venue: v, events: byVenue.get(v.id)! }));

  return { date, groups, totalEvents: events.length, venues, areas };
}

export default function EventsByDate() {
  const { date, groups, totalEvents, venues, areas } = useLoaderData<typeof loader>();
  const [searchParams] = useSearchParams();
  const { hiddenIds } = useVenueFilter();

  const hasVenueFilter = !!searchParams.get("venue_id");
  const visibleGroups = hasVenueFilter
    ? groups
    : groups.filter((g) => !hiddenIds.has(g.venue.id));
  const hiddenCount = groups.length - visibleGroups.length;

  function dateUrl(d: string) {
    const p = new URLSearchParams(searchParams);
    p.set("date", d);
    return `?${p.toString()}`;
  }

  const hasFilters = ["keyword", "venue_id", "capacity_range", "area"].some(
    (k) => searchParams.get(k)
  );

  const prevDay = addDays(date, -1);
  const nextDay = addDays(date, 1);

  return (
    <div className="min-h-screen bg-gray-950 text-gray-100">
      <header className="border-b border-gray-800 px-4 sm:px-6 py-3 sm:py-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 sm:gap-0">
        <Link to="/" className="text-xl font-bold tracking-tight text-white">
          🎸 ライブに行くしかない
        </Link>
        <nav className="flex gap-4 sm:gap-6 text-sm text-gray-400">
          <Link to="/events" className="hover:text-white transition-colors">イベント</Link>
          <Link to="/events/by-date" className="text-white">日付別</Link>
          <Link to="/venues" className="hover:text-white transition-colors">会場一覧</Link>
        </nav>
      </header>

      <main className="max-w-4xl mx-auto px-4 py-8">
        {/* Date navigation */}
        <div className="mb-6 flex items-center justify-between">
          <Link
            to={dateUrl(prevDay)}
            className="rounded-lg bg-gray-800 px-4 py-2 text-sm hover:bg-gray-700 transition-colors"
          >
            ← 前日
          </Link>

          <div className="flex flex-col items-center gap-2">
            <h1 className="text-2xl font-bold">{formatDateJa(date)}</h1>
            <div className="flex items-center gap-2">
              <input
                type="date"
                value={date}
                onChange={(e) => {
                  if (e.target.value) window.location.href = dateUrl(e.target.value);
                }}
                className="rounded bg-gray-800 border border-gray-700 px-2 py-1 text-sm text-gray-200 focus:outline-none focus:border-indigo-500"
              />
            </div>
          </div>

          <Link
            to={dateUrl(nextDay)}
            className="rounded-lg bg-gray-800 px-4 py-2 text-sm hover:bg-gray-700 transition-colors"
          >
            翌日 →
          </Link>
        </div>

        {/* Filter bar */}
        <Form method="get" className="mb-6 flex flex-wrap gap-3 items-end">
          <input type="hidden" name="date" value={date} />

          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-400">キーワード</label>
            <input
              name="keyword"
              type="text"
              defaultValue={searchParams.get("keyword") ?? ""}
              placeholder="アーティスト名、イベント名..."
              className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 w-full sm:w-44"
            />
          </div>

          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-400">会場</label>
            <select
              name="venue_id"
              defaultValue={searchParams.get("venue_id") ?? ""}
              className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500"
            >
              <option value="">すべて</option>
              {venues.map((v) => (
                <option key={v.id} value={v.id}>{v.name}</option>
              ))}
            </select>
          </div>

          {areas.length > 0 && (
            <div className="flex flex-col gap-1">
              <label className="text-xs text-gray-400">エリア</label>
              <select
                name="area"
                defaultValue={searchParams.get("area") ?? ""}
                className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500"
              >
                <option value="">すべて</option>
                {areas.map((a) => (
                  <option key={a} value={a}>{a}</option>
                ))}
              </select>
            </div>
          )}

          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-400">キャパシティ</label>
            <select
              name="capacity_range"
              defaultValue={searchParams.get("capacity_range") ?? ""}
              className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500"
            >
              <option value="">すべて</option>
              <option value="small">〜100人（小箱）</option>
              <option value="medium">100〜300人（中箱）</option>
              <option value="large">300人〜（大箱）</option>
            </select>
          </div>

          <button
            type="submit"
            className="rounded-md bg-gray-700 px-4 py-1.5 text-sm font-medium hover:bg-gray-600 transition-colors"
          >
            絞り込む
          </button>

          {hasFilters && (
            <a
              href={`/events/by-date?date=${date}`}
              className="rounded-md border border-gray-700 px-4 py-1.5 text-sm text-gray-400 hover:text-white transition-colors"
            >
              クリア
            </a>
          )}
        </Form>

        {/* Summary */}
        {totalEvents > 0 && (
          <p className="mb-6 text-sm text-gray-500">
            {visibleGroups.length} 会場 ／ {totalEvents} イベント
            {hiddenCount > 0 && (
              <> — <Link to="/venues" className="text-indigo-400 hover:text-indigo-300 underline">{hiddenCount} 会場非表示</Link></>
            )}
          </p>
        )}

        {/* Venue groups */}
        {visibleGroups.length === 0 ? (
          <div className="mt-16 text-center text-gray-500">
            <p className="text-lg">この日のイベントはありません</p>
            <p className="mt-2 text-sm">
              スクレイパーを実行してデータを取得してください:{" "}
              <code className="text-gray-400">npm run scrape</code>
            </p>
          </div>
        ) : (
          <div className="flex flex-col gap-8">
            {visibleGroups.map(({ venue, events }) => (
              <section key={venue.id}>
                <div className="mb-3 flex items-baseline gap-2">
                  <h2 className="text-lg font-semibold text-white">
                    {venue.name}
                  </h2>
                  {venue.area && (
                    <span className="text-xs text-gray-500">{venue.area}</span>
                  )}
                  <span className="ml-auto text-xs text-gray-600">
                    {events.length} 件
                  </span>
                </div>

                <div className="flex flex-col gap-1.5">
                  {events.map((event) => (
                    <VenueEventRow key={event.id} event={event} />
                  ))}
                </div>
              </section>
            ))}
          </div>
        )}
      </main>
    </div>
  );
}

function VenueEventRow({ event }: { event: Event }) {
  const timeLabel = buildTimeLabel(event.open_time, event.start_time);

  return (
    <Link
      to={`/events/${event.id}`}
      className="group flex items-start gap-4 rounded-lg px-4 py-3 bg-gray-800/40 border border-gray-700/30 hover:border-indigo-500/50 hover:bg-gray-800/70 transition-all"
    >
      {/* Time */}
      <span className="w-20 sm:w-28 shrink-0 text-xs text-gray-400 tabular-nums pt-0.5">
        {timeLabel || <span className="text-gray-600">時間未定</span>}
      </span>

      {/* Title + artist */}
      <span className="flex-1 min-w-0">
        <span className="block truncate text-sm font-medium text-gray-100 group-hover:text-indigo-300 transition-colors">
          {event.title}
        </span>
        {event.artist && (
          <span className="block truncate text-xs text-indigo-300/80 mt-0.5">
            {event.artist}
          </span>
        )}
      </span>

      {/* Price */}
      {event.price ? (
        <span className="hidden sm:block shrink-0 text-xs text-emerald-400 pt-0.5">
          ¥{event.price}
        </span>
      ) : (
        <span className="hidden sm:block shrink-0 w-16" />
      )}
    </Link>
  );
}
