<?php



class Ffmpeg
{

    static function videoToGif($original_video_file_path, $user_id)
    {
        $fileName = uniqid() . $user_id;
        $folder = UPLOADS_FOLDER_URI . '/gif/' . $user_id;
        $genrateGifPath = $folder . $fileName . ".gif";
        if (!file_exists($folder)) {
            mkdir($folder, 0777, true);
        }



        $gif = "ffmpeg -ss 3 -t 2 -i $original_video_file_path -vf 'fps=10,scale=160:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse' -loop 0 $genrateGifPath";

        exec($gif, $output);

        return $genrateGifPath;

    }

   static function videoToThumb($original_video_file_path, $user_id)
    {

        $without_extension_file_name = pathinfo($original_video_file_path, PATHINFO_FILENAME);


        $pieces = explode('/', $original_video_file_path);

        $str = implode('/', array_slice($pieces, 0, -1));


        $thumb_path = $str . '/' . $without_extension_file_name . "thumb.png";

        $thumb_cmd = "ffmpeg -i $original_video_file_path -vf fps=3 $thumb_path";

        exec($thumb_cmd, $output);


        return $thumb_path;
    }

    static function mergeVideoWithSound($video_path, $audio)
    {
        // 1. Absolute Paths ensure karein
        $video_path = realpath($video_path) ?: $video_path;
        $audio_path = realpath($audio) ?: $audio;
        
        $dir = dirname($video_path);
        $without_extension = pathinfo($video_path, PATHINFO_FILENAME);
        $output_file = $dir . DIRECTORY_SEPARATOR . $without_extension . "_merged_" . time() . ".mp4";

        // Debugging Start
        $log_file = $dir . DIRECTORY_SEPARATOR . 'ffmpeg_debug.log';
        $log_entry = "\n--- New Merge Attempt: " . date('Y-m-d H:i:s') . " ---\n";
        $log_entry .= "Video Path: $video_path\nAudio Path: $audio_path\n";

        if (!file_exists($video_path)) {
            file_put_contents($log_file, $log_entry . "ERROR: Video file not found: $video_path\n", FILE_APPEND);
            return $video_path;
        }

        // Fix Audio URL: If it looks like a URL (contains cloudfront/s3/http) but has no protocol, add https://
        if (!file_exists($audio_path) && (strpos($audio_path, 'cloudfront.net') !== false || strpos($audio_path, 's3.amazonaws.com') !== false) && strpos($audio_path, 'http') !== 0) {
             $audio_path = "https://" . $audio_path;
             $log_entry .= "Fixed Audio URL: $audio_path\n";
        }

        $v_path = escapeshellarg($video_path);
        
        if (filter_var($audio_path, FILTER_VALIDATE_URL)) {
             $temp_audio_local = $dir . DIRECTORY_SEPARATOR . "temp_audio_" . time() . ".mp3";
             $log_entry .= "Downloading remote audio to: $temp_audio_local\n";
             
             // Use cURL for robust download
             $ch = curl_init($audio_path);
             curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Handle SSL issues
             curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
             $audio_content = curl_exec($ch);
             $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
             curl_close($ch);

             if ($http_code == 200 && $audio_content) {
                 file_put_contents($temp_audio_local, $audio_content);
                 $a_path = escapeshellarg($temp_audio_local); // Use local path
             } else {
                 $log_entry .= "ERROR: Failed to download audio. HTTP Code: $http_code. URL: $audio_path\n";
                 // Fallback: try URL directly, but it likely won't work on old ffmpeg
                 $a_path = escapeshellarg($audio_path);
             }
        } else {
             $a_path = escapeshellarg($audio_path);
        }
        
        $out_path = escapeshellarg($output_file);

        // 3. Command:
        // 'libx264' is missing on this server. Switching to '-c:v copy' which is faster and safer.
        // We still re-encode audio to AAC to ensure it plays correctly.
        $cmd = "ffmpeg -y -i $v_path -i $a_path -c:v copy -c:a aac -b:a 128k -map 0:v:0 -map 1:a:0 -shortest $out_path 2>&1";

        $log_entry .= "Executing CMD: $cmd\n";
        
        // Execute ONLY ONCE
        exec($cmd, $output, $return_var);
        
        // Cleanup local temp audio
        if (!empty($temp_audio_local) && file_exists($temp_audio_local)) {
            @unlink($temp_audio_local);
        }

        $log_entry .= "Return Value: $return_var\n";
        $log_entry .= "Output: " . implode("\n", $output) . "\n";

        if ($return_var === 0 && file_exists($output_file) && filesize($output_file) > 0) {
            $log_entry .= "SUCCESS: File generated at $output_file\n";
            file_put_contents($log_file, $log_entry, FILE_APPEND);
            return $output_file;
        } else {
            $log_entry .= "FAILED: Merging failed. Check permissions or codecs.\n";
            file_put_contents($log_file, $log_entry, FILE_APPEND);
            return $video_path; 
        }
    }
    static function convertVideoToAudio($original_video_file_path)
    {

        $fileName = uniqid();
        $folder = UPLOADS_FOLDER_URI . '/audio/';
        $mp3_file = $folder . $fileName . ".mp3";
        if (!file_exists($folder)) {
            mkdir($folder, 0777, true);
        }

        $cmd = "ffprobe -i $original_video_file_path -show_streams -select_streams a -loglevel error";
        exec($cmd, $output);
        if (count($output) > 0) {

            $command_new = "ffmpeg -i $original_video_file_path -b:a 192K -vn $mp3_file";
            exec($command_new, $output);
            if(file_exists($mp3_file)) {
                return $mp3_file;
            } else {
                return false;
            }
        } else {

            return false;
        }


    }
    static function addWaterMarkInTheUserUploadedVideo($video,$username,$user_id,$duration){
        $fileName = uniqid() . $user_id;
        $starting_time = $duration/2;
        $ending_time = $starting_time*2;
        $dir =  UPLOADS_FOLDER_URI."/watermark/";
        $watermark_with_video ="$dir.$fileName.mp4";
        if (!file_exists($dir)) {
            mkdir($dir, 0777, true);
        }
        $watermark_with_username = (new self)->addUsernameWithWatermark($username,$user_id);

        $cmd = "ffmpeg -i $video -i $watermark_with_username -filter_complex \"[0:v][1:v]overlay=x='if(between(t,1,$starting_time),10,(main_w-overlay_w))':y='if(between(t,1,$starting_time),(main_h-overlay_h)/2-10,(main_h-overlay_h))':enable='between(t,0,$ending_time)'\" $watermark_with_video";

        //$cmd = "ffmpeg -i $original_video_file_path -i $image_with_watermark -filter_complex \"[0:v][1:v] overlay=x=\$x1\$:y=\$y1\$:enable='between(t,0,3)'[first]; [first][1:v] overlay=x=\$x2\$:y=\$y2\$:enable='between(t,3,6)'[outv]; [outv] fade=out:st=6:d=1 [finalv]\" -map '[finalv]' -c:a copy $video_with_watermark 2>&1";

        exec($cmd, $output);

        if(file_exists($watermark_with_video)){
            return $watermark_with_video;
        }else{
            return false;
        }



    }


