<?php

declare(strict_types=1);

namespace Tests\Support;

use PDO;

/**
 * Seeds a minimal org graph for integration tests.
 */
final class DatabaseSeeder
{
    public const PASSWORD = 'TestPass1!';

    public const ADMIN_USERNAME = 'test_admin';
    public const SUPERVISOR_USERNAME = 'test_supervisor';
    public const COACH_USERNAME = 'test_coach';

    public static function seed(PDO $pdo): FixtureIds
    {
        $now = time();
        $passwordHash = password_hash(self::PASSWORD, PASSWORD_DEFAULT);

        // Stable IDs so fixture metadata always matches seeded rows.
        $adminId = 'admin-test';
        $adminUserId = 'u-admin-test';
        $supervisorId = 'sv-test';
        $supervisorUserId = 'u-sv-test';
        $coachId = 'coach-test';
        $coachUserId = 'u-coach-test';
        $qnId = 'qn-test';
        $questionId = $qnId . '__q1';
        $optionId = 'opt-test-q1-yes';
        $freeTextQuestionId = $qnId . '__q2';
        $glassQuestionId = $qnId . '__q3';
        $glassSymptomKey = 'pain';
        $multiQuestionId = $qnId . '__q4';
        $multiOptionAId = 'opt-test-q4-a';
        $multiOptionBId = 'opt-test-q4-b';
        $draftQuestionnaireId = 'qn-draft-test';

        $pdo->prepare('INSERT INTO admin (adminID, username, location) VALUES (:id, :u, :loc)')
            ->execute([':id' => $adminId, ':u' => self::ADMIN_USERNAME, ':loc' => 'HQ']);
        $pdo->prepare(
            'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
             VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
        )->execute([
            ':uid' => $adminUserId,
            ':u' => self::ADMIN_USERNAME,
            ':h' => $passwordHash,
            ':role' => 'admin',
            ':eid' => $adminId,
            ':now' => $now,
        ]);

        $pdo->prepare('INSERT INTO supervisor (supervisorID, username, location) VALUES (:id, :u, :loc)')
            ->execute([':id' => $supervisorId, ':u' => self::SUPERVISOR_USERNAME, ':loc' => 'Region A']);
        $pdo->prepare(
            'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
             VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
        )->execute([
            ':uid' => $supervisorUserId,
            ':u' => self::SUPERVISOR_USERNAME,
            ':h' => $passwordHash,
            ':role' => 'supervisor',
            ':eid' => $supervisorId,
            ':now' => $now,
        ]);

        $pdo->prepare('INSERT INTO coach (coachID, supervisorID, username) VALUES (:id, :sid, :u)')
            ->execute([':id' => $coachId, ':sid' => $supervisorId, ':u' => self::COACH_USERNAME]);
        $pdo->prepare(
            'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
             VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
        )->execute([
            ':uid' => $coachUserId,
            ':u' => self::COACH_USERNAME,
            ':h' => $passwordHash,
            ':role' => 'coach',
            ':eid' => $coachId,
            ':now' => $now,
        ]);

        $pdo->prepare('INSERT INTO client (clientCode, coachID) VALUES (:cc, :cid)')
            ->execute([':cc' => 'CLIENT-TEST-001', ':cid' => $coachId]);

        $pdo->prepare(
            'INSERT INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson, categoryKey)
             VALUES (:id, :n, :v, :s, 1, 0, :cj, :ck)'
        )->execute([
            ':id' => $qnId,
            ':n' => 'Test questionnaire',
            ':v' => '1',
            ':s' => 'active',
            ':cj' => '{}',
            ':ck' => '',
        ]);
        $pdo->prepare('UPDATE questionnaire SET showPoints = 1 WHERE questionnaireID = :id')
            ->execute([':id' => $qnId]);

        $pdo->prepare(
            'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
             VALUES (:id, :qn, :txt, :type, 0, 1, :cfg)'
        )->execute([
            ':id' => $questionId,
            ':qn' => $qnId,
            ':txt' => 'Consent?',
            ':type' => 'single_choice_question',
            ':cfg' => json_encode(['questionKey' => 'consent_q'], JSON_THROW_ON_ERROR),
        ]);

        $pdo->prepare(
            'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
             VALUES (:id, :qid, :txt, 0, 0, :next)'
        )->execute([
            ':next' => '',
            ':id' => $optionId,
            ':qid' => $questionId,
            ':txt' => 'yes',
        ]);

        $pdo->prepare(
            'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
             VALUES (:id, :qn, :txt, :type, 1, 0, :cfg)'
        )->execute([
            ':id' => $freeTextQuestionId,
            ':qn' => $qnId,
            ':txt' => 'Notes',
            ':type' => 'free_text_question',
            ':cfg' => json_encode(['questionKey' => 'notes_q'], JSON_THROW_ON_ERROR),
        ]);

        $glassConfig = json_encode(
            ['questionKey' => 'symptoms_q', 'symptoms' => [$glassSymptomKey, 'fatigue']],
            JSON_THROW_ON_ERROR
        );
        $pdo->prepare(
            'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
             VALUES (:id, :qn, :txt, :type, 2, 0, :cfg)'
        )->execute([
            ':id' => $glassQuestionId,
            ':qn' => $qnId,
            ':txt' => 'Symptoms',
            ':type' => 'glass_scale_question',
            ':cfg' => $glassConfig,
        ]);

        require_once dirname(__DIR__, 2) . '/lib/settings.php';
        qdb_settings_save_on_pdo($pdo, qdb_settings_defaults());

        $pdo->prepare(
            'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
             VALUES (:id, :qn, :txt, :type, 3, 0, :cfg)'
        )->execute([
            ':id' => $multiQuestionId,
            ':qn' => $qnId,
            ':txt' => 'Pick several',
            ':type' => 'multi_check_box_question',
            ':cfg' => json_encode(['questionKey' => 'multi_q'], JSON_THROW_ON_ERROR),
        ]);
        $pdo->prepare(
            'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
             VALUES (:id, :qid, :txt, 1, 0, :next)'
        )->execute([':next' => '', ':id' => $multiOptionAId, ':qid' => $multiQuestionId, ':txt' => 'opt_a']);
        $pdo->prepare(
            'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
             VALUES (:id, :qid, :txt, 2, 1, :next)'
        )->execute([':next' => '', ':id' => $multiOptionBId, ':qid' => $multiQuestionId, ':txt' => 'opt_b']);
        qdb_upsert_source_translation($pdo, 'answer_option', $multiOptionAId, 'A');
        qdb_upsert_source_translation($pdo, 'answer_option', $multiOptionBId, 'B');

        $pdo->prepare(
            'INSERT INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson, categoryKey)
             VALUES (:id, :n, :v, :s, 2, 0, :cj, :ck)'
        )->execute([
            ':id' => $draftQuestionnaireId,
            ':n' => 'Draft only',
            ':v' => '1',
            ':s' => 'draft',
            ':cj' => '{}',
            ':ck' => '',
        ]);

        qdb_upsert_source_translation($pdo, 'answer_option', $optionId, 'Ja');

        return new FixtureIds(
            adminUserId: $adminUserId,
            supervisorUserId: $supervisorUserId,
            coachUserId: $coachUserId,
            coachId: $coachId,
            supervisorId: $supervisorId,
            questionnaireId: $qnId,
            questionId: $questionId,
            questionShortId: 'q1',
            optionId: $optionId,
            freeTextQuestionId: $freeTextQuestionId,
            freeTextShortId: 'q2',
            glassQuestionId: $glassQuestionId,
            glassShortId: 'q3',
            glassSymptomKey: $glassSymptomKey,
            multiCheckQuestionId: $multiQuestionId,
            multiCheckShortId: 'q4',
            draftQuestionnaireId: $draftQuestionnaireId,
            clientCode: 'CLIENT-TEST-001',
        );
    }
}

final class FixtureIds
{
    public function __construct(
        public readonly string $adminUserId,
        public readonly string $supervisorUserId,
        public readonly string $coachUserId,
        public readonly string $coachId,
        public readonly string $supervisorId,
        public readonly string $questionnaireId,
        public readonly string $questionId,
        public readonly string $questionShortId,
        public readonly string $optionId,
        public readonly string $freeTextQuestionId,
        public readonly string $freeTextShortId,
        public readonly string $glassQuestionId,
        public readonly string $glassShortId,
        public readonly string $glassSymptomKey,
        public readonly string $multiCheckQuestionId,
        public readonly string $multiCheckShortId,
        public readonly string $draftQuestionnaireId,
        public readonly string $clientCode,
    ) {
    }
}
