<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PosSetting extends Model
{
    use HasFactory;

    protected $fillable = [
        'restaurant_id',
        'branch_id',
        'key',
        'value',
        'type',
        'description',
    ];

    protected $casts = [
        'value' => 'string',
    ];

    /**
     * Get the restaurant that owns the setting
     */
    public function restaurant()
    {
        return $this->belongsTo(Restaurant::class, 'restaurant_id');
    }

    /**
     * Get the branch that owns the setting
     */
    public function branch()
    {
        return $this->belongsTo(Branch::class, 'branch_id');
    }

    /**
     * Scope to filter by restaurant
     */
    public function scopeForRestaurant($query, $restaurantId)
    {
        return $query->where('restaurant_id', $restaurantId)
            ->whereNull('branch_id');
    }

    /**
     * Scope to filter by branch
     */
    public function scopeForBranch($query, $branchId)
    {
        return $query->where('branch_id', $branchId);
    }

    /**
     * Get the typed value based on type
     */
    public function getValue()
    {
        switch ($this->type) {
            case 'boolean':
                return filter_var($this->value, FILTER_VALIDATE_BOOLEAN);
            case 'number':
                return is_numeric($this->value) ? (strpos($this->value, '.') !== false ? (float) $this->value : (int) $this->value) : 0;
            case 'json':
                return json_decode($this->value, true);
            default:
                return $this->value;
        }
    }

    /**
     * Set the value with proper type conversion
     */
    public function setValue($value)
    {
        switch ($this->type) {
            case 'boolean':
                $this->value = $value ? '1' : '0';
                break;
            case 'number':
                $this->value = (string) $value;
                break;
            case 'json':
                $this->value = json_encode($value);
                break;
            default:
                $this->value = (string) $value;
        }
    }

    /**
     * Get a setting value by key with fallback priority
     * Priority: branch setting > restaurant setting > default
     * 
     * @param string $key
     * @param int|null $restaurantId
     * @param int|null $branchId
     * @param mixed $default
     * @return mixed
     */
    public static function getSetting($key, $restaurantId = null, $branchId = null, $default = null)
    {
        // First try to get branch-specific setting
        if ($branchId) {
            $branchSetting = static::where('key', $key)
                ->where('branch_id', $branchId)
                ->first();
            
            if ($branchSetting) {
                return $branchSetting->getValue();
            }
        }

        // Then try restaurant-level setting
        if ($restaurantId) {
            $restaurantSetting = static::where('key', $key)
                ->where('restaurant_id', $restaurantId)
                ->whereNull('branch_id')
                ->first();
            
            if ($restaurantSetting) {
                return $restaurantSetting->getValue();
            }
        }

        // Return default if nothing found
        return $default;
    }

    /**
     * Set a setting value
     * 
     * @param string $key
     * @param mixed $value
     * @param string $type
     * @param int|null $restaurantId
     * @param int|null $branchId
     * @param string|null $description
     * @return PosSetting
     */
    public static function setSetting($key, $value, $type = 'string', $restaurantId = null, $branchId = null, $description = null)
    {
        $setting = static::updateOrCreate(
            [
                'restaurant_id' => $restaurantId,
                'branch_id' => $branchId,
                'key' => $key,
            ],
            [
                'type' => $type,
                'description' => $description,
            ]
        );

        $setting->setValue($value);
        $setting->save();

        return $setting;
    }
}