    static function addUsernameWithWatermark($username,$user_id){
        $fileName = uniqid() . $user_id;
        $font_name = 'roboto-bold.ttf';
        $font_path = FONT_FOLDER_URI . '/' . $font_name;
        $watermark = WATERMARK_IMAGE_URI;
        $dir =  UPLOADS_FOLDER_URI."/watermark/";
        $watermark_with_username ="$dir.$fileName.png";
        if (!file_exists($dir)) {
            mkdir($dir, 0777, true);
        }
        $cmd_image = "ffmpeg -i $watermark -vf \"drawtext=text='@$username':fontsize=14:fontcolor=white:fontfile=$font_path:x=12:y=80\" $watermark_with_username";
        exec($cmd_image, $output);
        if(file_exists($watermark_with_username)){
            return $watermark_with_username;
        }else{
            return false;
        }



    }

    static function addWaterMarkInLastClip($username,$user_id){
        $fileName = uniqid() . $user_id;

        $dir =  UPLOADS_FOLDER_URI."/watermark/";
        $watermark_with_video ="$dir.$fileName.mp4";
        if (!file_exists($dir)) {
            mkdir($dir, 0777, true);
        }

        $watermark_video = WATERMARK_VIDEO_URI;
        $cmd_video_watermark = "ffmpeg -i $watermark_video -vf \"drawtext=text='@$username':x=400:y=1110:fontsize=30:fontcolor=white:enable='gte(t,1)'\" -c:a copy $watermark_with_video";


        exec($cmd_video_watermark, $output);

        if(file_exists($watermark_with_video)){
            return $watermark_with_video;
        }else{
            return false;
        }



    }



