/**
 * Chain Poster Enricher
 *
 * Fetches poster images directly from cinema chain websites for movies that:
 *   - Have no poster_url (TMDB couldn't match them or had no image)
 *   - Have a chain_movie_refs entry for 'grand-cinemas-lb' or 'grand-cinemas-jo'
 *     (Grand doesn't include posters in its API; we reconstruct the movie detail URL)
 *
 * Empire and Taj already capture poster_url in their scrapers so no fallback needed.
 */

import { buildRemoteImageProxyPath } from '../../../src/sites/cultroll/lib/image-proxy';
import { mapWithConcurrency } from '../utils/concurrency';
import { fetchWithTimeout } from '../utils/http';

const CHAIN_POSTER_CONCURRENCY = 4;

export interface ChainPosterResult {
  updated: number;
  failed: number;
  skipped: number;
}

interface PosterlessMovie {
  id: string;
  chain_id: string;
  chain_movie_id: string;
}

/** Extract og:image or first large <img> src from an HTML page */
function extractPoster(html: string): string | null {
  // Prefer og:image meta tag
  const og = html.match(/<meta[^>]+property=["']og:image["'][^>]+content=["']([^"']+)["']/i)
    ?? html.match(/<meta[^>]+content=["']([^"']+)["'][^>]+property=["']og:image["']/i);
  if (og?.[1]) return og[1];

  // Fallback: look for a large movie poster image in common Grand Cinema HTML patterns
  const img = html.match(/<img[^>]+src=["']([^"']*(?:poster|movie|film|MovieImages)[^"']*)["']/i);
  if (img?.[1]) return img[1];

  return null;
}

function buildChainUrl(chainId: string, chainMovieId: string): string | null {
  if (chainId !== 'grand-cinemas') return null;
  // chainMovieId format: "lb:0000000046" or "jo:0000000046"
  const colonIdx = chainMovieId.indexOf(':');
  if (colonIdx === -1) return null;
  const region = chainMovieId.slice(0, colonIdx);
  const externalId = chainMovieId.slice(colonIdx + 1);
  if (region === 'lb') {
    return `https://lb.grandcinemasme.com/en/NowShowing/MovieDetails?Id=${externalId}`;
  }
  if (region === 'jo') {
    return `https://jo.grandcinemasme.com/en/NowShowing/MovieDetails?Id=${externalId}`;
  }
  return null;
}

export async function enrichChainPosters(
  db: D1Database,
  limit = 10
): Promise<ChainPosterResult> {
  // Join titles → title_chain_refs to find Grand titles without posters
  const { results } = await db.prepare(
    `SELECT t.id, r.chain_id, r.chain_movie_id
     FROM titles t
     JOIN title_chain_refs r ON r.title_id = t.id
     WHERE t.poster_url IS NULL
       AND r.chain_id = 'grand-cinemas'
     ORDER BY t.updated_at ASC
     LIMIT ?`
  ).bind(limit).all<PosterlessMovie>();

  if (!results?.length) return { updated: 0, failed: 0, skipped: 0 };

  const outcomes = await mapWithConcurrency(
    results,
    CHAIN_POSTER_CONCURRENCY,
    async (title): Promise<keyof ChainPosterResult> => {
      const url = buildChainUrl(title.chain_id, title.chain_movie_id);
      if (!url) return 'skipped';

      try {
        const resp = await fetchWithTimeout(url, {
          headers: { 'User-Agent': 'Mozilla/5.0 CultRoll/1.0' },
          redirect: 'follow',
        }, {
          resource: `Chain poster ${title.chain_movie_id}`,
        });
        if (!resp.ok) {
          console.warn(`chain-posters: ${title.id} returned ${resp.status} for ${url}`);
          return 'failed';
        }

        const html = await resp.text();
        const poster = extractPoster(html);
        if (!poster) return 'skipped';

        await db.prepare(
          `UPDATE titles SET poster_url = ?, updated_at = datetime('now') WHERE id = ? AND poster_url IS NULL`
        ).bind(buildRemoteImageProxyPath(poster), title.id).run();

        return 'updated';
      } catch (error) {
        console.warn(
          `chain-posters: failed for ${title.id} (${title.chain_movie_id}):`,
          error instanceof Error ? error.message : String(error),
        );
        return 'failed';
      }
    },
  );

  return outcomes.reduce<ChainPosterResult>((acc, outcome) => {
    acc[outcome] += 1;
    return acc;
  }, { updated: 0, failed: 0, skipped: 0 });
}
