import { NextRequest, NextResponse } from 'next/server';
import { verifySignatureSession } from '@/lib/odentas-sign/jwt';
import { supabaseAdmin } from '@/lib/odentas-sign/supabase';
import { getPresignedDownloadUrl } from '@/lib/odentas-sign/s3';
import {
  extractPlaceholdersWithPdfParse,
  countPdfPagesFromBytes,
  estimatePositionsFromPlaceholders,
  estimatePositionsFromPlaceholdersUsingText,
  extractPlaceholdersWithPdfium,
  extractPrecisePositionsFromPdf,
} from '@/lib/odentas-sign/placeholders';

// Force Node.js runtime
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

/**
 * GET /api/odentas-sign/requests/:id/positions
 * Récupère les positions de signature pour toutes les parties
 */
export async function GET(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const requestId = params.id;

    // Vérifier le token JWT
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return NextResponse.json(
        { error: 'Token manquant ou invalide' },
        { status: 401 }
      );
    }

    const token = authHeader.split(' ')[1];
    const payload = verifySignatureSession(token);

    if (!payload || payload.requestId !== requestId) {
      return NextResponse.json(
        { error: 'Token invalide ou expiré' },
        { status: 401 }
      );
    }

    // Récupérer toutes les positions de signature existantes
    const { data: positions, error } = await supabaseAdmin
      .from('sign_positions')
      .select('page, x, y, w, h, role')
      .eq('request_id', requestId)
      .order('role');

    console.log('[POSITIONS API] Positions en DB:', {
      requestId,
      count: positions?.length || 0,
      hasError: !!error,
      positions,
    });

    if (error) {
      console.error('Erreur DB lors de la récupération des positions:', error);
      return NextResponse.json(
        { error: 'Erreur lors de la récupération des positions' },
        { status: 500 }
      );
    }

    // Si positions déjà présentes, renvoyer directement
    if (positions && positions.length > 0) {
      console.log('[POSITIONS API] ✅ Positions trouvées en DB, renvoi direct');
      const transformedPositions = positions.map((p) => ({
        page: p.page,
        x: p.x,
        y: p.y,
        width: p.w,
        height: p.h,
        role: p.role,
      }));
      return NextResponse.json({ positions: transformedPositions });
    }

    console.log('[POSITIONS API] ❌ Aucune position en DB, extraction depuis le PDF...');

    // Pas de positions en DB: tenter d'extraire depuis le PDF via placeholders
    // 1) Récupérer la clé S3 du PDF source
    const { data: signRequest, error: requestErr } = await supabaseAdmin
      .from('sign_requests')
      .select('source_s3_key')
      .eq('id', requestId)
      .single();

    console.log('[POSITIONS API] Sign request récupéré:', {
      hasData: !!signRequest,
      source_s3_key: signRequest?.source_s3_key,
      hasError: !!requestErr,
    });

    if (requestErr || !signRequest?.source_s3_key) {
      console.error('Impossible de récupérer sign_request pour extraction:', requestErr);
      return NextResponse.json({ positions: [] });
    }

    // 2) Générer une URL présignée et télécharger le PDF
    const pdfUrl = await getPresignedDownloadUrl(signRequest.source_s3_key, 300);
    console.log('[POSITIONS API] URL présignée générée, téléchargement du PDF...');
    
    const resp = await fetch(pdfUrl);
    if (!resp.ok) {
      console.error('Téléchargement du PDF échoué:', resp.status, pdfUrl);
      return NextResponse.json({ positions: [] });
    }
    const arrayBuf = await resp.arrayBuffer();
    const bytes = Buffer.from(arrayBuf);
    console.log('[POSITIONS API] PDF téléchargé:', {
      size: bytes.length,
      sizeKB: Math.round(bytes.length / 1024),
    });

    // 1) Tentative d'extraction précise via pdf-lib (Tm/Td) → pourcentages
    console.log('[POSITIONS] Tentative extraction PRÉCISE (pdf-lib) ...');
    let precise = await extractPrecisePositionsFromPdf(bytes);

    // 2) Fallback DocuSeal-like (Pdfium) si rien
    if (!precise || precise.length === 0) {
      console.warn('[POSITIONS] Aucun résultat précis, fallback PDFIUM ...');
      precise = await extractPlaceholdersWithPdfium(bytes);
    }

    if (!precise || precise.length === 0) {
      console.warn('[POSITIONS] ❌ Aucun placeholder trouvé (pdf-lib + Pdfium). Tentative fallback via pdf-parse + estimation');
  const { placeholders, text, numPages } = await extractPlaceholdersWithPdfParse(bytes);
  const pageCount = numPages || countPdfPagesFromBytes(bytes);
  // Utiliser l'estimation basée sur le TEXTE pour une meilleure position verticale et page
  const estimated = estimatePositionsFromPlaceholdersUsingText(placeholders, text, pageCount);
      precise = estimated.map((p) => ({
        role: p.role,
        label: p.label,
        page: p.page,
        x: p.x,
        y: p.y,
        width: p.width,
        height: p.height,
        text: p.label,
      }));

      if (!precise || precise.length === 0) {
        console.warn('[POSITIONS] ❌ Aucun placeholder détecté avec les méthodes disponibles');
        return NextResponse.json({ positions: [] });
      }
    }

    console.log(`[POSITIONS] ✅ Extraction réussie: ${precise.length} position(s) trouvée(s)`);

    // Persister en DB pour cette demande (meilleure UX aux prochains chargements)
    try {
      const rows = precise.map((pos) => ({
        request_id: requestId,
        role: pos.role,
        page: pos.page,
        x: pos.x, // POURCENTAGES (%)
        y: pos.y, // POURCENTAGES (%)
        w: pos.width, // POURCENTAGES (%)
        h: pos.height, // POURCENTAGES (%)
        kind: 'signature',
        label: pos.label,
      }));
      const { error: insertErr } = await supabaseAdmin.from('sign_positions').insert(rows);
      if (insertErr) {
        console.warn('Insertion positions estimées échouée (non bloquant):', insertErr);
      }
    } catch (e) {
      console.warn('Erreur lors de la persistance des positions estimées:', e);
    }

    // 6) Retourner au format attendu par le front
    const transformedPositions = precise.map((p) => ({
      page: p.page,
      x: p.x,
      y: p.y,
      width: p.width,
      height: p.height,
      role: p.role,
    }));

    return NextResponse.json({ positions: transformedPositions });

  } catch (error) {
    console.error('Erreur lors de la récupération des positions:', error);
    return NextResponse.json(
      { error: 'Erreur serveur lors de la récupération des positions' },
      { status: 500 }
    );
  }
}

