---
export const prerender = false;

import { isAuthenticated, ADMIN_COOKIE } from '@admin/lib/admin-auth';
import {
  buildPersonMetadataIdProjectionSql,
  buildPersonMetadataIdentitySql,
  remapPersonMetadataFields,
} from '@/lib/catalog-metadata';

interface Env { DB: D1Database }
const runtime = Astro.locals.runtime as { env: Env } | undefined;
const db = runtime?.env?.DB;
if (!db || !await isAuthenticated(Astro.cookies.get(ADMIN_COOKIE)?.value, db)) {
  return Astro.redirect('/admin/login', 302);
}

const q = (Astro.url.searchParams.get('q') ?? '').trim();
const typeParam = (Astro.url.searchParams.get('type') ?? 'all').toLowerCase();
const type = typeParam === 'cast' || typeParam === 'crew' ? typeParam : 'all';
const page = Math.max(parseInt(Astro.url.searchParams.get('page') ?? '1', 10) || 1, 1);
const limit = 50;
const offset = (page - 1) * limit;

type CastRow = {
  person_metadata_id: string | null;
  person_name: string;
  credit_type: 'cast' | 'crew';
  primary_job: string;
  credit_count: number;
  title_count: number;
  primary_count: number;
  last_seen: string | null;
  titles_csv: string | null;
};

let rows: CastRow[] = [];
let total = 0;
let dbError: string | null = null;

try {
  const whereParts: string[] = ['1 = 1'];
  const whereParams: Array<string | number> = [];
  if (q) {
    whereParts.push('tc.person_name LIKE ?');
    whereParams.push(`%${q}%`);
  }
  if (type !== 'all') {
    whereParts.push('tc.credit_type = ?');
    whereParams.push(type);
  }

  const where = whereParts.join(' AND ');
  const countSQL = `
    SELECT COUNT(*) AS total FROM (
       SELECT 1
         FROM title_credits tc
        WHERE ${where}
        GROUP BY ${buildPersonMetadataIdentitySql('tc')}, tc.person_name, tc.credit_type
    )
  `;

  const dataSQL = `
    SELECT
      ${buildPersonMetadataIdProjectionSql('tc')},
      tc.person_name,
      tc.credit_type,
      MAX(CASE WHEN tc.credit_type = 'crew' THEN tc.job ELSE '' END) AS primary_job,
      COUNT(*) AS credit_count,
      COUNT(DISTINCT tc.title_id) AS title_count,
      SUM(CASE WHEN tc.is_primary = 1 THEN 1 ELSE 0 END) AS primary_count,
      MAX(tc.updated_at) AS last_seen,
      GROUP_CONCAT(DISTINCT t.title_en) AS titles_csv
    FROM title_credits tc
    LEFT JOIN titles t ON t.id = tc.title_id
    WHERE ${where}
    GROUP BY ${buildPersonMetadataIdentitySql('tc')}, tc.person_name, tc.credit_type
    ORDER BY primary_count DESC, title_count DESC, tc.person_name ASC
    LIMIT ? OFFSET ?
  `;

  const [countRes, dataRes] = await db.batch([
    db.prepare(countSQL).bind(...whereParams),
    db.prepare(dataSQL).bind(...whereParams, limit, offset),
  ]);

  total = Number((countRes.results[0] as { total?: number } | undefined)?.total ?? 0);
  rows = (dataRes.results ?? []).map((row) => remapPersonMetadataFields(row as Record<string, unknown>)) as CastRow[];
} catch (err) {
  dbError = String(err);
}

const totalPages = Math.max(1, Math.ceil(total / limit));
const hasPrev = page > 1;
const hasNext = page < totalPages;

