<?php

namespace App\Models;

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

class Setting extends Model
{
    use HasFactory;

    protected $fillable = [
        'group',
        'key',
        'value',
        'type',
        'country_id',
        'is_country_specific',
        'is_public',
        'is_locked',
        'description',
        'order',
    ];

    protected $casts = [
        'is_country_specific' => 'boolean',
        'is_public' => 'boolean',
        'is_locked' => 'boolean',
        'order' => 'integer',
    ];

    // Relations
    public function country()
    {
        return $this->belongsTo(Country::class);
    }

    // Scopes
    public function scopeByGroup($query, $group)
    {
        return $query->where('group', $group);
    }

    public function scopeByKey($query, $key)
    {
        return $query->where('key', $key);
    }

    public function scopePublic($query)
    {
        return $query->where('is_public', true);
    }

    public function scopeCountrySpecific($query)
    {
        return $query->where('is_country_specific', true);
    }

    public function scopeGlobal($query)
    {
        return $query->whereNull('country_id');
    }

    public function scopeForCountry($query, $countryId)
    {
        return $query->where('country_id', $countryId);
    }

    public function scopeOrdered($query)
    {
        return $query->orderBy('order')->orderBy('key');
    }

    // Helper Methods

    /**
     * Get setting value with country support
     */
    public static function getValue($group, $key, $default = null, $countryId = null)
    {
        $cacheKey = "setting_{$group}_{$key}" . ($countryId ? "_{$countryId}" : '');
        
        return Cache::remember($cacheKey, 3600, function () use ($group, $key, $default, $countryId) {
            // First try country-specific setting if country is provided
            if ($countryId) {
                $setting = static::where('group', $group)
                    ->where('key', $key)
                    ->where('country_id', $countryId)
                    ->first();
                
                if ($setting) {
                    return static::castValue($setting->value, $setting->type);
                }
            }
            
            // Fallback to global setting
            $setting = static::where('group', $group)
                ->where('key', $key)
                ->whereNull('country_id')
                ->first();
            
            if ($setting) {
                return static::castValue($setting->value, $setting->type);
            }
            
            return $default;
        });
    }

    /**
     * Set setting value with country support
     */
    public static function setValue($group, $key, $value, $countryId = null, $type = 'string')
    {
        $setting = static::updateOrCreate(
            [
                'group' => $group,
                'key' => $key,
                'country_id' => $countryId,
            ],
            [
                'value' => $value,
                'type' => $type,
            ]
        );

        // Clear cache
        $cacheKey = "setting_{$group}_{$key}" . ($countryId ? "_{$countryId}" : '');
        Cache::forget($cacheKey);
        Cache::forget("settings_group_{$group}");
        if ($countryId) {
            Cache::forget("settings_group_{$group}_{$countryId}");
        }

        return $setting;
    }

    /**
     * Get all settings for a group with country support
     */
    public static function getGroup($group, $countryId = null)
    {
        $cacheKey = "settings_group_{$group}" . ($countryId ? "_{$countryId}" : '');
        
        return Cache::remember($cacheKey, 3600, function () use ($group, $countryId) {
            $settings = [];
            
            // Get unique keys for this group
            $keys = static::where('group', $group)->distinct()->pluck('key');
            
            foreach ($keys as $key) {
                $value = static::getValue($group, $key, null, $countryId);
                if ($value !== null) {
                    $settings[$key] = $value;
                }
            }
            
            return $settings;
        });
    }

    /**
     * Set multiple settings for a group
     */
    public static function setGroup($group, array $settings, $countryId = null)
    {
        foreach ($settings as $key => $value) {
            static::setValue($group, $key, $value, $countryId);
        }
    }

    /**
     * Cast value based on type
     */
    protected static function castValue($value, $type)
    {
        switch ($type) {
            case 'boolean':
                return filter_var($value, FILTER_VALIDATE_BOOLEAN);
            case 'number':
                return is_numeric($value) ? (float) $value : $value;
            case 'json':
                return is_string($value) ? json_decode($value, true) : $value;
            default:
                return $value;
        }
    }

    /**
     * Get SEO settings for a specific country
     */
    public static function getSeoForCountry($countryId)
    {
        return static::getGroup('seo', $countryId);
    }

    /**
     * Get all countries that have custom SEO settings
     */
    public static function getCountriesWithCustomSeo()
    {
        return Country::whereHas('settings', function ($query) {
            $query->where('group', 'seo');
        })->get();
    }

    /**
     * Copy SEO settings from one country to another
     */
    public static function copySeoSettings($fromCountryId, $toCountryId)
    {
        $seoSettings = static::where('group', 'seo')
            ->where('country_id', $fromCountryId)
            ->get();

        foreach ($seoSettings as $setting) {
            static::setValue('seo', $setting->key, $setting->value, $toCountryId, $setting->type);
        }
    }
}