<?php
declare(strict_types=1);

namespace App\Modules\Inventory\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;

final class OpeningBalanceService
{
    public static function saveBalances(int $warehouseId, string $balanceDate, array $items): array
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        if (empty($items)) {
            return ['success' => false, 'error' => 'يجب إضافة صنف واحد على الأقل'];
        }

        $db->beginTransaction();
        try {
            $savedCount = 0;
            foreach ($items as $item) {
                $itemId = (int) ($item['item_id'] ?? 0);
                if ($itemId <= 0) continue;

                $quantity = (string) ($item['quantity'] ?? '0');
                $unitCost = (string) ($item['unit_cost'] ?? '0');
                $totalCost = bcmul($quantity, $unitCost, 2);

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

                if ($existing) {
                    $db->update('inventory_opening_balances', [
                        'quantity' => $quantity,
                        'unit_cost' => $unitCost,
                        'total_cost' => $totalCost,
                        'updated_at' => date('Y-m-d H:i:s'),
                    ], 'id = ?', [(int) $existing['id']]);
                } else {
                    $db->insert('inventory_opening_balances', [
                        'item_id' => $itemId,
                        'warehouse_id' => $warehouseId,
                        'balance_date' => $balanceDate,
                        'quantity' => $quantity,
                        'unit_cost' => $unitCost,
                        'total_cost' => $totalCost,
                        'created_by' => $employee ? (int) $employee->id : null,
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                    ]);
                }

                // Also update the actual stock with an opening stock movement
                StockService::moveStock([
                    'item_id' => $itemId,
                    'warehouse_id' => $warehouseId,
                    'movement_type' => 'opening_balance',
                    'direction' => 'in',
                    'quantity' => $quantity,
                    'unit_cost' => $unitCost,
                    'reference_type' => 'opening_balance',
                    'notes' => 'رصيد افتتاحي — ' . $balanceDate,
                ]);

                $savedCount++;
            }

            $db->commit();

            EventBus::dispatch('inventory.opening_balance_saved', [
                'warehouse_id' => $warehouseId,
                'balance_date' => $balanceDate,
                'items_count' => $savedCount,
            ]);

            Logger::info("Opening balances saved: {$savedCount} items in warehouse #{$warehouseId}");

            return ['success' => true, 'saved_count' => $savedCount];
        } catch (\Throwable $e) {
            $db->rollBack();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    public static function getBalances(int $warehouseId, ?string $balanceDate = null): array
    {
        $db = App::getInstance()->db();

        $sql = "SELECT ob.*, i.name_ar, i.sku
                FROM inventory_opening_balances ob
                JOIN inventory_items i ON i.id = ob.item_id
                WHERE ob.warehouse_id = ?";
        $params = [$warehouseId];

        if ($balanceDate) {
            $sql .= " AND ob.balance_date = ?";
            $params[] = $balanceDate;
        }

        $sql .= " ORDER BY i.name_ar";

        return $db->select($sql, $params);
    }
}
