<?php

namespace App\Models;

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

class StockOpnameDetail extends Model
{
    use HasFactory;

    protected $table = 't_stock_opname_details';

    protected $fillable = [
        'so_id',
        'raw_material_id',
        'qty_utuh',
        'qty_pakai',
        'qty_converted',
        'adj_ekstra',
        'adj_restan',
        'adj_ringkas',
        'adj_selisih',
        'item_olahan',
        'lsm_aktual',
        'doi',
        'notes',
        'created_at',
        'updated_at',
    ];

    public function stockOpname()
    {
        return $this->belongsTo(StockOpname::class, 'so_id');
    }

    public function rawMaterial()
    {
        return $this->belongsTo(RawMaterial::class, 'raw_material_id');
    }

    public function changeLogs()
    {
        return $this->hasMany(StockOpnameChangeLog::class, 'so_detail_id');
    }

    // Calculate LSM Aktual: Same as Ending Stock (qty_total)
    // LSM Aktual = Ending Stock = (Qty Utuh × Conversion Factor) + Qty Pakai + Item Olahan
    public function calculateLsmAktual()
    {
        $rawMaterial = $this->rawMaterial;
        $conversionFactor = $rawMaterial && isset($rawMaterial->conversion_factor) ? $rawMaterial->conversion_factor : 1;
        
        // LSM Aktual is the same as Ending Stock (qty_total)
        // Ending Stock = qty_converted + qty_pakai + item_olahan
        $lsmAktual = ($this->qty_utuh * $conversionFactor) + $this->qty_pakai + ($this->item_olahan ?? 0);
        
        // Update without triggering events to prevent infinite loop
        $this->timestamps = false;
        $this->updateQuietly(['lsm_aktual' => $lsmAktual]);
        $this->timestamps = true;
        
        return $lsmAktual;
    }

    // Calculate DOI: LSM Aktual / Average 7-day forecast (excluding today)
    public function calculateDoi()
    {
        $stockOpname = $this->stockOpname;
        if (!$stockOpname) return 0;

        // Get 7-day forecast average (excluding today)
        $startDate = $stockOpname->so_date->copy()->addDay(); // Tomorrow
        $endDate = $startDate->copy()->addDays(6); // Next 7 days
        
        $avgForecast = \App\Models\Forecast::where('store_id', $stockOpname->store_id)
            ->where('raw_material_id', $this->raw_material_id)
            ->whereBetween('forecast_date', [$startDate, $endDate])
            ->avg('forecast_qty');

        $doi = $avgForecast > 0 ? ($this->lsm_aktual / $avgForecast) : 0;
        
        // Update without triggering events to prevent infinite loop
        $this->timestamps = false;
        $this->updateQuietly(['doi' => $doi]);
        $this->timestamps = true;
        
        return $doi;
    }

    // Check if adjustments should be shown (inv_matrix_flag = 1)
    public function shouldShowAdjustments()
    {
        return $this->rawMaterial && $this->rawMaterial->inv_matrix_flag == 1;
    }

    // Log field changes for audit trail
    public function logFieldChange($fieldName, $oldValue, $newValue, $reason = null)
    {
        if ($oldValue != $newValue) {
            StockOpnameChangeLog::logChange(
                $this->id,
                $fieldName,
                $oldValue,
                $newValue,
                $reason
            );
        }
    }

    // Override update method to log changes
    public function update(array $attributes = [], array $options = [])
    {
        $trackableFields = ['qty_utuh', 'qty_pakai', 'adj_ekstra', 'adj_restan', 'adj_ringkas', 'adj_selisih'];
        
        foreach ($trackableFields as $field) {
            if (isset($attributes[$field]) && $this->$field != $attributes[$field]) {
                $this->logFieldChange($field, $this->$field, $attributes[$field]);
            }
        }

        return parent::update($attributes, $options);
    }

    // Auto calculate qty_converted and lsm_aktual when saving
    protected static function boot()
    {
        parent::boot();

        static::saving(function ($model) {
            // Load rawMaterial with activeConversion if not already loaded
            if (!$model->relationLoaded('rawMaterial')) {
                $model->load('rawMaterial.activeConversion');
            }
            
            $rawMaterial = $model->rawMaterial;
            if ($rawMaterial) {
                // Get conversion factor from active item conversion
                $activeConversion = $rawMaterial->activeConversion;
                $conversionFactor = $activeConversion ? $activeConversion->conversion_factor : 1;
                
                \Log::info('StockOpnameDetail saving calculation', [
                    'raw_material_id' => $rawMaterial->id,
                    'has_active_conversion' => $activeConversion !== null,
                    'conversion_factor' => $conversionFactor,
                    'qty_utuh' => $model->qty_utuh,
                    'qty_pakai' => $model->qty_pakai,
                ]);
                
                // qty_converted = qty_utuh * conversion_factor
                $model->qty_converted = $model->qty_utuh * $conversionFactor;
                
                // lsm_aktual (Ending Stock) = qty_converted + qty_pakai + item_olahan
                $model->lsm_aktual = $model->qty_converted + $model->qty_pakai + ($model->item_olahan ?? 0);
                
                \Log::info('StockOpnameDetail calculated values', [
                    'qty_converted' => $model->qty_converted,
                    'lsm_aktual' => $model->lsm_aktual,
                    'item_olahan' => $model->item_olahan ?? 0,
                ]);
            } else {
                \Log::warning('StockOpnameDetail: rawMaterial not found', [
                    'raw_material_id' => $model->raw_material_id
                ]);
            }
        });

        // Removed static::saved event to prevent infinite loop
        // DOI calculation will be called manually when needed
    }
}