<?php

namespace Tests\Unit;

use App\Services\PaymentHealthReportService;
use Illuminate\Support\Facades\File;
use Tests\TestCase;

class PaymentHealthReportServiceTest extends TestCase
{
    public function test_summarize_date_classifies_failure_buckets(): void
    {
        $date = '2099-01-01';
        $this->writePaymentLog($date, [
            '[2099-01-01 10:00:00] production.INFO: Razorpay webhook: Payment captured {"order_id":101}',
            '[2099-01-01 10:01:00] production.WARNING: Razorpay webhook: Payment failed {"order_id":102,"error":"Payment was unsuccessful as you could not complete it in time.","failure_bucket":"gateway_timeout"}',
            '[2099-01-01 10:02:00] production.WARNING: Razorpay webhook: Payment failed {"order_id":103,"error":"Transaction failed due to insufficient funds.","failure_bucket":"customer_decline"}',
            '[2099-01-01 10:03:00] production.ERROR: Razorpay verify failed with stock error {"order_id":104,"error":"Order is no longer payable."}',
            '[2099-01-01 10:04:00] production.WARNING: Razorpay webhook: Order not found {"razorpay_order_id":"order_x"}',
            '[2099-01-01 10:05:00] production.WARNING: Razorpay verify: recovered non-payable state using captured payment {"order_id":105}',
        ]);

        $stats = (new PaymentHealthReportService())->summarizeDate($date);

        $this->assertSame(1, $stats['captured_events']);
        $this->assertSame(2, $stats['failed_events']);
        $this->assertSame(1, $stats['gateway_timeout_events']);
        $this->assertSame(1, $stats['customer_decline_events']);
        $this->assertSame(2, $stats['backend_state_race_events']);
        $this->assertSame(1, $stats['webhook_order_not_found_events']);
        $this->assertSame(3, $stats['backend_failure_events']);
    }

    public function test_hard_fail_does_not_count_failed_for_captured_order(): void
    {
        $date = '2099-01-02';
        $this->writePaymentLog($date, [
            '[2099-01-02 09:00:00] production.INFO: Razorpay webhook: Payment captured {"order_id":201}',
            '[2099-01-02 09:05:00] production.WARNING: Razorpay webhook: Payment failed {"order_id":201,"error":"Payment was unsuccessful as you could not complete it in time.","failure_bucket":"gateway_timeout"}',
        ]);

        $stats = (new PaymentHealthReportService())->summarizeDate($date);

        $this->assertSame(1, $stats['attempted_unique_orders']);
        $this->assertSame(0, $stats['hard_fail_unique_orders']);
        $this->assertSame(0.0, $stats['hard_fail_rate_pct']);
    }

    public function test_aggregate_includes_backend_failure_rate(): void
    {
        $service = new PaymentHealthReportService();
        $aggregate = $service->aggregate([
            [
                'log_exists' => true,
                'captured_events' => 2,
                'failed_events' => 1,
                'verify_stock_error_events' => 1,
                'backend_state_race_events' => 1,
                'gateway_timeout_events' => 1,
                'customer_decline_events' => 0,
                'webhook_order_not_found_events' => 1,
                'backend_failure_events' => 2,
                'already_paid_verification_skips' => 0,
                'recovered_non_payable_events' => 0,
                'attempted_unique_orders' => 4,
                'captured_unique_orders' => 2,
                'failed_unique_orders' => 1,
                'hard_fail_unique_orders' => 1,
            ],
        ]);

        $this->assertSame(2, $aggregate['backend_failure_events']);
        $this->assertSame(50.0, $aggregate['backend_failure_rate_pct']);
    }

    /**
     * @param array<int, string> $lines
     */
    private function writePaymentLog(string $date, array $lines): void
    {
        $dir = storage_path('logs/payments');
        File::ensureDirectoryExists($dir);
        File::put($dir . "/payment-{$date}.log", implode(PHP_EOL, $lines) . PHP_EOL);
    }
}
