<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Production extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'batch_no',
        'date',
        'machine',
        'raw_material_cost',
        'agent_commission',
        'transportation_cost',
        'labor_cost',
        'electricity_cost',
        'other_expenses',
        'other_expenses_description',
        'total_cost',
        'output_quantity',
        'wastage_quantity',
        'cost_per_unit',
        'narration',
        'status',
        'created_by',
    ];

    protected $casts = [
        'date' => 'date',
        'raw_material_cost' => 'decimal:2',
        'agent_commission' => 'decimal:2',
        'transportation_cost' => 'decimal:2',
        'labor_cost' => 'decimal:2',
        'electricity_cost' => 'decimal:2',
        'other_expenses' => 'decimal:2',
        'total_cost' => 'decimal:2',
        'output_quantity' => 'decimal:3',
        'wastage_quantity' => 'decimal:3',
        'cost_per_unit' => 'decimal:2',
    ];

    /**
     * Production items relationship
     */
    public function items(): HasMany
    {
        return $this->hasMany(ProductionItem::class);
    }

    /**
     * Input items (raw materials)
     */
    public function inputItems(): HasMany
    {
        return $this->hasMany(ProductionItem::class)->where('type', 'input');
    }

    /**
     * Output items (finished goods)
     */
    public function outputItems(): HasMany
    {
        return $this->hasMany(ProductionItem::class)->where('type', 'output');
    }

    /**
     * Wastage items
     */
    public function wastageItems(): HasMany
    {
        return $this->hasMany(ProductionItem::class)->where('type', 'wastage');
    }

    /**
     * Created by user
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Generate batch number
     */
    public static function generateBatchNo(): string
    {
        $prefix = 'PRD-' . date('Ym') . '-';
        $lastProduction = self::withTrashed()
            ->where('batch_no', 'like', $prefix . '%')
            ->orderBy('batch_no', 'desc')
            ->first();

        if ($lastProduction) {
            $lastNumber = (int) substr($lastProduction->batch_no, -4);
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }

        return $prefix . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
    }

    /**
     * Calculate total cost
     */
    public function calculateTotalCost(): float
    {
        return $this->raw_material_cost 
            + $this->agent_commission 
            + $this->transportation_cost 
            + $this->labor_cost 
            + $this->electricity_cost 
            + $this->other_expenses;
    }

    /**
     * Calculate cost per unit
     */
    public function calculateCostPerUnit(): float
    {
        if ($this->output_quantity > 0) {
            return $this->total_cost / $this->output_quantity;
        }
        return 0;
    }

    /**
     * Update stock for production (reduce raw materials, add finished goods)
     */
    public function updateStock(): void
    {
        // Reduce raw material stock
        foreach ($this->inputItems as $item) {
            $item->item->reduceStock($item->quantity, 'production', "Production Batch: {$this->batch_no}");
        }

        // Add finished goods stock
        foreach ($this->outputItems as $item) {
            $item->item->addStock($item->quantity, 'production', "Production Batch: {$this->batch_no}");
            
            // Update item's purchase price to the calculated cost per unit
            $item->item->update(['purchase_price' => $this->cost_per_unit]);
        }
    }

    /**
     * Reverse stock changes (for delete/cancel)
     */
    public function reverseStock(): void
    {
        // Add back raw material stock
        foreach ($this->inputItems as $item) {
            $item->item->addStock($item->quantity, 'production_reverse', "Reversed Production: {$this->batch_no}");
        }

        // Reduce finished goods stock
        foreach ($this->outputItems as $item) {
            $item->item->reduceStock($item->quantity, 'production_reverse', "Reversed Production: {$this->batch_no}");
        }
    }
}