    static function combineVideoWithOriginal($user_video_with_watermark,$video_with_last_clip_watermark){
        $fileName = uniqid();


        $dir =  UPLOADS_FOLDER_URI."/watermark/";
        $video =$dir.$fileName.".mp4";
        if (!file_exists($dir)) {
            mkdir($dir, 0777, true);
        }
        $user_video_with_watermark = realpath($user_video_with_watermark);
        $video_with_last_clip_watermark = realpath($video_with_last_clip_watermark);

        if (!$user_video_with_watermark || !$video_with_last_clip_watermark) {
            return false;
        }
// Create a temporary text file listing the videos
        $file_list = $dir.'file_list.txt';

        file_put_contents($file_list, "file '" . $user_video_with_watermark . "'\nfile '" . $video_with_last_clip_watermark . "'");

// Build the FFmpeg command
        $cmd_combine = "ffmpeg -f concat -safe 0 -i " . $file_list . " -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 192k " . $video . " 2>&1";

// Execute the command
        exec($cmd_combine,$output);
       

// Cleanup: Remove the temporary file list
        unlink($file_list);

        $cmd_combine = "ffmpeg -i $user_video_with_watermark -i $video_with_last_clip_watermark -filter_complex '[0:v]scale=720:1280,setsar=1[v0]; [1:v]scale=720:1280,setsar=1[v1]; [v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]' -map '[outv]' -map '[outa]' $video";


        exec($cmd_combine, $output);

        if(file_exists($video)){
            return $video;
        }else{
            return false;
        }



    }

    function addWaterMarkAndText($original_video_file_path, $user_id, $username, $duration)
    {




        if ($duration < 1) {

            $duration = (new self)->getDurationOfVideoFile($original_video_file_path);
        }

        if(file_exists(WATERMARK_VIDEO_URI)) {


            $video_with_last_clip_watermark = (new self)->addWaterMarkInLastClip($username, $user_id);
            $user_video_with_watermark = (new self)->addWaterMarkInTheUserUploadedVideo($original_video_file_path, $username, $user_id, $duration);
            
            if($video_with_last_clip_watermark && $user_video_with_watermark){
                 $final_video = (new self)->combineVideoWithOriginal($user_video_with_watermark, $video_with_last_clip_watermark);

                 @unlink($user_video_with_watermark);
                 @unlink($video_with_last_clip_watermark);

                 return $final_video;
            }else{
                 @unlink($user_video_with_watermark);
                 @unlink($video_with_last_clip_watermark);
                 return false;
            }

        }else{

            $fileName = uniqid() . $user_id;
            $font_name = 'roboto-bold.ttf';
            $font_path = FONT_FOLDER_URI . '/' . $font_name;
            $watermark = WATERMARK_IMAGE_URI;
            $folder = TEMP_UPLOADS_FOLDER_URI . '/video/' . $user_id . '/';
            $video_with_watermark = $folder . $fileName . ".mp4";
            if (!file_exists($folder)) {
                mkdir($folder, 0777, true);
            }

            $ext = pathinfo($watermark, PATHINFO_EXTENSION);

            if ($ext == "png" || $ext == "jpeg") {


                $cmd = "ffmpeg -i $original_video_file_path -i $watermark -filter_complex \"[0:v][1:v]overlay=10:10,drawtext=fontfile='$font_path':text='@$username':fontcolor=#ffffff:fontsize=18:y=40:x=13\" -c:a copy -movflags +faststart $video_with_watermark";

            } else {




                $cmd = "ffmpeg -i $original_video_file_path -ignore_loop 0 -i $watermark -filter_complex \"[0:v][1:v]overlay=x=10:y=10:format=auto:enable='lte(t,$duration)':shortest=1[bg];[bg][1:v]overlay=x=main_w-overlay_w-10:y=main_h-overlay_h-20:format=auto:enable='gte(t,$duration)':shortest=1,drawtext=fontfile='$font_path':text='@$username':fontsize=18:fontcolor=white:x=13:y=40:enable='lte(t,$duration)',drawtext=fontfile='$font_path':text='@$username':fontsize=18:fontcolor=white:x=w-tw-10:y=h-th-10:enable='gte(t,$duration)',format=yuv420p[v]\" -map \"[v]\" -c:v libx264 -crf 18 -map 0:a? -c:a copy -movflags +faststart $video_with_watermark";
            }

            exec($cmd, $output);


            return $video_with_watermark;
        }







    }

