<?php

declare(strict_types=1);

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use Tests\Support\DatabaseSeeder;
use Tests\Support\TestFilesystem;

final class ProgramSessionsTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        TestFilesystem::resetUploads();
        if (defined('QDB_PATH') && is_file(QDB_PATH)) {
            @unlink(QDB_PATH);
        }
        [$pdo, $tmpDb, $lockFp] = qdb_open(true);
        DatabaseSeeder::seed($pdo);
        require_once dirname(__DIR__, 2) . '/lib/program_sessions.php';

        $sessionID = bin2hex(random_bytes(8));
        $now = time();
        $pdo->prepare(
            'INSERT INTO program_session
             (sessionID, name, description, sessionNumber, orderIndex, isActive, createdAt, updatedAt)
             VALUES (:id, :name, "", 1, 0, 1, :t, :t)'
        )->execute([':id' => $sessionID, ':name' => 'S1', ':t' => $now]);
        qdb_sync_program_session_questionnaires($pdo, $sessionID, [
            ['questionnaireID' => 'qn-test', 'orderIndex' => 0],
        ]);
        qdb_save($tmpDb, $lockFp);
    }

    public function testResolveOrderFromSessionNumber(): void
    {
        [$pdo] = qdb_open(true);
        require_once dirname(__DIR__, 2) . '/lib/program_sessions.php';

        $order = qdb_program_session_resolve_order($pdo, ['sessionNumber' => 3]);
        $this->assertSame(3, $order['sessionNumber']);
        $this->assertSame(2, $order['orderIndex']);
    }

    public function testResolveOrderFromOrderIndexLegacy(): void
    {
        [$pdo] = qdb_open(true);
        require_once dirname(__DIR__, 2) . '/lib/program_sessions.php';

        $order = qdb_program_session_resolve_order($pdo, ['orderIndex' => 4]);
        $this->assertSame(5, $order['sessionNumber']);
        $this->assertSame(4, $order['orderIndex']);
    }

    public function testResolveOrderDefaultsToNextSession(): void
    {
        [$pdo] = qdb_open(true);
        require_once dirname(__DIR__, 2) . '/lib/program_sessions.php';

        $order = qdb_program_session_resolve_order($pdo, []);
        $this->assertSame(2, $order['sessionNumber']);
        $this->assertSame(1, $order['orderIndex']);
    }

    public function testAdvanceCycleWhenSessionComplete(): void
    {
        [$pdo, $tmpDb, $lockFp] = qdb_open(true);
        require_once dirname(__DIR__, 2) . '/lib/program_sessions.php';
        qdb_program_session_settings_save($pdo, ['autoRepeatSessions' => true]);

        $now = time();
        $pdo->prepare(
            "INSERT INTO completed_questionnaire
             (clientCode, questionnaireID, status, completedAt, sumPoints)
             VALUES ('CLIENT-TEST-001', 'qn-test', 'completed', :t, 0)"
        )->execute([':t' => $now]);

        $this->assertTrue(qdb_maybe_advance_program_cycle($pdo, 'CLIENT-TEST-001'));
        $cycle = qdb_client_program_cycle_get($pdo, 'CLIENT-TEST-001');
        $this->assertSame(2, $cycle['cycleNumber']);
        qdb_save($tmpDb, $lockFp);
    }
}
