<?php
declare(strict_types=1);

namespace App\Modules\Treasury\Services;

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

final class CustodyService
{
    public static function recordCollection(int $treasuryId, int $employeeId, string $amount, int $paymentId, string $description = ''): void
    {
        $db = App::getInstance()->db();
        $currentBalance = self::getCurrentBalance($treasuryId, $employeeId);
        $newBalance = bcadd($currentBalance, $amount, 2);

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'collection',
            'amount'         => $amount,
            'balance_after'  => $newBalance,
            'reference_type' => 'payment',
            'reference_id'   => $paymentId,
            'description_ar' => $description ?: 'تحصيل دفعة',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordSettlementOut(int $treasuryId, int $employeeId, string $amount, int $settlementId): void
    {
        $db = App::getInstance()->db();
        $currentBalance = self::getCurrentBalance($treasuryId, $employeeId);
        $newBalance = bcsub($currentBalance, $amount, 2);

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'settlement_out',
            'amount'         => $amount,
            'balance_after'  => $newBalance,
            'reference_type' => 'settlement',
            'reference_id'   => $settlementId,
            'description_ar' => 'تسوية للخزنة الرئيسية',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordSettlementIn(int $treasuryId, int $employeeId, string $amount, int $settlementId): void
    {
        $db = App::getInstance()->db();
        $currentBalance = self::getCurrentBalance($treasuryId, $employeeId);
        $newBalance = bcadd($currentBalance, $amount, 2);

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'settlement_in',
            'amount'         => $amount,
            'balance_after'  => $newBalance,
            'reference_type' => 'settlement',
            'reference_id'   => $settlementId,
            'description_ar' => 'استلام تسوية من خزنة فرعية',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordDeposit(int $treasuryId, int $employeeId, string $amount, int $depositId): void
    {
        $db = App::getInstance()->db();
        $currentBalance = self::getCurrentBalance($treasuryId, $employeeId);
        $newBalance = bcsub($currentBalance, $amount, 2);

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'deposit',
            'amount'         => $amount,
            'balance_after'  => $newBalance,
            'reference_type' => 'deposit',
            'reference_id'   => $depositId,
            'description_ar' => 'إيداع في البنك',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordDepositConfirmed(int $treasuryId, int $employeeId, string $amount, int $depositId): void
    {
        $db = App::getInstance()->db();

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'deposit_confirmed',
            'amount'         => $amount,
            'balance_after'  => self::getCurrentBalance($treasuryId, $employeeId),
            'reference_type' => 'deposit',
            'reference_id'   => $depositId,
            'description_ar' => 'تأكيد إيداع بنكي من مدير الحسابات',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordVoidReversal(int $treasuryId, int $employeeId, string $amount, int $paymentId): void
    {
        $db = App::getInstance()->db();
        $currentBalance = self::getCurrentBalance($treasuryId, $employeeId);
        $newBalance = bcsub($currentBalance, $amount, 2);

        $db->insert('treasury_custody_log', [
            'treasury_id'    => $treasuryId,
            'employee_id'    => $employeeId,
            'action'         => 'void_reversal',
            'amount'         => $amount,
            'balance_after'  => $newBalance,
            'reference_type' => 'payment',
            'reference_id'   => $paymentId,
            'description_ar' => 'إلغاء دفعة - عكس العهدة',
            'created_at'     => date('Y-m-d H:i:s'),
        ]);
    }

    public static function getCurrentBalance(int $treasuryId, int $employeeId): string
    {
        $db = App::getInstance()->db();
        $last = $db->selectOne(
            "SELECT balance_after FROM treasury_custody_log WHERE treasury_id = ? AND employee_id = ? ORDER BY id DESC LIMIT 1",
            [$treasuryId, $employeeId]
        );
        return $last ? (string) $last['balance_after'] : '0.00';
    }

    public static function getTreasuryCustodyBalance(int $treasuryId): string
    {
        $db = App::getInstance()->db();
        $result = $db->selectOne(
            "SELECT COALESCE(
                (SELECT balance_after FROM treasury_custody_log WHERE treasury_id = ? ORDER BY id DESC LIMIT 1),
                0.00
            ) as balance",
            [$treasuryId]
        );
        return (string) ($result['balance'] ?? '0.00');
    }

    public static function getLog(int $treasuryId, ?int $employeeId = null, int $limit = 100): array
    {
        $db = App::getInstance()->db();
        $where = 'cl.treasury_id = ?';
        $params = [$treasuryId];

        if ($employeeId !== null) {
            $where .= ' AND cl.employee_id = ?';
            $params[] = $employeeId;
        }

        return $db->select(
            "SELECT cl.*, e.full_name_ar as employee_name
             FROM treasury_custody_log cl
             LEFT JOIN employees e ON e.id = cl.employee_id
             WHERE {$where}
             ORDER BY cl.id DESC
             LIMIT ?",
            array_merge($params, [$limit])
        );
    }

    public static function getActionLabel(string $action): string
    {
        return match ($action) {
            'collection'        => 'تحصيل',
            'settlement_out'    => 'تسوية صادرة',
            'settlement_in'     => 'تسوية واردة',
            'deposit'           => 'إيداع بنكي',
            'deposit_confirmed' => 'تأكيد إيداع',
            'void_reversal'     => 'عكس إلغاء',
            default             => $action,
        };
    }
}
