<?php
declare(strict_types=1);

namespace App\Modules\Procurement\Services;

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

final class SupplierPaymentScheduleService
{
    public static function createSchedule(array $data): array
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        $totalAmount = (string) $data['total_amount'];
        $installmentsCount = (int) $data['installments_count'];
        $startDate = $data['start_date'];
        $intervalDays = (int) ($data['interval_days'] ?? 30);

        $scheduleNumber = 'SCHED-' . date('Ymd') . '-' . str_pad((string) random_int(1, 9999), 4, '0', STR_PAD_LEFT);
        $installmentAmount = bcdiv($totalAmount, (string) $installmentsCount, 2);
        $remainder = bcsub($totalAmount, bcmul($installmentAmount, (string) $installmentsCount, 2), 2);

        $db->beginTransaction();
        try {
            $scheduleId = $db->insert('supplier_payment_schedules', [
                'supplier_id' => (int) $data['supplier_id'],
                'invoice_id' => $data['invoice_id'] ?? null,
                'schedule_number' => $scheduleNumber,
                'total_amount' => $totalAmount,
                'installments_count' => $installmentsCount,
                'status' => 'active',
                'notes' => $data['notes'] ?? null,
                'created_by' => $employee ? (int) $employee->id : null,
            ]);

            for ($i = 1; $i <= $installmentsCount; $i++) {
                $amount = $installmentAmount;
                if ($i === $installmentsCount) {
                    $amount = bcadd($amount, $remainder, 2);
                }

                $dueDate = date('Y-m-d', strtotime($startDate . ' +' . ($i * $intervalDays) . ' days'));

                $db->insert('supplier_payment_schedule_items', [
                    'schedule_id' => $scheduleId,
                    'installment_number' => $i,
                    'due_date' => $dueDate,
                    'amount' => $amount,
                    'payment_method' => $data['payment_method'] ?? 'cash',
                    'status' => 'upcoming',
                ]);
            }

            $db->commit();

            EventBus::dispatch('supplier_schedule.created', [
                'schedule_id' => $scheduleId,
                'supplier_id' => (int) $data['supplier_id'],
            ]);

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

    public static function recordPayment(int $scheduleItemId, string $paidAmount, ?string $paidDate = null): array
    {
        $db = App::getInstance()->db();

        $item = $db->selectOne("SELECT * FROM supplier_payment_schedule_items WHERE id = ?", [$scheduleItemId]);
        if (!$item) {
            return ['success' => false, 'error' => 'القسط غير موجود'];
        }

        $db->beginTransaction();
        try {
            $db->update('supplier_payment_schedule_items', [
                'paid_amount' => $paidAmount,
                'paid_date' => $paidDate ?? date('Y-m-d'),
                'status' => 'paid',
            ], 'id = ?', [$scheduleItemId]);

            $remaining = $db->selectOne(
                "SELECT COUNT(*) as cnt FROM supplier_payment_schedule_items WHERE schedule_id = ? AND status != 'paid'",
                [(int) $item['schedule_id']]
            );

            if ((int) ($remaining['cnt'] ?? 1) === 0) {
                $db->update('supplier_payment_schedules', ['status' => 'completed'], 'id = ?', [(int) $item['schedule_id']]);
            }

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

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

        return $db->select(
            "SELECT si.*, s.schedule_number, sp.name_ar as supplier_name
             FROM supplier_payment_schedule_items si
             JOIN supplier_payment_schedules s ON s.id = si.schedule_id
             JOIN suppliers sp ON sp.id = s.supplier_id
             WHERE si.status IN ('upcoming','due') AND si.due_date < CURDATE()
             ORDER BY si.due_date ASC"
        );
    }
}
