<?php

namespace App\Console\Commands;

use App\Libraries\CommonHelper;
use Illuminate\Console\Command;
use Illuminate\Http\File;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Dcat\Admin\Traits\HasUploadedFile;
use FFMpeg\FFMpeg;
use FFMpeg\Coordinate\TimeCode;





/*
 * 生成预览10秒视频
 *
 * @author  <EMAIL>
 * 运行命令：php artisan command:preview-video
 */

class GeneratePreviewVideo extends Command
{
    use HasUploadedFile;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:preview-video';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '生成预览视频';

    public $timeSecond = 8;

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
//        $this->importVideo();
//        exit;

        $disk = $this->disk('oss');

        //如果目录不存在则创建
        $localPreviewPath = storage_path('tmp/previews');
        if (!file_exists($localPreviewPath)) {
            mkdir($localPreviewPath, 0777, true);
        }

        $reslut = DB::table('site_preview_video')
            ->where('status', '==', 0) // 过滤非空 video 字段
            ->orderBy('id') // 按主键排序确保顺序
            ->limit(1) // 限制处理 1 条
            ->get();

        foreach ($reslut as $item) {
            try {
                $video_oss_url = $this->ossUrl($item->video_url);
                $fileName = basename($video_oss_url);
                $fileInfo = pathinfo($fileName);

                //下载$video_url到本地
                $localFilePath = $localPreviewPath. '/'. $fileName;
                $this->saveLocal($video_oss_url, $localFilePath);


                $previewName = $fileInfo['filename'] . '_preview.' . $fileInfo['extension'];
                $previewPath = storage_path('tmp/previews/'.$previewName);
                //截取视频前5秒
                $this->generatePreview($localFilePath, $previewPath);

                //上传到OSS
                $uploadPath = 'videos/uploads/previews/'. date('Ym');
                $file = new File($previewPath);
                $disk->putFileAs($uploadPath, $file, $previewName);

                DB::table('site_preview_video')
                    ->where('id', $item->id)
                    ->update([
                        'preview_url' => $uploadPath . '/' . $previewName,
                        'status' => 1
                    ]);

                //删除本地文件
                unlink($localFilePath);
                unlink($previewPath);
            } catch (\Exception $e) {
                DB::table('site_preview_video')
                    ->where('id', $item->id)
                    ->update([
                        'remark' => $e->getMessage(),
                        'status' => -1
                    ]);
            }
        }

        //$this->importVideo();
        return dd('success');
    }

    private  function saveLocal($url, $localPath) {
        $remote = fopen($url, 'rb');
        $local = fopen($localPath, 'wb');
        while (!feof($remote)) {
            fwrite($local, fread($remote, 8192)); // 8KB分块
        }
        fclose($remote);
        fclose($local);
        return $localPath;
    }

    private function ossUrl($url)
    {
        if (strpos($url, 'http:') === 0 || strpos($url, 'https:') === 0) {
            return  $url;
        }
        return "https://mietublcom.oss-cn-hongkong.aliyuncs.com".'/'.$url;
    }


    public function generatePreview($inputUrl, $outputPath) {
        $ffmpeg = FFMpeg::create([
            'ffmpeg.binaries'  => '/usr/bin/ffmpeg',
            'ffprobe.binaries' => '/usr/bin/ffprobe',
            'timeout' => 300
        ]);

        $video = $ffmpeg->open($inputUrl);
        $video->filters()->clip(TimeCode::fromSeconds(0), TimeCode::fromSeconds($this->timeSecond));

        // 输出为H.264编码的MP4
        $format = new \FFMpeg\Format\Video\X264();
        $format->setAudioCodec('none')  // 完全禁用音频
        ->setAdditionalParameters([
            '-crf 38',           // 极高压缩率(0-51,默认28)
            '-preset superfast', // 最快编码速度
            '-vf "scale=640:-2:flags=lanczos, fps=15"', // 分辨率+帧率限制
            '-tune zerolatency', // 低延迟模式
            '-x265-params rd=4:psy-rd=0:no-sao:no-deblock', // 关闭视觉优化
            '-g 30',             // 关键帧间隔
            '-pix_fmt yuv420p',  // 兼容色彩采样
            '-movflags +faststart'
        ]);
        $video->save($format, $outputPath);
        return $outputPath;
    }


    /*ssssssss
     * 把旧数据导入新的预览表
     */
    function importVideo()
    {
        try {
            // 分批处理数据，避免内存溢出
            DB::table('site_album')
                ->where('video', '<>', '[]') // 过滤非空 video 字段
                ->orderBy('id') // 按主键排序确保顺序
                ->chunkById(10000, function ($albums) { // 每次处理 100 条
                    $insertData = [];

                    foreach ($albums as $album) {
                        // 跳过无效 JSON 数据
                        $videos = json_decode($album->video, true);
                        if (json_last_error() !== JSON_ERROR_NONE || !is_array($videos)) {
                            Log::warning("Invalid JSON in album ID: {$album->id}");
                            continue;
                        }

                        foreach ($videos as $video) {
                            // 校验必要字段存在性
                            if (empty($video['video_src']) || empty($video['cover'])) {
                                Log::warning("Missing video_src or cover in album ID: {$album->id}");
                                continue;
                            }

                            // 处理 URL 长度限制
                            $videoUrl = substr($video['video_src'], 0, 255);

                            // 构建插入数据
                            $insertData[] = [
                                'video_url'    => $videoUrl,
                                'preview_url'  => '',
                                'status'       => 0,
                                'album_id'     => $album->id,
                                'created_at'   => Carbon::now(),
                                'updated_at'   => Carbon::now(),
                            ];
                        }
                    }

                    // 插入剩余数据
                    if (!empty($insertData)) {
                        DB::table('site_preview_video')->insert($insertData);
                    }
                });

            return true;
        } catch (\Exception $e) {
            Log::error("Video import failed: " . $e->getMessage());
            return false;
        }
    }


}
