<?php

declare(strict_types=1);

namespace App\Services;

use PDO;

final class SalesPostingService
{
    public function __construct(private PDO $pdo)
    {
    }

    public function postStockOutForInvoice(int $invoiceId, int $warehouseId, array $lines, array $itemsMap, ?int $userId): void
    {
        foreach ($lines as $line) {
            $itemId = (int) ($line['item_id'] ?? 0);
            $qty = (float) ($line['qty'] ?? 0);
            if ($itemId <= 0 || $qty <= 0) {
                continue;
            }

            $item = $itemsMap[$itemId] ?? null;
            $cost = (float) ($item['cost'] ?? 0.0);

            $this->pdo->prepare("INSERT INTO stock_moves (ref_type, ref_id, warehouse_id, item_id, qty_in, qty_out, cost, user_id) VALUES ('SALES_INV', ?, ?, ?, 0, ?, ?, ?)")
                ->execute([$invoiceId, $warehouseId, $itemId, $qty, $cost, $userId]);

            if (warehouse_allows_negative($this->pdo, $warehouseId)) {
                stock_balance_apply($this->pdo, $warehouseId, $itemId, -$qty);
            } else {
                stock_balance_deduct_or_fail($this->pdo, $warehouseId, $itemId, $qty);
            }
        }
    }

    public function postPartyLedgerAndCash(
        int $partyId,
        int $invoiceId,
        string $invoiceNo,
        string $invoiceDate,
        float $grandTotal,
        float $paidAmount,
        int $cashboxId,
        ?string $notes,
        ?string $collectionNote,
        ?int $userId,
        bool $isPos = false
    ): void {
        $invoiceNotes = trim((string) $notes);
        if ($invoiceNotes === '' && $isPos) {
            $invoiceNotes = 'فاتورة نقطة بيع';
        }

        party_add_ledger($this->pdo, $partyId, 'SALES_INV', $invoiceId, $invoiceNo, $invoiceDate, $grandTotal, 0.0, $invoiceNotes !== '' ? $invoiceNotes : null);

        if ($paidAmount > 0) {
            $collectNotes = trim((string) $collectionNote);
            if ($collectNotes === '') {
                $collectNotes = ($isPos ? 'تحصيل POS على الفاتورة ' : 'تحصيل على الفاتورة ') . $invoiceNo;
            }

            party_add_ledger($this->pdo, $partyId, 'SALES_RCPT', $invoiceId, $invoiceNo, $invoiceDate, 0.0, $paidAmount, $collectNotes);
            if ($cashboxId > 0) {
                cashbox_add_txn($this->pdo, $cashboxId, date('Y-m-d H:i:s'), 'in', $paidAmount, 'sales_invoice', $invoiceId, $collectNotes, (int) ($userId ?? 0));
            }
        }
    }
}
