<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Services;

use App\Core\App;

final class AccountStatementService
{
    public static function getCustomerStatement(int $memberId, ?string $dateFrom = null, ?string $dateTo = null): array
    {
        $db = App::getInstance()->db();
        $where = 'member_id = ?';
        $params = [$memberId];

        if ($dateFrom) {
            $where .= ' AND transaction_date >= ?';
            $params[] = $dateFrom;
        }
        if ($dateTo) {
            $where .= ' AND transaction_date <= ?';
            $params[] = $dateTo;
        }

        $transactions = $db->select(
            "SELECT * FROM customer_transactions WHERE {$where} ORDER BY transaction_date ASC, id ASC",
            $params
        );

        $runningBalance = '0.00';
        if ($dateFrom) {
            $priorRow = $db->selectOne(
                "SELECT COALESCE(SUM(debit) - SUM(credit), 0) as balance
                 FROM customer_transactions WHERE member_id = ? AND transaction_date < ?",
                [$memberId, $dateFrom]
            );
            $runningBalance = (string) ($priorRow['balance'] ?? '0.00');
        }

        $result = [];
        foreach ($transactions as $tx) {
            $runningBalance = bcadd(bcsub($runningBalance, (string) $tx['credit'], 2), (string) $tx['debit'], 2);
            $tx['running_balance'] = $runningBalance;
            $result[] = $tx;
        }

        $totalDebit = '0.00';
        $totalCredit = '0.00';
        foreach ($transactions as $tx) {
            $totalDebit = bcadd($totalDebit, (string) $tx['debit'], 2);
            $totalCredit = bcadd($totalCredit, (string) $tx['credit'], 2);
        }

        return [
            'transactions' => $result,
            'opening_balance' => $dateFrom ? (string) ($priorRow['balance'] ?? '0.00') : '0.00',
            'total_debit' => $totalDebit,
            'total_credit' => $totalCredit,
            'closing_balance' => $runningBalance,
        ];
    }

    public static function getSupplierStatement(int $supplierId, ?string $dateFrom = null, ?string $dateTo = null): array
    {
        $db = App::getInstance()->db();
        $where = 'supplier_id = ?';
        $params = [$supplierId];

        if ($dateFrom) {
            $where .= ' AND transaction_date >= ?';
            $params[] = $dateFrom;
        }
        if ($dateTo) {
            $where .= ' AND transaction_date <= ?';
            $params[] = $dateTo;
        }

        $transactions = $db->select(
            "SELECT * FROM supplier_transactions WHERE {$where} ORDER BY transaction_date ASC, id ASC",
            $params
        );

        $runningBalance = '0.00';
        if ($dateFrom) {
            $priorRow = $db->selectOne(
                "SELECT COALESCE(SUM(credit) - SUM(debit), 0) as balance
                 FROM supplier_transactions WHERE supplier_id = ? AND transaction_date < ?",
                [$supplierId, $dateFrom]
            );
            $runningBalance = (string) ($priorRow['balance'] ?? '0.00');
        }

        $result = [];
        foreach ($transactions as $tx) {
            $runningBalance = bcadd(bcsub($runningBalance, (string) $tx['debit'], 2), (string) $tx['credit'], 2);
            $tx['running_balance'] = $runningBalance;
            $result[] = $tx;
        }

        $totalDebit = '0.00';
        $totalCredit = '0.00';
        foreach ($transactions as $tx) {
            $totalDebit = bcadd($totalDebit, (string) $tx['debit'], 2);
            $totalCredit = bcadd($totalCredit, (string) $tx['credit'], 2);
        }

        return [
            'transactions' => $result,
            'opening_balance' => $dateFrom ? (string) ($priorRow['balance'] ?? '0.00') : '0.00',
            'total_debit' => $totalDebit,
            'total_credit' => $totalCredit,
            'closing_balance' => $runningBalance,
        ];
    }

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

        return $db->insert('customer_transactions', [
            'member_id' => (int) $data['member_id'],
            'transaction_date' => $data['transaction_date'] ?? date('Y-m-d'),
            'document_type' => $data['document_type'],
            'document_id' => $data['document_id'] ?? null,
            'document_number' => $data['document_number'] ?? null,
            'description' => $data['description'],
            'debit' => $data['debit'] ?? '0.00',
            'credit' => $data['credit'] ?? '0.00',
            'branch_id' => $data['branch_id'] ?? null,
        ]);
    }

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

        return $db->insert('supplier_transactions', [
            'supplier_id' => (int) $data['supplier_id'],
            'transaction_date' => $data['transaction_date'] ?? date('Y-m-d'),
            'document_type' => $data['document_type'],
            'document_id' => $data['document_id'] ?? null,
            'document_number' => $data['document_number'] ?? null,
            'description' => $data['description'],
            'debit' => $data['debit'] ?? '0.00',
            'credit' => $data['credit'] ?? '0.00',
        ]);
    }
}