function queryFor(nextPage: number): string {
  const params = new URLSearchParams();
  if (q) params.set('q', q);
  if (type !== 'all') params.set('type', type);
  if (nextPage > 1) params.set('page', String(nextPage));
  const qs = params.toString();
  return qs ? `?${qs}` : '';
}
---
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Cast &amp; Credits — CultRoll Admin</title>
  <style>
    :root { --bg: #0f0f0f; --surface: #141414; --surface2: #1a1a1a; --border: #2a2a2a; --text: #e0e0e0; --muted: #8a8a8a; --gold: #b07d2e; --green: #3ea06a; --blue: #4a7fb9; }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { background: var(--bg); color: var(--text); font-family: system-ui, sans-serif; font-size: 14px; }
    a { color: var(--gold); text-decoration: none; }
    a:hover { text-decoration: underline; }
    .nav { display: flex; gap: 1rem; padding: 1rem 1.5rem; border-bottom: 1px solid var(--border); background: var(--surface); align-items: center; }
    .nav strong { color: var(--gold); margin-right: auto; font-size: 1rem; }
    .nav a { color: var(--muted); font-size: 13px; }
    .nav a:hover { color: var(--text); text-decoration: none; }
    .page { padding: 1.25rem 1.5rem 2rem; }
    h1 { font-size: 1.2rem; margin-bottom: .65rem; }
    .sub { color: var(--muted); font-size: .83rem; margin-bottom: 1rem; }
    .filters { display: grid; grid-template-columns: minmax(220px, 1fr) 160px auto; gap: .6rem; margin-bottom: .8rem; align-items: end; }
    .field label { display: block; font-size: .72rem; color: #777; margin-bottom: .28rem; text-transform: uppercase; letter-spacing: .05em; }
    .field input, .field select { width: 100%; background: var(--surface2); border: 1px solid var(--border); color: var(--text); border-radius: 5px; padding: .38rem .5rem; font-size: .82rem; }
    .field input:focus, .field select:focus { outline: none; border-color: var(--gold); }
    .btn { background: var(--surface2); border: 1px solid var(--border); color: var(--text); border-radius: 5px; padding: .4rem .8rem; font-size: .8rem; cursor: pointer; }
    .btn:hover { border-color: var(--gold); color: var(--gold); }
    .meta { margin-bottom: .6rem; color: #777; font-size: .78rem; }
    .tbl-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 8px; }
    table { width: 100%; border-collapse: collapse; }
    th { text-align: left; font-size: 11px; color: #737373; text-transform: uppercase; letter-spacing: .06em; padding: .5rem .65rem; background: var(--surface); border-bottom: 1px solid var(--border); white-space: nowrap; }
    td { padding: .52rem .65rem; border-bottom: 1px solid var(--border); vertical-align: top; font-size: .82rem; }
    tr:hover td { background: rgba(255,255,255,.02); }
    .name { font-weight: 600; color: #f0f0f0; }
    .dim { color: #8a8a8a; font-size: .75rem; }
    .badge { display: inline-block; padding: 2px 7px; border-radius: 100px; font-size: 11px; font-weight: 700; text-transform: uppercase; }
    .badge-cast { color: var(--green); background: rgba(62,160,106,.18); border: 1px solid rgba(62,160,106,.35); }
    .badge-crew { color: var(--blue); background: rgba(74,127,185,.18); border: 1px solid rgba(74,127,185,.35); }
    .titles { color: #9b9b9b; max-width: 440px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .empty { text-align: center; color: #777; padding: 2rem 1rem; }
    .pager { margin-top: .7rem; display: flex; align-items: center; justify-content: space-between; gap: .6rem; color: #777; font-size: .78rem; }
    .pager .links { display: flex; gap: .4rem; }
    .pager a { padding: .28rem .6rem; border: 1px solid var(--border); border-radius: 4px; color: #b0b0b0; text-decoration: none; }
    .pager a:hover { border-color: var(--gold); color: var(--gold); }
    .db-error { background: #2a1010; border: 1px solid #5a2020; border-radius: 8px; padding: .8rem 1rem; color: #f87171; margin-bottom: .9rem; font-size: .82rem; }
  </style>
</head>
<body>
  <nav class="nav">
    <strong>CultRoll Admin</strong>
    <a href="/admin">Dashboard</a>
    <a href="/admin/titles">Titles</a>
    <a href="/admin/cast" style="color:var(--text)">Cast</a>
    <a href="/admin/genres">Genres</a>
    <a href="/admin/scrapers">Sources</a>
    <a href="/admin/cinemas">Cinemas</a>
    <a href="/admin/pipelines">Pipeline Jobs</a>
    <a href="/admin/runs">Runs</a>
    <a href="/admin/logout">Logout</a>
  </nav>

  <main class="page">
    <h1>Cast &amp; Credits</h1>
    <p class="sub">Aggregated cast and crew mapped from the metadata catalog.</p>

    {dbError && <div class="db-error">DB error: {dbError}</div>}

    <form method="GET" class="filters">
      <div class="field">
        <label for="q">Search Person</label>
        <input id="q" name="q" type="search" value={q} placeholder="Name…" />
      </div>
      <div class="field">
        <label for="type">Type</label>
        <select id="type" name="type">
          <option value="all" selected={type === 'all'}>All</option>
          <option value="cast" selected={type === 'cast'}>Cast</option>
          <option value="crew" selected={type === 'crew'}>Crew</option>
        </select>
      </div>
      <div>
        <button type="submit" class="btn">Apply</button>
      </div>
    </form>

    <div class="meta">{total.toLocaleString()} people · page {page} / {totalPages}</div>

    <div class="tbl-wrap">
      <table>
        <thead>
          <tr>
            <th>Person</th>
            <th>Type</th>
            <th>Primary Role</th>
            <th style="text-align:right">Titles</th>
            <th style="text-align:right">Credits</th>
            <th style="text-align:right">Primary</th>
            <th>Sample Titles</th>
            <th>Last Seen</th>
          </tr>
        </thead>
        <tbody>
          {rows.length === 0 && (
            <tr><td colspan="8" class="empty">No cast/crew rows found.</td></tr>
          )}
          {rows.map((row) => {
            const sampleTitles = (row.titles_csv ?? '').split(',').map((x) => x.trim()).filter(Boolean).slice(0, 3).join(' • ');
            return (
              <tr>
                <td>
                    <div class="name">
                      {row.person_name}
                    {row.person_metadata_id && (
                      <>
                        {' '}
                        <span class="dim">#{row.person_metadata_id}</span>
                      </>
                    )}
                  </div>
                </td>
                <td>
                  <span class={`badge ${row.credit_type === 'cast' ? 'badge-cast' : 'badge-crew'}`}>{row.credit_type}</span>
                </td>
                <td>{row.primary_job || (row.credit_type === 'cast' ? 'Cast' : '—')}</td>
                <td style="text-align:right">{row.title_count}</td>
                <td style="text-align:right">{row.credit_count}</td>
                <td style="text-align:right">{row.primary_count}</td>
                <td class="titles">{sampleTitles || '—'}</td>
                <td class="dim">{row.last_seen ? row.last_seen.replace('T', ' ').replace('Z', '') : '—'}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>

    <div class="pager">
      <span>Showing {rows.length ? `${offset + 1}-${offset + rows.length}` : '0'} of {total.toLocaleString()}</span>
      <div class="links">
        {hasPrev ? <a href={queryFor(page - 1)}>← Prev</a> : <span class="dim">← Prev</span>}
        {hasNext ? <a href={queryFor(page + 1)}>Next →</a> : <span class="dim">Next →</span>}
      </div>
    </div>
  </main>
</body>
</html>
