<?php
declare(strict_types=1);

namespace App\Modules\Inventory\Models;

use App\Core\Model;
use App\Core\App;

class ItemWarehouseStock extends Model
{
    protected static string $table = 'item_warehouse_stock';
    protected static string $primaryKey = 'id';
    protected static bool $timestamps = false;
    protected static bool $softDelete = false;
    protected static bool $autoTrackAuthor = false;

    protected static array $fillable = [
        'item_id',
        'warehouse_id',
        'quantity',
        'min_level',
        'max_level',
        'last_counted_at',
    ];

    /**
     * Get stock records for a specific item across all warehouses.
     */
    public static function getForItem(int $itemId): array
    {
        return static::query()
            ->where('item_id', '=', $itemId)
            ->orderBy('warehouse_id', 'ASC')
            ->get();
    }

    /**
     * Get all item stock records for a specific warehouse.
     */
    public static function getForWarehouse(int $warehouseId): array
    {
        return static::query()
            ->where('warehouse_id', '=', $warehouseId)
            ->orderBy('item_id', 'ASC')
            ->get();
    }

    /**
     * Get the quantity for a specific item in a specific warehouse.
     */
    public static function getQuantity(int $itemId, int $warehouseId): float
    {
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT `quantity` FROM `item_warehouse_stock` WHERE `item_id` = ? AND `warehouse_id` = ?",
            [$itemId, $warehouseId]
        );
        return (float) ($row['quantity'] ?? 0);
    }

    /**
     * Upsert stock: adjust quantity by direction ('in' adds, 'out' subtracts).
     * If no row exists for the item/warehouse pair, a new row is inserted.
     */
    public static function upsertStock(int $itemId, int $warehouseId, string $quantityChange, string $direction): void
    {
        $db = App::getInstance()->db();

        $existing = $db->selectOne(
            "SELECT `id` FROM `item_warehouse_stock` WHERE `item_id` = ? AND `warehouse_id` = ?",
            [$itemId, $warehouseId]
        );

        if ($existing) {
            $operator = $direction === 'in' ? '+' : '-';
            $db->statement(
                "UPDATE `item_warehouse_stock` SET `quantity` = `quantity` {$operator} ?, `updated_at` = NOW() WHERE `item_id` = ? AND `warehouse_id` = ?",
                [$quantityChange, $itemId, $warehouseId]
            );
        } else {
            $qty = $direction === 'in' ? $quantityChange : '-' . $quantityChange;
            $db->insert('item_warehouse_stock', [
                'item_id'      => $itemId,
                'warehouse_id' => $warehouseId,
                'quantity'     => $qty,
                'updated_at'   => date('Y-m-d H:i:s'),
            ]);
        }
    }

    /**
     * Get items where current quantity is at or below the minimum level.
     */
    public static function getLowStockItems(): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT iws.*, i.`name_ar`, i.`sku`, w.`name_ar` as warehouse_name
             FROM `item_warehouse_stock` iws
             JOIN `inventory_items` i ON i.`id` = iws.`item_id`
             JOIN `warehouses` w ON w.`id` = iws.`warehouse_id`
             WHERE iws.`quantity` <= iws.`min_level` AND iws.`min_level` IS NOT NULL
             ORDER BY (iws.`quantity` - iws.`min_level`) ASC"
        );
    }
}