/**
 * POST /api/odentas-sign/requests/:id/positions
 * Upsert des positions détectées côté client (mm)
 */
export async function POST(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const requestId = params.id;

    // Vérifier le token JWT
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return NextResponse.json(
        { error: 'Token manquant ou invalide' },
        { status: 401 }
      );
    }
    const token = authHeader.split(' ')[1];
    const payload = verifySignatureSession(token);
    if (!payload || payload.requestId !== requestId) {
      return NextResponse.json(
        { error: 'Token invalide ou expiré' },
        { status: 401 }
      );
    }

    const body = await request.json();
    const positions = Array.isArray(body?.positions) ? body.positions : [];
    if (positions.length === 0) {
      return NextResponse.json({ success: false, message: 'Aucune position fournie' }, { status: 400 });
    }

    // Nettoyer les positions existantes de type signature pour cette requête
    await supabaseAdmin
      .from('sign_positions')
      .delete()
      .eq('request_id', requestId)
      .eq('kind', 'signature');

    // Insérer les nouvelles positions (mm)
    const rows = positions.map((p: any) => ({
      request_id: requestId,
      role: p.role,
      page: p.page,
      x: p.x,
      y: p.y,
      w: p.w,
      h: p.h,
      kind: p.kind || 'signature',
      label: p.label || null,
    }));

    const { error: insertErr } = await supabaseAdmin
      .from('sign_positions')
      .insert(rows);

    if (insertErr) {
      console.error('Erreur insertion positions (POST):', insertErr);
      return NextResponse.json({ error: 'Insertion des positions échouée' }, { status: 500 });
    }

    return NextResponse.json({ success: true, inserted: rows.length });
  } catch (error) {
    console.error('Erreur POST positions:', error);
    return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
  }
}
