<?php

namespace App\Models;

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

class ScoopWeightConfig extends Model
{
    use HasFactory;

    protected $fillable = [
        'scoop_count',
        'total_weight_grams',
        'weight_per_scoop_grams',
        'min_weight_grams',
        'max_weight_grams',
        'is_active',
        'notes',
    ];

    protected $casts = [
        'scoop_count' => 'integer',
        'total_weight_grams' => 'decimal:2',
        'weight_per_scoop_grams' => 'decimal:2',
        'min_weight_grams' => 'decimal:2',
        'max_weight_grams' => 'decimal:2',
        'is_active' => 'boolean',
    ];

    /**
     * Get weight configuration for a specific scoop count
     */
    public static function getWeightForScoops(int $scoopCount): ?self
    {
        return static::where('scoop_count', $scoopCount)
            ->where('is_active', true)
            ->first();
    }

    /**
     * Calculate weight per scoop for a given total scoop count
     * Uses interpolation if exact scoop count not configured
     */
    public static function calculateWeightPerScoop(int $totalScoops): float
    {
        // Try to get exact configuration
        $config = static::getWeightForScoops($totalScoops);

        if ($config) {
            return (float) $config->weight_per_scoop_grams;
        }

        // If no exact match, interpolate between closest values
        $lower = static::where('scoop_count', '<', $totalScoops)
            ->where('is_active', true)
            ->orderBy('scoop_count', 'desc')
            ->first();

        $upper = static::where('scoop_count', '>', $totalScoops)
            ->where('is_active', true)
            ->orderBy('scoop_count', 'asc')
            ->first();

        if ($lower && $upper) {
            // Linear interpolation
            $scoopDiff = $upper->scoop_count - $lower->scoop_count;
            $weightDiff = $upper->weight_per_scoop_grams - $lower->weight_per_scoop_grams;
            $position = ($totalScoops - $lower->scoop_count) / $scoopDiff;

            return (float) ($lower->weight_per_scoop_grams + ($weightDiff * $position));
        }

        // Fallback to largest configured if beyond range
        if ($lower) {
            return (float) $lower->weight_per_scoop_grams;
        }

        // Absolute fallback
        return 70.0; // Default to single scoop weight
    }

    /**
     * Calculate total weight for a given scoop count
     */
    public static function calculateTotalWeight(int $totalScoops): float
    {
        $config = static::getWeightForScoops($totalScoops);

        if ($config) {
            return (float) $config->total_weight_grams;
        }

        // Interpolate if not found
        $weightPerScoop = static::calculateWeightPerScoop($totalScoops);
        return $weightPerScoop * $totalScoops;
    }

    /**
     * Get all active configurations ordered by scoop count
     */
    public static function getAllActive()
    {
        return static::where('is_active', true)
            ->orderBy('scoop_count', 'asc')
            ->get();
    }

    /**
     * Validate if weight is within tolerance
     */
    public function isWeightWithinTolerance(float $actualWeight): bool
    {
        if ($this->min_weight_grams && $actualWeight < $this->min_weight_grams) {
            return false;
        }

        if ($this->max_weight_grams && $actualWeight > $this->max_weight_grams) {
            return false;
        }

        return true;
    }

    /**
     * Get tolerance percentage
     */
    public function getTolerancePercentage(): float
    {
        if (!$this->min_weight_grams || !$this->max_weight_grams) {
            return 0;
        }

        $range = $this->max_weight_grams - $this->min_weight_grams;
        return ($range / $this->total_weight_grams) * 100;
    }
}
