<?php

namespace Tests\Feature;

use App\Enums\UserRole;
use App\Models\Business;
use App\Models\Setting;
use App\Models\User;
use App\Services\Settings\PaymentSettingsService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PaymentSettingsTest extends TestCase
{
    use RefreshDatabase;

    public function test_business_owner_can_save_payment_settings_with_encrypted_credentials(): void
    {
        [$owner, $business] = $this->ownerWithBusiness();

        $this->actingAs($owner)
            ->post(route('admin.settings.payments.update'), $this->payload())
            ->assertRedirect(route('admin.settings.payments'))
            ->assertSessionHas('status', 'Payment settings saved securely.');

        $service = app(PaymentSettingsService::class);
        $settings = $service->get($business, revealSecrets: true);

        $this->assertSame('PKR', data_get($settings, 'general.default_currency'));
        $this->assertFalse(data_get($settings, 'cash.enabled'));
        $this->assertTrue(data_get($settings, 'stripe.enabled'));
        $this->assertSame('sk_test_booklio_secret', data_get($settings, 'stripe.secret_key'));
        $this->assertSame('paypal-client-secret-demo', data_get($settings, 'paypal.client_secret'));

        $secretRow = Setting::query()
            ->where('business_id', $business->id)
            ->where('group', PaymentSettingsService::GROUP)
            ->where('name', 'stripe.secret_key')
            ->firstOrFail();

        $this->assertTrue($secretRow->is_encrypted);
        $this->assertStringNotContainsString('sk_test_booklio_secret', json_encode($secretRow->value));
    }

    public function test_payment_settings_page_never_prints_saved_secret_values(): void
    {
        [$owner, $business] = $this->ownerWithBusiness();
        app(PaymentSettingsService::class)->save($business, $this->payload());

        $this->actingAs($owner)
            ->get(route('admin.settings.payments'))
            ->assertOk()
            ->assertSee('Configured - leave blank to keep current value')
            ->assertDontSee('sk_test_booklio_secret')
            ->assertDontSee('paypal-client-secret-demo');
    }

    public function test_gateway_test_button_is_backend_ready_placeholder(): void
    {
        [$owner] = $this->ownerWithBusiness();

        $this->actingAs($owner)
            ->post(route('admin.settings.payments.test', 'stripe'), $this->payload())
            ->assertRedirect(route('admin.settings.payments'))
            ->assertSessionHas('status', 'Stripe connection check is ready for backend API wiring. No external request was sent.');
    }

    public function test_staff_cannot_update_payment_settings(): void
    {
        [$owner, $business] = $this->ownerWithBusiness();
        $staff = User::factory()->create(['role' => UserRole::Staff->value]);
        $business->users()->attach($staff->id, [
            'role' => UserRole::Staff->value,
            'status' => 'active',
            'joined_at' => now(),
        ]);

        $this->actingAs($staff)
            ->post(route('admin.settings.payments.update'), $this->payload())
            ->assertForbidden();

        $this->assertDatabaseMissing('settings', [
            'business_id' => $business->id,
            'group' => PaymentSettingsService::GROUP,
            'name' => 'stripe.secret_key',
        ]);
    }

    private function ownerWithBusiness(): array
    {
        $owner = User::factory()->create([
            'role' => UserRole::BusinessOwner->value,
        ]);
        $business = Business::factory()->create([
            'owner_id' => $owner->id,
            'status' => 'active',
            'currency' => 'USD',
        ]);

        return [$owner, $business];
    }

    private function payload(): array
    {
        return [
            'general' => [
                'default_currency' => 'PKR',
                'currency_position' => 'before',
                'enable_tax' => '1',
                'tax_name' => 'GST',
                'tax_percentage' => '16',
                'invoice_due_days' => '10',
                'payment_success_message' => 'Payment received. Thank you.',
                'payment_failed_message' => 'Payment failed. Please try again.',
            ],
            'cash' => [
                'display_name' => 'Counter Cash',
                'instructions' => 'Pay at reception.',
            ],
            'bank' => [
                'enabled' => '1',
                'bank_name' => 'Booklio Bank',
                'account_holder_name' => 'Glow Beauty Salon',
                'account_number' => 'PK00BOOKLIO123456789',
                'swift_bic' => 'BOOKPKKA',
                'branch_name' => 'Main Branch',
                'payment_instructions' => 'Use invoice number as reference.',
                'upload_payment_proof' => '1',
            ],
            'stripe' => [
                'enabled' => '1',
                'mode' => 'test',
                'publishable_key' => 'pk_test_51BooklioDemo',
                'secret_key' => 'sk_test_booklio_secret',
                'webhook_secret' => 'whsec_booklio_demo',
                'currency' => 'PKR',
                'payment_description' => 'Booklio invoice payment',
            ],
            'paypal' => [
                'enabled' => '1',
                'mode' => 'sandbox',
                'client_id' => 'paypal-client-id-demo',
                'client_secret' => 'paypal-client-secret-demo',
                'webhook_id' => 'WH-BOOKLIO-DEMO',
                'currency' => 'PKR',
            ],
        ];
    }
}
