<?php

declare(strict_types=1);

namespace Tests\Feature\Pwa;

use App\Models\Company;
use App\Models\Credit;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
use PHPUnit\Framework\Attributes\Test;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

/**
 * #97 — Endurecimiento: la regla exists de credit_id en StorePaymentRequest debe
 * estar scoped por company_id, de modo que un crédito de OTRA empresa falle como
 * error de validación (sin confirmar su existencia) en vez de pasar la validación.
 * También verifica que los endpoints de escritura llevan throttle:pwa-write.
 */
class PaymentRequestTenantScopeTest extends TestCase
{
    use DatabaseTransactions;

    private function companyWithCollector(): array
    {
        Role::firstOrCreate(['name' => 'collector', 'guard_name' => 'web']);
        $plan = Plan::factory()->create(['has_pwa_access' => true]);
        $company = Company::factory()->create();
        Subscription::factory()->active()->create([
            'company_id' => $company->id,
            'plan_id' => $plan->id,
            'ends_at' => now()->addYear(),
        ]);
        $collector = User::factory()->create(['company_id' => $company->id]);
        $collector->assignRole('collector');

        return [$company, $collector->fresh()];
    }

    #[Test]
    public function a_credit_from_another_company_fails_credit_id_validation(): void
    {
        [, $collectorA] = $this->companyWithCollector();
        [$companyB] = $this->companyWithCollector();

        // Crédito de la empresa B; el cobrador A intenta pagarlo.
        $foreignCredit = Credit::factory()->create([
            'company_id' => $companyB->id,
            'status' => Credit::STATUS_ACTIVE,
        ]);

        Sanctum::actingAs($collectorA);

        $this->postJson('/api/pwa/payments', [
            'credit_id' => $foreignCredit->id,
            'amount' => 1000,
            'payment_date' => today()->toDateString(),
            'payment_method' => 'cash',
            'idempotency_key' => (string) Str::uuid(),
        ])
            ->assertStatus(422)
            ->assertJsonValidationErrors(['credit_id']);
    }

    #[Test]
    public function write_endpoints_carry_pwa_write_throttle(): void
    {
        $routesWithThrottle = [
            'POST api/pwa/visits',
            'POST api/pwa/expenses',
            'POST api/pwa/approvals/{id}/approve',
            'POST api/pwa/approvals/{id}/reject',
            'POST api/pwa/partners/{id}/transaction',
            'PUT api/pwa/credits/reorder',
            'PUT api/pwa/clients/{id}',
            'POST api/pwa/payments/{id}/void',
        ];

        foreach ($routesWithThrottle as $signature) {
            [$method, $uri] = explode(' ', $signature, 2);
            $route = collect(Route::getRoutes()->getRoutes())
                ->first(fn ($r) => $r->uri() === $uri && in_array($method, $r->methods(), true));

            $this->assertNotNull($route, "Ruta no encontrada: {$signature}");
            $this->assertContains(
                'throttle:pwa-write',
                $route->gatherMiddleware(),
                "La ruta {$signature} debe llevar throttle:pwa-write.",
            );
        }
    }
}
