import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import { resolveDirectVideoUrl } from '@/lib/resolvers';
import { analyzeCookingThumbnails, analyzeFromTranscript, analyzeFromTranscriptAndImages, transcribeAudioBytes, generateRecipeTitle, generateDetailedInstructions } from '@/lib/openai';
import { downloadInstagramVideoBytes } from '@/lib/instaloader';
import { downloadTikTokVideoBytes } from '@/lib/pyktok';
import { extractThumbnailsFromVideoBytes } from '@/lib/video';
import { extractMp3FromVideoBytes } from '@/lib/audio';
import { unlink } from 'node:fs/promises';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
export const maxDuration = 60; // seconds

const BodySchema = z.object({ url: z.string().url() });

async function downloadBytes(url: string): Promise<Uint8Array> {
  const res = await fetch(url, {
    headers: {
      'user-agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123 Safari/537.36',
      accept: '*/*',
    },
    redirect: 'follow',
  });
  if (!res.ok) {
    throw new Error(`Failed to download video: ${res.status}`);
  }
  const ab = await res.arrayBuffer();
  return new Uint8Array(ab);
}

export async function POST(req: NextRequest) {
  try {
    const json = await req.json();
    const { url } = BodySchema.parse(json);

    const resolved = await resolveDirectVideoUrl(url);
    let uploadBytes: Uint8Array | null = null;
    let description: string = '';
    let tempFilePath: string | null = null;
    if (resolved.directUrl) {
      uploadBytes = await downloadBytes(resolved.directUrl);
    } else if (resolved.sourcePlatform === 'instagram') {
      // Fallback: use Instaloader helper
      const ig = await downloadInstagramVideoBytes(url);
      if (ig) {
        uploadBytes = ig.bytes;
        description = ig.description || '';
        tempFilePath = ig.filePath || null;
      }
    } else if (resolved.sourcePlatform === 'tiktok') {
      // Fallback: use Pyktok helper
      const tt = await downloadTikTokVideoBytes(url);
      if (tt) {
        uploadBytes = tt.bytes;
        description = tt.description || '';
        tempFilePath = tt.filePath || null;
      }
    } else {
      return NextResponse.json(
        { error: 'Could not resolve a direct video URL from the provided link.' },
        { status: 400 },
      );
    }

    if (!uploadBytes) {
      return NextResponse.json(
        { error: 'Could not obtain video bytes from the provided link.' },
        { status: 400 },
      );
    }

    // 1) Convert to transcript first
    let analysis;
    let transcript: string | null = null;
    const MAX_FRAMES = Number(process.env.ANALYZE_MAX_FRAMES || '24');
    try {
      const audio = await extractMp3FromVideoBytes(uploadBytes);
      if (audio && audio.byteLength > 0) {
        transcript = await transcribeAudioBytes(audio);
        if (transcript && transcript.trim().length > 0) {
          // Extract frames at 2 fps and include alongside transcript in order
          const thumbsForCombined = await extractThumbnailsFromVideoBytes(uploadBytes, MAX_FRAMES > 0 ? MAX_FRAMES : 0, 2);
          if (thumbsForCombined.length) {
            analysis = await analyzeFromTranscriptAndImages(transcript, thumbsForCombined, description);
          } else {
            const combined = description && description.trim()
              ? `Caption/Description: ${description}\n\nTranscript: ${transcript}`
              : transcript;
            analysis = await analyzeFromTranscript(combined);
          }
        }
      }
    } catch {
      // fall back to thumbnails below
    }

    // 2) If transcript failed/empty, fall back to thumbnails-based analysis
    if (!analysis) {
      const thumbs = await extractThumbnailsFromVideoBytes(uploadBytes, MAX_FRAMES > 0 ? MAX_FRAMES : 0, 2);
      if (!thumbs.length) {
        return NextResponse.json({ error: 'Could not extract thumbnails from video' }, { status: 400 });
      }
      analysis = await analyzeCookingThumbnails(thumbs, description);
    }

    // Provide first thumbnail base64 for saving
    const firstThumbArr = await extractThumbnailsFromVideoBytes(uploadBytes, 1, 2);
    const firstThumbBase64 = firstThumbArr[0]
      ? `data:image/jpeg;base64,${Buffer.from(firstThumbArr[0]).toString('base64')}`
      : undefined;

    // Generate a title and detailed instructions
    const title = await generateRecipeTitle({ description, transcript: transcript || '', analysis });
    try {
      const detailed = await generateDetailedInstructions({ description, transcript: transcript || '', analysis });
      if (detailed) {
        (analysis as any).detailed = detailed;
      }
    } catch {}

    // Cleanup: delete temp downloaded video file if present
    if (tempFilePath) {
      try { await unlink(tempFilePath); } catch {}
    }

    return NextResponse.json({
      platform: resolved.sourcePlatform,
      title,
      description,
      transcript: transcript || '',
      thumbnailBase64: firstThumbBase64,
      analysis,
    });
  } catch (err: any) {
    return NextResponse.json({ error: err?.message || 'Unexpected error' }, { status: 500 });
  }
}


