<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Services;

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

final class DailyCashMovementService
{
    public static function registerListeners(): void
    {
        EventBus::listen('sale.completed', [self::class, 'onSaleCompleted'], 30);
        EventBus::listen('payment.completed', [self::class, 'onPaymentReceived'], 30);
        EventBus::listen('procurement.payment_completed', [self::class, 'onPaymentMade'], 30);
    }

    public static function record(array $data): int
    {
        $db = App::getInstance()->db();

        return $db->insert('daily_cash_movements', [
            'movement_date' => $data['movement_date'] ?? date('Y-m-d'),
            'movement_type' => $data['movement_type'],
            'direction' => $data['direction'],
            'amount' => $data['amount'],
            'description' => $data['description'] ?? null,
            'reference_type' => $data['reference_type'] ?? null,
            'reference_id' => $data['reference_id'] ?? null,
            'bank_account_id' => $data['bank_account_id'] ?? null,
            'created_at' => date('Y-m-d H:i:s'),
        ]);
    }

    public static function onSaleCompleted(array $data): void
    {
        $amount = (string) ($data['total_amount'] ?? '0');
        if (bccomp($amount, '0', 2) <= 0) return;

        self::record([
            'movement_type' => 'sale',
            'direction' => 'in',
            'amount' => $amount,
            'description' => 'مبيعات — ' . ($data['invoice_number'] ?? ''),
            'reference_type' => 'sales',
            'reference_id' => $data['sale_id'] ?? null,
        ]);
    }

    public static function onPaymentReceived(array $data): void
    {
        $amount = (string) ($data['amount'] ?? '0');
        if (bccomp($amount, '0', 2) <= 0) return;

        self::record([
            'movement_date' => $data['payment_date'] ?? date('Y-m-d'),
            'movement_type' => 'collection',
            'direction' => 'in',
            'amount' => $amount,
            'description' => 'تحصيل — ' . ($data['receipt_number'] ?? ''),
            'reference_type' => 'payments',
            'reference_id' => $data['payment_id'] ?? null,
        ]);
    }

    public static function onPaymentMade(array $data): void
    {
        $amount = (string) ($data['amount'] ?? '0');
        if (bccomp($amount, '0', 2) <= 0) return;

        self::record([
            'movement_type' => 'disbursement',
            'direction' => 'out',
            'amount' => $amount,
            'description' => 'سداد مورد — ' . ($data['payment_number'] ?? ''),
            'reference_type' => 'vendor_payments',
            'reference_id' => $data['payment_id'] ?? null,
        ]);
    }

    public static function getDailySummary(string $date): array
    {
        $db = App::getInstance()->db();

        $inflows = $db->selectOne(
            "SELECT COALESCE(SUM(amount), 0) as total FROM daily_cash_movements WHERE movement_date = ? AND direction = 'in'",
            [$date]
        );
        $outflows = $db->selectOne(
            "SELECT COALESCE(SUM(amount), 0) as total FROM daily_cash_movements WHERE movement_date = ? AND direction = 'out'",
            [$date]
        );

        $totalIn = (string) ($inflows['total'] ?? '0.00');
        $totalOut = (string) ($outflows['total'] ?? '0.00');

        return [
            'date' => $date,
            'total_in' => $totalIn,
            'total_out' => $totalOut,
            'net' => bcsub($totalIn, $totalOut, 2),
        ];
    }

    public static function getMovements(string $date): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM daily_cash_movements WHERE movement_date = ? ORDER BY created_at",
            [$date]
        );
    }
}
