import { NextRequest, NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';
import matter from 'gray-matter';
import { generateImage } from '@/lib/image-service';
import { getIdeaMotriz } from '@/lib/file-service';
import type { FondoReferencia, ActoGuion } from '@/types/project';

const PROJECTS_DIR = path.join(process.cwd(), 'projects');
const DEFAULT_ESTILO = 'Pixar-style 3D animation, vibrant colors, expressive characters';

async function findCapDir(capitulosDir: string, numero: string) {
  const dirs = await fs.readdir(capitulosDir, { withFileTypes: true });
  return dirs.find(d =>
    d.isDirectory() && d.name.startsWith(numero.padStart(2, '0'))
  );
}

/** Extract unique escenarios from escaleta planos + guion actos */
async function extractFondos(capPath: string): Promise<FondoReferencia[]> {
  // Read escaleta planos
  let planos: any[] = [];
  try {
    planos = JSON.parse(await fs.readFile(path.join(capPath, 'escaleta-planos.json'), 'utf-8'));
  } catch { return []; }

  // Read guion actos for disenoFondo / accionVisualClave
  let actos: ActoGuion[] = [];
  try {
    actos = JSON.parse(await fs.readFile(path.join(capPath, 'guion-actos.json'), 'utf-8'));
  } catch { /* ok */ }

  // Build segment lookup: segmentoId → { nombre, disenoFondo, accionVisualClave }
  const segmentoMap = new Map<string, { nombre: string; disenoFondo: string; accionVisualClave: string }>();
  for (const acto of actos) {
    for (const seg of acto.segmentos) {
      segmentoMap.set(seg.id, { nombre: seg.nombre, disenoFondo: (seg as any).disenoFondo || '', accionVisualClave: seg.accionVisualClave });
    }
  }

  // Get unique segments from planos (segmentoGuion = "I.1 Nombre del Segmento")
  const seen = new Set<string>();
  const fondos: FondoReferencia[] = [];

  for (const plano of planos) {
    const segGuion: string = plano.segmentoGuion || '';
    // Extract segment ID (e.g. "I.1" from "I.1 El Silencio del Bosque")
    const segId = segGuion.split(' ')[0];
    if (!segId || seen.has(segId)) continue;
    seen.add(segId);

    const segInfo = segmentoMap.get(segId);
    const nombre = segInfo?.nombre || segGuion.replace(segId, '').trim() || segId;
    // Prefer disenoFondo (dedicated background description), fall back to accionVisualClave
    const descripcion = segInfo?.disenoFondo || segInfo?.accionVisualClave || '';

    fondos.push({
      id: `fondo-${segId}`,
      segmentoId: segId,
      nombre,
      descripcion,
      promptGeneracion: '',
    });
  }

  return fondos;
}

/** Load or auto-generate fondos.json */
async function loadFondos(capPath: string): Promise<FondoReferencia[]> {
  const fondosPath = path.join(capPath, 'fondos.json');
  try {
    return JSON.parse(await fs.readFile(fondosPath, 'utf-8'));
  } catch { /* not yet */ }

  // Auto-generate from escaleta
  const fondos = await extractFondos(capPath);
  if (fondos.length > 0) {
    await fs.writeFile(fondosPath, JSON.stringify(fondos, null, 2));
  }
  return fondos;
}

async function saveFondos(capPath: string, fondos: FondoReferencia[]): Promise<void> {
  await fs.writeFile(path.join(capPath, 'fondos.json'), JSON.stringify(fondos, null, 2));
}

/** Check if fondo image exists on disk */
async function enrichWithImageStatus(
  fondos: FondoReferencia[],
  slug: string,
  capDirName: string
): Promise<FondoReferencia[]> {
  const fondosDir = path.join(PROJECTS_DIR, slug, 'capitulos', capDirName, 'fondos');
  return Promise.all(fondos.map(async (fondo) => {
    try {
      await fs.access(path.join(fondosDir, `${fondo.id}.png`));
      return {
        ...fondo,
        imagenUrl: `/api/projects/${slug}/capitulos/${capDirName}/fondos/${fondo.id}`,
      };
    } catch {
      return { ...fondo, imagenUrl: undefined };
    }
  }));
}

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ slug: string; numero: string }> }
) {
  try {
    const { slug, numero } = await params;
    const capitulosDir = path.join(PROJECTS_DIR, slug, 'capitulos');
    const capDir = await findCapDir(capitulosDir, numero);

    if (!capDir) {
      return NextResponse.json(null);
    }

    const capPath = path.join(capitulosDir, capDir.name);
    const fondos = await loadFondos(capPath);
    const enriched = await enrichWithImageStatus(fondos, slug, capDir.name);
    const generated = enriched.filter(f => f.imagenUrl).length;

    return NextResponse.json({ fondos: enriched, total: enriched.length, generated });
  } catch (error: any) {
    console.error('Error fetching fondos:', error);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ slug: string; numero: string }> }
) {
  try {
    const { slug, numero } = await params;
    const { action, fondoId, descripcion, promptGeneracion } = await request.json();

    const capitulosDir = path.join(PROJECTS_DIR, slug, 'capitulos');
    const capDir = await findCapDir(capitulosDir, numero);

    if (!capDir) {
      return NextResponse.json({ error: 'Capítulo no encontrado' }, { status: 404 });
    }

    const capPath = path.join(capitulosDir, capDir.name);
    let fondos = await loadFondos(capPath);

    if (action === 'generate') {
      if (!fondoId) {
        return NextResponse.json({ error: 'Se necesita fondoId' }, { status: 400 });
      }

      const fondoIdx = fondos.findIndex(f => f.id === fondoId);
      if (fondoIdx === -1) {
        return NextResponse.json({ error: 'Fondo no encontrado' }, { status: 404 });
      }

      const fondo = fondos[fondoIdx];
      const ideaMotriz = await getIdeaMotriz(slug);
      const estilo = ideaMotriz?.estiloVisual || DEFAULT_ESTILO;

      // Always compose from current descripcion + estilo (promptGeneracion is only a user override)
      const prompt = `${estilo}. Empty scene without characters: ${fondo.descripcion}. Panoramic view of the environment, lighting, and atmosphere of the place. No characters, no text, no UI elements.`;

      const imageBuffer = await generateImage(prompt, { aspectRatio: '16:9' });

      // Save image
      const fondosDir = path.join(capPath, 'fondos');
      await fs.mkdir(fondosDir, { recursive: true });
      await fs.writeFile(path.join(fondosDir, `${fondoId}.png`), imageBuffer);

      // Update fondos.json
      fondos[fondoIdx] = {
        ...fondo,
        promptGeneracion: prompt,
        imagenUrl: `/api/projects/${slug}/capitulos/${capDir.name}/fondos/${fondoId}`,
      };
      await saveFondos(capPath, fondos);

      return NextResponse.json({ fondo: fondos[fondoIdx] });
    }

    if (action === 'generate-all') {
      const ideaMotriz = await getIdeaMotriz(slug);
      const estilo = ideaMotriz?.estiloVisual || DEFAULT_ESTILO;
      const fondosDir = path.join(capPath, 'fondos');
      await fs.mkdir(fondosDir, { recursive: true });

      const results: { id: string; success: boolean; error?: string }[] = [];

      for (let i = 0; i < fondos.length; i++) {
        const fondo = fondos[i];

        try {
          // Always compose from current descripcion + estilo
          const prompt = `${estilo}. Empty scene without characters: ${fondo.descripcion}. Panoramic view of the environment, lighting, and atmosphere of the place. No characters, no text, no UI elements.`;

          const imageBuffer = await generateImage(prompt, { aspectRatio: '16:9' });
          await fs.writeFile(path.join(fondosDir, `${fondo.id}.png`), imageBuffer);

          fondos[i] = {
            ...fondo,
            promptGeneracion: prompt,
            imagenUrl: `/api/projects/${slug}/capitulos/${capDir.name}/fondos/${fondo.id}`,
          };
          results.push({ id: fondo.id, success: true });
        } catch (err: any) {
          console.error(`Error generando fondo ${fondo.id}:`, err);
          results.push({ id: fondo.id, success: false, error: err.message });
        }
      }

      await saveFondos(capPath, fondos);
      const enriched = await enrichWithImageStatus(fondos, slug, capDir.name);
      const generated = enriched.filter(f => f.imagenUrl).length;

      return NextResponse.json({ fondos: enriched, total: enriched.length, generated, results });
    }

    if (action === 'refresh') {
      // Re-extract fondos from guión, merging with existing data
      const freshFondos = await extractFondos(capPath);
      const existingMap = new Map(fondos.map(f => [f.id, f]));

      const merged = freshFondos.map(fresh => {
        const existing = existingMap.get(fresh.id);
        if (!existing) return fresh;
        // Update descripcion from guión, clear promptGeneracion so it recomposes on next generate
        return { ...fresh, promptGeneracion: '' };
      });

      await saveFondos(capPath, merged);
      const enriched = await enrichWithImageStatus(merged, slug, capDir.name);
      const generated = enriched.filter(f => f.imagenUrl).length;

      return NextResponse.json({ fondos: enriched, total: enriched.length, generated });
    }

    if (action === 'update-description') {
      if (!fondoId) {
        return NextResponse.json({ error: 'Se necesita fondoId' }, { status: 400 });
      }

      const fondoIdx = fondos.findIndex(f => f.id === fondoId);
      if (fondoIdx === -1) {
        return NextResponse.json({ error: 'Fondo no encontrado' }, { status: 404 });
      }

      fondos[fondoIdx] = {
        ...fondos[fondoIdx],
        ...(descripcion !== undefined && { descripcion }),
        ...(promptGeneracion !== undefined && { promptGeneracion }),
      };
      await saveFondos(capPath, fondos);

      return NextResponse.json({ fondo: fondos[fondoIdx] });
    }

    return NextResponse.json({ error: 'Acción inválida' }, { status: 400 });
  } catch (error: any) {
    console.error('Error en fondos:', error);
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}
