<?php

namespace App\Nexus\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

class NexusConfig extends Model
{
    protected $table = 'nexus_config';

    protected $fillable = [
        'key',
        'value',
        'type',
        'group',
        'description',
        'is_editable',
    ];

    protected $casts = [
        'is_editable' => 'boolean',
    ];

    // Cache TTL in seconds — config rarely changes, cache aggressively
    const CACHE_TTL = 300; // 5 minutes
    const CACHE_PREFIX = 'nexus_config_';

    // ─── CORE READ METHODS ───

    /**
     * Get a config value by key, cast to correct type.
     * Returns $default if key does not exist.
     */
    public static function get(string $key, mixed $default = null): mixed
    {
        $cacheKey = self::CACHE_PREFIX . $key;

        $row = Cache::remember($cacheKey, self::CACHE_TTL, function () use ($key) {
            return static::where('key', $key)->first();
        });

        if (!$row) return $default;

        return self::castValue($row->value, $row->type);
    }

    /**
     * Get all config rows for a group
     */
    public static function getGroup(string $group): array
    {
        $rows = static::where('group', $group)->get();
        $result = [];
        foreach ($rows as $row) {
            $result[$row->key] = self::castValue($row->value, $row->type);
        }
        return $result;
    }

    /**
     * Set a config value — flushes cache after update
     */
    public static function set(string $key, mixed $value): bool
    {
        $updated = static::where('key', $key)->update(['value' => (string) $value]);
        Cache::forget(self::CACHE_PREFIX . $key);
        return $updated > 0;
    }

    // ─── CONVENIENCE METHODS ───

    public static function isEngineActive(): bool
    {
        return self::get('nexus_status') === 'active';
    }

    public static function isEnginePaused(): bool
    {
        return (bool) self::get('emergency_pause', false);
    }

    public static function getSessionTime(int $sessionNumber): string
    {
        return self::get("session_{$sessionNumber}_start_utc", '00:00');
    }

    public static function getSessionDuration(): int
    {
        return (int) self::get('session_duration_minutes', 60);
    }

    public static function getWinRate(int $sessionNumber): float
    {
        return (float) self::get("win_rate_session_{$sessionNumber}", 50);
    }

    public static function getLossRequirementRange(): array
    {
        return [
            'min' => (float) self::get('loss_requirement_min', 5),
            'max' => (float) self::get('loss_requirement_max', 20),
        ];
    }

    public static function getBuybackZonePercent(): float
    {
        return (float) self::get('buyback_zone_percent', 5);
    }

    public static function getRecessThreshold(): float
    {
        return (float) self::get('recess_threshold_percent', 10);
    }

    public static function getExcessThreshold(): float
    {
        return (float) self::get('excess_threshold_percent', 30);
    }

    // ─── TYPE CASTING ───

    private static function castValue(mixed $value, string $type): mixed
    {
        return match ($type) {
            'integer' => (int) $value,
            'decimal' => (float) $value,
            'boolean' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
            'json'    => json_decode($value, true),
            default   => $value,
        };
    }
}
