<?php

namespace Tests\Feature;

use App\Domain\Training\Models\TrainingGroup;
use App\Models\User;
use Tests\TestCase;

/**
 * The subscription column and the POS grid are Blade, so a wrong variable name
 * or a renamed method is a 500 at request time and nothing earlier catches it.
 *
 * Runs against a restored Postgres tenant; skips on the default SQLite suite,
 * where the schema does not exist:
 *
 *   DB_CONNECTION=pgsql DB_DATABASE=oc_sport_test ./vendor/bin/phpunit --filter GroupRosterAndPosRenderTest
 */
class GroupRosterAndPosRenderTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        if (config('database.default') !== 'pgsql') {
            $this->markTestSkipped('Needs a restored Postgres tenant; see the class comment.');
        }
    }

    private function anAdmin(): User
    {
        $user = User::query()->whereHas('roles', fn ($q) => $q->where('name', 'admin'))->first()
            ?? User::query()->first();

        $this->assertNotNull($user, 'The restored tenant has no users to act as.');

        return $user;
    }

    public function test_the_group_roster_renders_and_names_the_subscription_column(): void
    {
        $group = TrainingGroup::withoutGlobalScopes()
            ->whereHas('enrollments', fn ($q) => $q->where('status', 'active'))
            ->first();

        $this->assertNotNull($group, 'No group with active enrollments in the restored tenant.');

        $response = $this->actingAs($this->anAdmin())->get(route('groups.show', $group));

        $response->assertOk();
        $response->assertSee('الاشتراك', escape: false);
        $response->assertDontSee('دليل ألوان الدفع', escape: false);
    }

    public function test_a_card_paid_inside_a_combined_invoice_shows_on_the_roster(): void
    {
        // The money for the federation card is routinely taken on the same
        // invoice as a kit or a bag, and typed as a free-text line. The column
        // has to allocate that invoice's payment across its lines and show the
        // card's share — production participants 219 (2,500 of 8,000,
        // non-member) and 97 (2,000 of 6,000, member) are both that case.
        $billing = app(\App\Domain\Financial\Services\ParticipantBillingService::class);

        foreach ([219 => 800000, 97 => 600000] as $participantId => $expectedTotal) {
            $participant = \App\Domain\Participant\Models\Participant::withoutGlobalScopes()->find($participantId);

            if (! $participant) {
                continue;
            }

            $facts = $billing->bundledProductForParticipants(
                [$participantId],
                2,
                'قيد اشتراك فريق اتحاد الكرة',
                null,
                true,
            )[$participantId] ?? null;

            $this->assertNotNull($facts, "Participant {$participantId} paid toward the card on a shared invoice.");
            $this->assertGreaterThan(0, $facts['paid'], 'The card gets its share of the invoice payment.');
            $this->assertTrue($facts['from_text'], 'The line was typed by hand, which is the whole point.');

            $enrollment = \App\Domain\Training\Models\Enrollment::withoutGlobalScopes()
                ->where('participant_id', $participantId)->where('status', 'active')->first();

            if (! $enrollment) {
                continue;
            }

            $group = \App\Domain\Training\Models\TrainingGroup::withoutGlobalScopes()->find($enrollment->training_group_id);
            $html = $this->actingAs($this->anAdmin())->get(route('groups.show', $group))->getContent();

            $paid = number_format($facts['paid'] / 100, 0);
            $total = number_format($expectedTotal / 100, 0);

            $this->assertStringContainsString($paid, $html);
            $this->assertStringContainsString($total, $html, 'The total is the price for this member tier, not the instalment.');
            $this->assertStringContainsString('أقساط', $html, 'Being paid off is not the same as never bought.');
        }
    }

    public function test_the_pos_terminal_renders_with_engine_prices(): void
    {
        $cashier = User::query()->get()->first(fn (User $u) => $u->can('pos.sell'));

        if (! $cashier) {
            $this->markTestSkipped('No user in the restored tenant may sell.');
        }

        $this->actingAs($cashier)->get(route('pos.terminal'))->assertOk();
    }
}
