<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Credit;

/**
 * Sincroniza la tabla collector_credit_order cuando cambia el estado de un crédito.
 *
 * Responsabilidad única: mantener la ruta de cobro del collector coherente
 * con los estados activos de los créditos.
 *
 * Flujo de llamada:
 *   CreditStatusSyncService::perform()
 *     → CreditStatusSynced::dispatch()
 *       → CollectorSyncListener::handle()
 *         → CollectorSyncService::handleStatusChange()
 *
 * Reglas de negocio:
 * - Activo → Cerrado : eliminar la fila (crédito sale de la ruta del cobrador)
 * - Cerrado → Activo : agregar al final de la ruta
 * - Activo → Activo  : sin cambios (e.g. active → delayed, ambos en ACTIVE_STATUSES)
 * - Cerrado → Cerrado: sin cambios
 *
 * Delega en CollectorCreditOrderService (misma fuente que CreditObserver, ver
 * insertRespectingHistory()/removeAndReindex()) para que los cambios de estado
 * AUTOMÁTICOS (reconciliación nocturna, SyncCreditStatusJob) tengan la misma
 * paridad que los síncronos: guardan la posición histórica del cliente y
 * reindexan sort_order — antes usaba delete()/appendCredit() crudos, dejando
 * huecos en sort_order y perdiendo el slot histórico (#129).
 */
class CollectorSyncService
{
    public function __construct(
        private readonly CollectorCreditOrderService $orderService,
    ) {}

    public function handleStatusChange(Credit $credit, string $oldStatus, string $newStatus): void
    {
        if (! $credit->collector_user_id) {
            return;
        }

        $wasActive = in_array($oldStatus, Credit::ACTIVE_STATUSES, true);
        $isNowActive = in_array($newStatus, Credit::ACTIVE_STATUSES, true);

        if ($wasActive && ! $isNowActive) {
            // Crédito sale de la ruta: guarda posición histórica + elimina + reindexa.
            $this->orderService->removeAndReindex(
                $credit->company_id,
                $credit->collector_user_id,
                $credit->id,
                $credit->client_id,
            );

            return;
        }

        if (! $wasActive && $isNowActive) {
            // Crédito entra a la ruta: respeta el slot histórico del cliente.
            $this->orderService->insertRespectingHistory(
                $credit->company_id,
                $credit->collector_user_id,
                $credit->id,
                $credit->client_id,
            );
        }
    }
}
