<?php

declare(strict_types=1);

namespace App\Services\Alerts;

use App\Models\AlertDelivery;
use App\Models\AlertDestination;
use App\Support\Alerts\AlertDestinationLastTestStatus;
use App\Support\Alerts\AlertDestinationLastTestStatusEnum;
use Carbon\CarbonImmutable;

class AlertDestinationLastTestResolver
{
    /**
     * Resolve the derived "last test" status for a given destination.
     *
     * Uses the most recent `alert_deliveries` row with `event_type = 'alerts.test'`,
     * ordered by `created_at` desc then `id` desc (deterministic tie-breaking).
     */
    public function resolve(AlertDestination $destination): AlertDestinationLastTestStatus
    {
        $delivery = AlertDelivery::query()
            ->where('workspace_id', (int) $destination->workspace_id)
            ->where('alert_destination_id', (int) $destination->getKey())
            ->where('event_type', AlertDelivery::EVENT_TYPE_TEST)
            ->orderByDesc('created_at')
            ->orderByDesc('id')
            ->first();

        if ($delivery === null) {
            return AlertDestinationLastTestStatus::never();
        }

        $status = $this->mapStatus((string) $delivery->status);
        $timestamp = $this->mapTimestamp($delivery, $status);

        return new AlertDestinationLastTestStatus(
            status: $status,
            timestamp: $timestamp,
            deliveryId: (int) $delivery->getKey(),
        );
    }

    private function mapStatus(string $deliveryStatus): AlertDestinationLastTestStatusEnum
    {
        return match ($deliveryStatus) {
            AlertDelivery::STATUS_SENT => AlertDestinationLastTestStatusEnum::Sent,
            AlertDelivery::STATUS_FAILED => AlertDestinationLastTestStatusEnum::Failed,
            AlertDelivery::STATUS_QUEUED,
            AlertDelivery::STATUS_DEFERRED => AlertDestinationLastTestStatusEnum::Pending,
            default => AlertDestinationLastTestStatusEnum::Failed,
        };
    }

    private function mapTimestamp(AlertDelivery $delivery, AlertDestinationLastTestStatusEnum $status): ?CarbonImmutable
    {
        return match ($status) {
            AlertDestinationLastTestStatusEnum::Sent => $delivery->sent_at
                ? CarbonImmutable::instance($delivery->sent_at)
                : null,
            AlertDestinationLastTestStatusEnum::Failed => $delivery->updated_at
                ? CarbonImmutable::instance($delivery->updated_at)
                : null,
            AlertDestinationLastTestStatusEnum::Pending => $delivery->send_after
                ? CarbonImmutable::instance($delivery->send_after)
                : ($delivery->created_at ? CarbonImmutable::instance($delivery->created_at) : null),
            AlertDestinationLastTestStatusEnum::Never => null,
        };
    }
}
