<?php

namespace App\Console\Commands;

use App\FaceSwapJob;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use App\Jobs\ProcessFaceSwapInsightface;

class Faceswap extends Command
{
	/**
	 * The name and signature of the console command.
	 *
	 * @var string
	 */
	protected $signature = 'faceswap:make {source} {target}';
	
	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Create a face swap image: --source path/to/source --target path/to/target';
	
	protected $filePath;
	protected $resultPath;
	
	/**
	 * Create a new command instance.
	 *
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();
		$this->filePath = public_path("face-swap/uploads/");
		$this->resultPath = public_path("face-swap/results/");
	}
	
	/**
	 * Execute the console command.
	 *
	 * @return int
	 */
	public function handle()
	{
		try {
			// Add time to start time
			$startTime = microtime(true);
			
			$sourceFileName = $this->argument('source');
			$targetFileName = $this->argument('target');
			
			$sourcePath = $this->filePath . $sourceFileName;
			if (!file_exists($sourcePath)) {
				$this->error("Source file \"{$sourceFileName}\" not found.");
				return 0;
			}
			
			$targetPath = $this->filePath . $targetFileName;
			if (!file_exists($targetPath)) {
				$this->error("Target file \"{$targetFileName}\" not found.");
				return 0;
			}
			
			$this->line("[Faceswap] Processing...");
			$bar = $this->output->createProgressBar(100);
			$bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %message%');
			$bar->setMessage("");
			
			$code = md5(rand(1, 9999) . now());
			$outputPath = $this->resultPath . $code . ".jpg";
			
			$job = FaceSwapJob::create([
				'code'        => $code,
				'source_path' => $sourcePath,
				'target_path' => $targetPath,
				'output_path' => $outputPath,
				'status'      => 'pending'
			]);
			
			ProcessFaceSwapInsightface::dispatch($job)->onQueue(config('queue.connections.redis.queue'));
			
			// Wait and checking status
			$attempts = 0;
			$maxAttempts = 30;
			while ($attempts < $maxAttempts) {
				$jobCheck = FaceSwapJob::findOrFail($job->id);
				if ($jobCheck && $jobCheck->status == "processing") {
					$bar->setMessage("...");
					$bar->advance();
				} elseif ($jobCheck && $jobCheck->status == "finished") {
					$bar->setMessage("...Done");
					$bar->advance();
					$bar->finish();
					
					// Calculate the processing time
					$endTime = microtime(true);
					$executionTime = round($endTime - $startTime, 2);
					
					$this->line('');
					$this->info("[Faceswap] Finished ({$executionTime} seconds) result file: {$outputPath}");
					
					return 0;
				}
				sleep(1);
				$attempts++;
			}
			
			// Tính thời gian khi timeout
			$endTime = microtime(true);
			$executionTime = round($endTime - $startTime, 2);
			
			$this->error("[Faceswap] Error: Timeout waiting 30s for face swap processing.");
			$this->error("[Faceswap] Total execution time: {$executionTime} seconds");
		} catch (\Exception $e) {
			// Tính thời gian khi có lỗi
			$endTime = microtime(true);
			$executionTime = round($endTime - $startTime, 2);
			
			$this->error("[Faceswap] Error: " . $e->getMessage());
			$this->error("[Faceswap] Total execution time: {$executionTime} seconds");
		}
	}
}
