<?php

declare(strict_types=1);

namespace Tests\Unit\Services\Project;

use App\Http\Controllers\Api\ProjectController;
use App\Services\Project\ProjectService;
use ReflectionMethod;
use Tests\TestCase;

/**
 * Гарантирует, что переключение `is_active` всегда сопровождается записью `paused_at`:
 *   - is_active = false → paused_at := NOW()
 *   - is_active = true  → paused_at := null
 *
 * Без этого SupplierSnapshotGuard для bulk-paused проектов начнёт считать их
 * "защищёнными навсегда" (paused_at NULL trait), и удаление никогда не разблокируется.
 *
 * Тест читает исходник методов и проверяет наличие явной записи `paused_at` рядом
 * с записью `is_active`. Это структурный smoke — поведенческие тесты (через БД)
 * пишутся отдельно (Task 14 final regression).
 *
 * Spec: docs/superpowers/plans/2026-05-26-supplier-snapshot-guard.md (Task 11).
 */
class PausedAtWriteSideTest extends TestCase
{
    public function test_project_service_bulk_pause_resume_writes_paused_at(): void
    {
        $body = $this->methodBody(ProjectService::class, 'bulkPauseResume');

        $this->assertStringContainsString('paused_at', $body,
            'bulkPauseResume должен явно обновлять paused_at вместе с is_active');
        $this->assertStringContainsString('is_active', $body);
    }

    public function test_project_controller_toggle_active_writes_paused_at(): void
    {
        $body = $this->methodBody(ProjectController::class, 'toggleActive');

        $this->assertStringContainsString('paused_at', $body,
            'toggleActive должен явно обновлять paused_at вместе с is_active');
        $this->assertStringContainsString('is_active', $body);
    }

    public function test_bulk_delete_distinguishes_supplier_snapshot_lock_from_has_deals(): void
    {
        $body = $this->methodBody(ProjectService::class, 'bulkDelete');

        $this->assertStringContainsString('supplier_snapshot_locked', $body,
            'bulkDelete должен помечать пропущенные проекты reason="supplier_snapshot_locked" при guard-блоке');
        $this->assertStringContainsString('has_deals', $body);
    }

    private function methodBody(string $class, string $method): string
    {
        $rm = new ReflectionMethod($class, $method);
        $lines = file($rm->getFileName());
        $body = array_slice($lines, $rm->getStartLine() - 1, $rm->getEndLine() - $rm->getStartLine() + 1);

        return implode('', $body);
    }
}
