<?php

namespace App\Models\Warehouse;

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

class DivisionDelivery extends Model
{
    use HasFactory;

    protected $fillable = [
        'division_id',
        'item_id',
        'total_quantity_delivered',
        'current_available_quantity',
        'total_quantity_issued',
        'average_unit_price',
        'total_value',
        'first_delivery_date',
        'last_delivery_date',
        'last_updated'
    ];

    protected $casts = [
        'total_quantity_delivered' => 'decimal:2',
        'current_available_quantity' => 'decimal:2',
        'total_quantity_issued' => 'decimal:2',
        'average_unit_price' => 'decimal:2',
        'total_value' => 'decimal:2',
        'first_delivery_date' => 'date',
        'last_delivery_date' => 'date',
        'last_updated' => 'datetime'
    ];

    /**
     * Get the division that this delivery belongs to
     */
    public function division(): BelongsTo
    {
        return $this->belongsTo(ProjectDivision::class, 'division_id');
    }

    /**
     * Get the item for this delivery record
     */
    public function item(): BelongsTo
    {
        return $this->belongsTo(Item::class);
    }

    /**
     * Update delivery totals when new stock arrives
     */
    public static function recordDelivery($divisionId, $itemId, $quantity, $unitPrice, $deliveryDate = null)
    {
        $deliveryDate = $deliveryDate ?: now()->format('Y-m-d');

        $record = self::firstOrNew([
            'division_id' => $divisionId,
            'item_id' => $itemId
        ]);

        if ($record->exists) {
            // Update existing record
            $totalDeliveredBefore = $record->total_quantity_delivered;
            $totalValueBefore = $record->total_value;

            $record->total_quantity_delivered += $quantity;
            $record->current_available_quantity += $quantity;
            $record->total_value += ($quantity * $unitPrice);
            $record->average_unit_price = $record->total_value / $record->total_quantity_delivered;
            $record->last_delivery_date = $deliveryDate;
        } else {
            // Create new record
            $record->total_quantity_delivered = $quantity;
            $record->current_available_quantity = $quantity;
            $record->total_quantity_issued = 0;
            $record->average_unit_price = $unitPrice;
            $record->total_value = $quantity * $unitPrice;
            $record->first_delivery_date = $deliveryDate;
            $record->last_delivery_date = $deliveryDate;
        }

        $record->last_updated = now();
        $record->save();

        return $record;
    }

    /**
     * Update quantities when items are issued
     */
    public static function recordIssue($divisionId, $itemId, $issuedQuantity)
    {
        $record = self::where('division_id', $divisionId)
            ->where('item_id', $itemId)
            ->first();

        if ($record) {
            $record->current_available_quantity = max(0, $record->current_available_quantity - $issuedQuantity);
            $record->total_quantity_issued += $issuedQuantity;
            $record->last_updated = now();
            $record->save();
        }

        return $record;
    }

    /**
     * Update quantities when items are returned from site
     * Note: This only updates current_available_quantity and reduces issued quantity.
     * It does NOT increase total_quantity_delivered (returns are not new deliveries).
     */
    public static function recordReturn($divisionId, $itemId, $returnedQuantity)
    {
        $record = self::where('division_id', $divisionId)
            ->where('item_id', $itemId)
            ->first();

        if ($record) {
            // Increase available quantity (items returned to warehouse)
            $record->current_available_quantity += $returnedQuantity;
            // Decrease issued quantity (items no longer at project site)
            $record->total_quantity_issued = max(0, $record->total_quantity_issued - $returnedQuantity);
            $record->last_updated = now();
            $record->save();
        }

        return $record;
    }

    /**
     * Update quantities when damaged items are returned from site
     * Damaged items reduce the issued quantity but do NOT return to available inventory
     * since they are being written off or converted to FOC (Free of Charge) inventory.
     *
     * @param int $divisionId The division ID
     * @param int $itemId The item ID
     * @param float $damagedQuantity The quantity of damaged items being returned
     * @return DivisionDelivery|null The updated record or null if not found
     */
    public static function recordDamagedReturn($divisionId, $itemId, $damagedQuantity)
    {
        $record = self::where('division_id', $divisionId)
            ->where('item_id', $itemId)
            ->first();

        if ($record) {
            // Decrease issued quantity (items no longer at project site)
            // but do NOT increase available quantity (damaged items don't return to stock)
            $record->total_quantity_issued = max(0, $record->total_quantity_issued - $damagedQuantity);
            $record->last_updated = now();
            $record->save();

            \Log::info("Recorded damaged return for division {$divisionId}, item {$itemId}: {$damagedQuantity} units", [
                'division_id' => $divisionId,
                'item_id' => $itemId,
                'damaged_quantity' => $damagedQuantity,
                'remaining_issued' => $record->total_quantity_issued,
                'available_unchanged' => $record->current_available_quantity
            ]);
        } else {
            \Log::warning("Could not record damaged return - no division delivery record found", [
                'division_id' => $divisionId,
                'item_id' => $itemId,
                'damaged_quantity' => $damagedQuantity
            ]);
        }

        return $record;
    }

    /**
     * Get delivery summary for a division
     */
    public static function getDivisionSummary($divisionId)
    {
        return self::where('division_id', $divisionId)
            ->with('item')
            ->orderBy('total_quantity_delivered', 'desc')
            ->get();
    }

    /**
     * Get delivery summary for an item across all divisions
     */
    public static function getItemSummary($itemId)
    {
        return self::where('item_id', $itemId)
            ->with('division')
            ->orderBy('total_quantity_delivered', 'desc')
            ->get();
    }
}