<?php

namespace Tests\Feature\Controllers;

use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Tests\TestCase;

class WebhookControllerTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        // Mock Oxapay configuration
        Config::set('services.oxapay.merchant_api_key', 'test_merchant_key');
        Config::set('services.oxapay.payout_api_key', 'test_payout_key');

        // Mock HTTP requests to prevent actual Telegram API calls
        Http::fake([
            'api.telegram.org/*' => Http::response(['ok' => true], 200),
        ]);

        // Allow any error, warning, and info logs for all tests
        Log::shouldReceive('error')
            ->zeroOrMoreTimes()
            ->withAnyArgs();
        Log::shouldReceive('warning')
            ->zeroOrMoreTimes()
            ->withAnyArgs();
        Log::shouldReceive('info')
            ->zeroOrMoreTimes()
            ->withAnyArgs();
    }

    /** @test */
    public function it_rejects_webhook_with_invalid_data_type(): void
    {
        $invalidData = [
            'type' => 'invalid_type',
            'email' => 'test@example.com',
        ];

        $response = $this->postJson('/webhook/oxapay', $invalidData);

        $response->assertStatus(400);
        $response->assertSee('Invalid data.type');
    }

    /** @test */
    public function it_rejects_webhook_with_missing_data_type(): void
    {
        $dataWithoutType = [
            'email' => 'test@example.com',
            'amount' => '100',
        ];

        $response = $this->postJson('/webhook/oxapay', $dataWithoutType);

        $response->assertStatus(400);
        $response->assertSee('Invalid data.type');
    }

    /** @test */
    public function it_rejects_webhook_with_no_data(): void
    {
        $response = $this->postJson('/webhook/oxapay', []);

        $response->assertStatus(400);
        $response->assertSee('Invalid data.type');
    }

    /** @test */
    public function it_rejects_webhook_with_invalid_hmac_signature(): void
    {
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '100',
            'currency' => 'USD',
            'track_id' => 'TRACK123',
            'order_id' => 'ORDER123',
            'date' => time(),
        ];

        json_encode($validData);
        $invalidHmac = 'invalid_hmac_signature';

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $invalidHmac,
        ]);

        $response->assertStatus(400);
        $response->assertSee('Invalid HMAC signature');
    }

    /** @test */
    public function it_processes_valid_invoice_webhook_successfully(): void
    {
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '99.99',
            'currency' => 'USD',
            'track_id' => 'TRACK123',
            'order_id' => 'ORDER123',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_merchant_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
        $response->assertSee('OK');
    }

    /** @test */
    public function it_processes_valid_payment_link_webhook_successfully(): void
    {
        $validData = [
            'type' => 'payment_link',
            'email' => 'test@example.com',
            'amount' => '149.99',
            'currency' => 'EUR',
            'track_id' => 'TRACK456',
            'order_id' => 'ORDER456',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_payout_key'; // payment_link uses payout key
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
        $response->assertSee('OK');
    }

    /** @test */
    public function it_processes_valid_payout_webhook_successfully(): void
    {
        $validData = [
            'type' => 'payout',
            'track_id' => 'PAYOUT123',
            'amount' => '500.00',
            'currency' => 'BTC',
            'network' => 'BTC',
            'address' => '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
            'tx_hash' => 'abc123def456',
            'description' => 'Payout to affiliate',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_payout_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
        $response->assertSee('OK');
    }

    /** @test */
    public function it_handles_webhook_processing_errors_gracefully(): void
    {
        // Use invalid date format to trigger error handling
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '99.99',
            'currency' => 'USD',
            'track_id' => 'TRACK123',
            'order_id' => 'ORDER123',
            'date' => 'invalid_timestamp', // This will cause an error
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_merchant_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        // Error logs are handled by the global mock in setUp()

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
        // Error is handled gracefully and logged
    }

    /** @test */
    public function it_logs_invoice_payment_details_correctly(): void
    {
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '99.99',
            'currency' => 'USD',
            'track_id' => 'TRACK123',
            'order_id' => 'ORDER123',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_merchant_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        // Telegram notification is handled by error logging in global mock

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
    }

    /** @test */
    public function it_logs_payout_details_correctly(): void
    {
        $validData = [
            'type' => 'payout',
            'track_id' => 'PAYOUT123',
            'amount' => '500.00',
            'currency' => 'BTC',
            'network' => 'BTC',
            'address' => '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
            'tx_hash' => 'abc123def456',
            'description' => 'Payout to affiliate',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_payout_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        // Telegram notification is handled by error logging in global mock

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
    }

    /** @test */
    public function it_logs_invalid_data_warnings(): void
    {
        $invalidData = [
            'type' => 'invalid_type',
            'email' => 'test@example.com',
        ];

        $response = $this->postJson('/webhook/oxapay', $invalidData);

        $response->assertStatus(400);
    }

    /** @test */
    public function it_logs_invalid_hmac_signature_warnings(): void
    {
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '100',
            'currency' => 'USD',
        ];
        json_encode($validData);
        $invalidHmac = 'invalid_hmac';

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $invalidHmac,
        ]);

        $response->assertStatus(400);
    }

    /** @test */
    public function it_handles_webhook_processing_exceptions(): void
    {
        $validData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '99.99',
            'currency' => 'USD',
            'track_id' => 'TRACK123',
            'order_id' => 'ORDER123',
            'date' => time(),
        ];

        $postData = json_encode($validData);
        $apiSecretKey = 'test_merchant_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        // Error logs are handled by the global mock in setUp()

        // Telegram notification for error is handled by error logging

        // Simulate an exception during processing by mocking a method that gets called
        $this->mock(Carbon::class)
            ->shouldReceive('createFromTimestamp')
            ->andThrow(new Exception('Date processing error'));

        $response = $this->postJson('/webhook/oxapay', $validData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
        // Exception is handled gracefully and logged
    }

    /** @test */
    public function it_uses_correct_api_key_based_on_webhook_type(): void
    {
        $invoiceData = [
            'type' => 'invoice',
            'email' => 'test@example.com',
            'amount' => '100',
            'currency' => 'USD',
            'date' => time(),
        ];

        $payoutData = [
            'type' => 'payout',
            'track_id' => 'PAYOUT123',
            'amount' => '500',
            'currency' => 'BTC',
            'date' => time(),
        ];

        // Test invoice uses merchant API key
        $invoicePostData = json_encode($invoiceData);
        $invoiceHmac = hash_hmac('sha512', $invoicePostData, 'test_merchant_key');

        $response = $this->postJson('/webhook/oxapay', $invoiceData, [
            'HMAC' => $invoiceHmac,
        ]);

        $response->assertStatus(200);

        // Test payout uses payout API key
        $payoutPostData = json_encode($payoutData);
        $payoutHmac = hash_hmac('sha512', $payoutPostData, 'test_payout_key');

        $response = $this->postJson('/webhook/oxapay', $payoutData, [
            'HMAC' => $payoutHmac,
        ]);

        $response->assertStatus(200);
    }

    /** @test */
    public function it_handles_missing_optional_fields_gracefully(): void
    {
        $minimalData = [
            'type' => 'invoice',
            'date' => time(),
        ];

        $postData = json_encode($minimalData);
        $apiSecretKey = 'test_merchant_key';
        $validHmac = hash_hmac('sha512', $postData, $apiSecretKey);

        // Telegram notification is handled by error logging in global mock

        $response = $this->postJson('/webhook/oxapay', $minimalData, [
            'HMAC' => $validHmac,
        ]);

        $response->assertStatus(200);
    }
}