    static function duet($video1_path, $video2_path, $duet)
    {



        $without_extension_file_name = pathinfo($video1_path, PATHINFO_FILENAME);


        $pieces = explode('/', $video1_path);

        $str = implode('/', array_slice($pieces, 0, -1));


        $duetMergePathOutput = $str . '/' . $without_extension_file_name . "duet.mp4";


        $command_new = "ffmpeg -i $video1_path   -i $video2_path   -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]'   -map [vid]   -c:v libx264   -crf 23   -preset veryfast $duetMergePathOutput";


        exec($command_new);


        return $duetMergePathOutput;
    }

    static function duetVertical($video1_path, $video2_path)
    {


        $without_extension_file_name = pathinfo($video1_path, PATHINFO_FILENAME);


        $pieces = explode('/', $video1_path);

        $str = implode('/', array_slice($pieces, 0, -1));


        $duetMergePathOutput_top = $str . '/' . $without_extension_file_name . "temptop.mp4";
        $duetMergePathOutput_bottom = $str . '/' . $without_extension_file_name . "tempbottom.mp4";
        $duetMergePathOutput_final = $str . '/' . $without_extension_file_name . "duet.mp4";


        $command_top = "ffmpeg -i $video1_path -s 720x640 -c:a copy $duetMergePathOutput_top";
        $command_bottom = "ffmpeg -i $video2_path -s 720x640 -c:a copy $duetMergePathOutput_bottom";
        exec($command_top);
        exec($command_bottom);

        $command_final = "ffmpeg -i $duetMergePathOutput_top -i $duetMergePathOutput_bottom -filter_complex '[0:v][1:v]vstack=inputs=2[v]' -map '[v]' -map 1:a $duetMergePathOutput_final";
        // $command_final = "ffmpeg -i $command_top -i $command_bottom -lavfi vstack $duetMergePathOutput_final";

        exec($command_final);


        return $duetMergePathOutput_final;
    }

    static function getDurationOfVideoFile($video_url)
    {

        $cmd = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 \"$video_url\" 2>&1";
        exec($cmd, $output);
        if(isset($output[0]) && is_numeric($output[0])){
             $duration = number_format((float)$output[0], 1, '.', '');
        }else{
            $duration = 0.0;
        }
        return $duration;
    }
    static function getDurationofAudioFile($filepath)
    {

        $duration = shell_exec("ffmpeg -i \"" . $filepath . "\" 2>&1");


        preg_match("/Duration: (\d{2}:\d{2}:\d{2}\.\d{2})/", $duration, $matches);

        if (isset($matches[1])) {
            $time = explode(':', $matches[1]);
            $hour = isset($time[0]) ? (int)$time[0] : 0;
            $minutes = isset($time[1]) ? (int)$time[1] : 0;
            $seconds = isset($time[2]) ? round((float)$time[2]) : 0;
        } else {
             // Default to 0 if duration cannot be parsed
            $hour = 0;
            $minutes = 0;
            $seconds = 0;
        }

        $total_seconds = 0;
        $total_seconds += 60 * 60 * $hour;
        $total_seconds += 60 * $minutes;

        return $minutes . ":" . $seconds;

    }

}
?>