<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Setting extends Model
{
    protected $fillable = ['key', 'value'];

    private static array $cache = [];

    public static function get(string $key, mixed $default = null): mixed
    {
        if (! array_key_exists($key, self::$cache)) {
            $row = static::where('key', $key)->first();
            self::$cache[$key] = $row ? $row->value : $default;
        }
        return self::$cache[$key];
    }

    public static function set(string $key, mixed $value): void
    {
        static::updateOrCreate(['key' => $key], ['value' => (string) $value]);
        self::$cache[$key] = (string) $value;
    }

    /** Returns the configured FFmpeg binary path, falling back to the config file default. */
    public static function ffmpegBinary(): string
    {
        return static::get('ffmpeg_binary', config('ffmpeg.ffmpeg', '/usr/bin/ffmpeg'));
    }

    public static function gpuEnabled(): bool
    {
        return static::get('gpu_enabled', 'true') === 'true';
    }

    public static function gpuDevice(): int
    {
        return (int) static::get('gpu_device', '0');
    }

    public static function gpuEncoder(): string
    {
        return static::gpuEnabled()
            ? static::get('gpu_encoder', 'h264_nvenc')
            : 'libx264';
    }

    public static function gpuPreset(): string
    {
        return static::gpuEnabled()
            ? static::get('gpu_preset', 'p4')
            : 'fast';
    }

    public static function gpuHwaccel(): string
    {
        return static::get('gpu_hwaccel', 'cuda');
    }

    /** Returns the full video codec flags for FFmpeg shell commands. */
    public static function ffmpegVideoFlags(bool $stillImage = false): string
    {
        if (static::gpuEnabled()) {
            $enc    = static::get('gpu_encoder', 'h264_nvenc');
            $preset = static::get('gpu_preset',  'p4');
            $device = static::gpuDevice();
            $gpuFlag = str_contains($enc, 'nvenc') ? " -gpu {$device}" : '';
            return "-c:v {$enc} -preset {$preset} -rc vbr -cq 23{$gpuFlag} -pix_fmt yuv420p";
        }
        $tune = $stillImage ? ' -tune stillimage' : '';
        return "-c:v libx264 -preset fast -crf 23{$tune} -pix_fmt yuv420p";
    }

    /** CPU-only video codec flags — used as automatic fallback when GPU encoding fails. */
    public static function ffmpegVideoFlagsCpu(bool $stillImage = false): string
    {
        $tune = $stillImage ? ' -tune stillimage' : '';
        return "-c:v libx264 -preset fast -crf 23{$tune} -pix_fmt yuv420p";
    }

    /** Returns hwaccel decode flags when the input source is a video file. */
    public static function ffmpegHwaccelFlags(bool $inputIsVideo): string
    {
        if (! $inputIsVideo || ! static::gpuEnabled()) return '';
        $hwaccel = static::get('gpu_hwaccel', 'cuda');
        $device  = static::gpuDevice();
        return "-hwaccel {$hwaccel} -hwaccel_device {$device} ";
    }
}
