<?php

declare(strict_types=1);

use App\Services\Install\EnvChecker;
use App\Services\Install\LockGuard;
use App\Services\Install\PasswordPolicy;

uses(Tests\TestCase::class);

beforeEach(function () {
    // 각 테스트마다 lock 파일을 청소
    $lock = app(LockGuard::class);
    if (is_file($lock->path())) {
        @unlink($lock->path());
    }
});

it('EnvChecker 가 현재 환경을 점검한다', function () {
    $report = (new EnvChecker())->run();

    expect($report)->toHaveKeys(['passed', 'checks']);
    expect($report['checks'])->toBeArray()->not->toBeEmpty();
});

it('PasswordPolicy 가 약한 비밀번호를 거부한다', function () {
    $policy = new PasswordPolicy();

    expect($policy->evaluate('short')['passed'])->toBeFalse();
    expect($policy->evaluate('password12345')['passed'])->toBeFalse();
    expect($policy->evaluate('Wdot!Secure#2026$Pass')['passed'])->toBeTrue();
});

it('LockGuard HMAC 검증이 정상 동작한다', function () {
    config(['app.key' => 'base64:'.base64_encode(random_bytes(32))]);

    $lock = app(LockGuard::class);

    expect($lock->exists())->toBeFalse();
    expect($lock->verify())->toBeFalse();

    $path = $lock->create([
        'installer_ip'   => '127.0.0.1',
        'super_admin_id' => 'test-uuid-12345',
        'user_agent'     => 'PHPUnit',
    ]);

    expect(is_file($path))->toBeTrue();
    expect($lock->verify())->toBeTrue();

    // 위조 시도 — JSON 의 IP 만 바꾸면 HMAC 불일치
    $data = json_decode((string) file_get_contents($path), true);
    $data['installer_ip'] = '999.999.999.999';
    file_put_contents($path, json_encode($data));

    expect($lock->verify())->toBeFalse();
});

it('GET /install 은 lock 없으면 200 을 돌려준다', function () {
    $resp = $this->get('/install');
    $resp->assertStatus(200);
});

it('POST /install/stage1/check 가 JSON 보고서를 반환한다', function () {
    $resp = $this->postJson('/install/stage1/check');
    $resp->assertStatus(200)->assertJsonStructure(['stage', 'passed', 'checks']);
});

it('install.lock 이 있으면 /install/* 가 403 으로 차단된다', function () {
    config(['app.key' => 'base64:'.base64_encode(random_bytes(32))]);
    app(LockGuard::class)->create([
        'installer_ip'   => '127.0.0.1',
        'super_admin_id' => 'already-installed',
    ]);

    $this->get('/install')->assertStatus(403);
    $this->postJson('/install/stage1/check')->assertStatus(403);
});

it('Stage 게이트 — stage2 는 stage1 통과 후에만 허용', function () {
    $resp = $this->postJson('/install/stage2/db', [
        'host' => '127.0.0.1', 'port' => 3306,
        'database' => 'wdot', 'username' => 'wdot', 'password' => '',
    ]);
    $resp->assertStatus(409); // stage1_required
});
