export const prerender = false;

import type { APIRoute } from 'astro';
import { isAuthenticated, ADMIN_COOKIE } from '@admin/lib/admin-auth';

interface Env { DB: D1Database }

function getCtx(locals: App.Locals) {
  const runtime = (locals as any).runtime as { env: Env } | undefined;
  return runtime?.env;
}

export const PUT: APIRoute = async ({ request, cookies, locals }) => {
  const env = getCtx(locals);
  if (!env?.DB || !await isAuthenticated(cookies.get(ADMIN_COOKIE)?.value, env.DB)) {
    return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
  }

  const body = await request.json() as {
    id?: number;
    external_cinema_name?: string | null;
    cinema_id?: string | null;
    priority?: number;
    enabled?: number;
    config_override?: string;
    cinema?: {
      name_en?: string | null;
      name_ar?: string | null;
      name_ku?: string | null;
      address_en?: string | null;
      address_ar?: string | null;
      mall_name?: string | null;
      phone?: string | null;
      screens?: number | null;
      experiences?: string | null;
      lat?: number | null;
      lng?: number | null;
    };
  };

  if (!Number.isInteger(body.id)) {
    return Response.json({ error: 'id must be an integer' }, { status: 400 });
  }
  if (body.priority !== undefined && (!Number.isInteger(body.priority) || body.priority < 0)) {
    return Response.json({ error: 'priority must be an integer >= 0' }, { status: 400 });
  }
  if (body.enabled !== undefined && body.enabled !== 0 && body.enabled !== 1) {
    return Response.json({ error: 'enabled must be 0 or 1' }, { status: 400 });
  }

  let configOverride: string | null = null;
  if (body.config_override !== undefined) {
    try {
      const parsed = JSON.parse(body.config_override);
      if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        return Response.json({ error: 'config_override must be a JSON object' }, { status: 400 });
      }
      configOverride = JSON.stringify(parsed);
    } catch {
      return Response.json({ error: 'config_override must be valid JSON' }, { status: 400 });
    }
  }

  const cinemaId = body.cinema_id && body.cinema_id.trim() ? body.cinema_id.trim() : null;
  if (cinemaId) {
    const exists = await env.DB.prepare(`SELECT 1 FROM cinemas WHERE id = ?`).bind(cinemaId).first();
    if (!exists) {
      return Response.json({ error: 'cinema_id not found' }, { status: 400 });
    }
  }

  let cinemaUpdate: {
    nameEn: string;
    nameAr: string;
    nameKu: string;
    addressEn: string;
    addressAr: string;
    mallName: string;
    phone: string;
    screens: number | null;
    experiences: string;
    lat: number | null;
    lng: number | null;
  } | null = null;
  if (body.cinema !== undefined) {
    if (!body.cinema || typeof body.cinema !== 'object' || Array.isArray(body.cinema)) {
      return Response.json({ error: 'cinema must be an object' }, { status: 400 });
    }
    if (!cinemaId) {
      return Response.json({ error: 'cinema_id is required to update cinema details' }, { status: 400 });
    }
    const nameEn = typeof body.cinema.name_en === 'string' ? body.cinema.name_en.trim() : '';
    if (!nameEn) {
      return Response.json({ error: 'cinema.name_en is required' }, { status: 400 });
    }
    const nameAr = typeof body.cinema.name_ar === 'string' ? body.cinema.name_ar.trim() : '';
    const nameKu = typeof body.cinema.name_ku === 'string' ? body.cinema.name_ku.trim() : '';
    const addressEn = typeof body.cinema.address_en === 'string' ? body.cinema.address_en.trim() : '';
    const addressAr = typeof body.cinema.address_ar === 'string' ? body.cinema.address_ar.trim() : '';
    const mallName = typeof body.cinema.mall_name === 'string' ? body.cinema.mall_name.trim() : '';
    const phone = typeof body.cinema.phone === 'string' ? body.cinema.phone.trim() : '';
    const experiences = typeof body.cinema.experiences === 'string' ? body.cinema.experiences.trim() : '';

    let lat: number | null = null;
    if (body.cinema.lat !== undefined && body.cinema.lat !== null) {
      if (typeof body.cinema.lat !== 'number' || !Number.isFinite(body.cinema.lat) || body.cinema.lat < -90 || body.cinema.lat > 90) {
        return Response.json({ error: 'cinema.lat must be a valid latitude' }, { status: 400 });
      }
      lat = body.cinema.lat;
    }

    let lng: number | null = null;
    if (body.cinema.lng !== undefined && body.cinema.lng !== null) {
      if (typeof body.cinema.lng !== 'number' || !Number.isFinite(body.cinema.lng) || body.cinema.lng < -180 || body.cinema.lng > 180) {
        return Response.json({ error: 'cinema.lng must be a valid longitude' }, { status: 400 });
      }
      lng = body.cinema.lng;
    }

    let screens: number | null = null;
    if (body.cinema.screens !== undefined && body.cinema.screens !== null) {
      if (!Number.isInteger(body.cinema.screens) || body.cinema.screens < 0) {
        return Response.json({ error: 'cinema.screens must be an integer >= 0' }, { status: 400 });
      }
      screens = body.cinema.screens;
    }
    cinemaUpdate = { nameEn, nameAr, nameKu, addressEn, addressAr, mallName, phone, screens, experiences, lat, lng };
  }

  await env.DB.prepare(
    `UPDATE source_target_cinemas
        SET external_cinema_name = COALESCE(?, external_cinema_name),
            cinema_id            = CASE WHEN ? = 1 THEN ? ELSE cinema_id END,
            priority             = COALESCE(?, priority),
            enabled              = COALESCE(?, enabled),
            config_override      = COALESCE(?, config_override),
            updated_at           = datetime('now')
      WHERE id = ?`
  ).bind(
    body.external_cinema_name === undefined ? null : body.external_cinema_name,
    body.cinema_id === undefined ? 0 : 1,
    cinemaId,
    body.priority ?? null,
    body.enabled ?? null,
    configOverride,
    body.id
  ).run();

  if (cinemaUpdate && cinemaId) {
    await env.DB.prepare(
      `UPDATE cinemas
          SET name_en    = ?,
              name_ar    = NULLIF(?, ''),
              name_ku    = NULLIF(?, ''),
              address_en = NULLIF(?, ''),
              address_ar = NULLIF(?, ''),
              mall_name  = NULLIF(?, ''),
              phone      = NULLIF(?, ''),
              screens    = ?,
              experiences = NULLIF(?, ''),
              lat        = ?,
              lng        = ?
        WHERE id = ?`
    ).bind(
      cinemaUpdate.nameEn,
      cinemaUpdate.nameAr,
      cinemaUpdate.nameKu,
      cinemaUpdate.addressEn,
      cinemaUpdate.addressAr,
      cinemaUpdate.mallName,
      cinemaUpdate.phone,
      cinemaUpdate.screens,
      cinemaUpdate.experiences,
      cinemaUpdate.lat,
      cinemaUpdate.lng,
      cinemaId
    ).run();
  }

  const mapping = await env.DB.prepare(
    `SELECT source_target_id, external_cinema_id, cinema_id
       FROM source_target_cinemas
      WHERE id = ?`
  ).bind(body.id).first<{ source_target_id: string; external_cinema_id: string; cinema_id: string | null }>();

  if (!mapping) {
    return Response.json({ error: 'mapping not found' }, { status: 404 });
  }

  await env.DB.prepare(
    `UPDATE source_discovered_cinemas
        SET cinema_id = ?,
            status = CASE
              WHEN ? IS NULL THEN CASE WHEN status = 'ignored' THEN 'ignored' ELSE 'new' END
              ELSE 'mapped'
            END,
            confidence = CASE WHEN ? IS NULL THEN confidence ELSE 1.0 END,
            last_seen_at = datetime('now')
      WHERE source_target_id = ?
        AND external_cinema_id = ?`
  ).bind(
    mapping.cinema_id,
    mapping.cinema_id,
    mapping.cinema_id,
    mapping.source_target_id,
    mapping.external_cinema_id
  ).run();

  return Response.json({ ok: true });
};
