<?php

it('adds dynamic_images_vehicle_type column for legacy selfserve wash session task schemas', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain("'selfserve_wash_session_tasks'");
    expect($bootstrapContent)->toContain("'dynamic_images_vehicle_type'");
    expect($bootstrapContent)->toContain('ALTER TABLE selfserve_wash_session_tasks ADD COLUMN dynamic_images_vehicle_type INT NULL AFTER buttons');
});

it('widens self-serve task descriptions for generated workbook instructions', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain('description TEXT NULL');
    expect($bootstrapContent)->toContain('ensureColumnDataType(');
    expect($bootstrapContent)->toContain("['text', 'mediumtext', 'longtext']");
    expect($bootstrapContent)->toContain('ALTER TABLE department_selfserve_tasks MODIFY COLUMN description TEXT NULL AFTER task');
    expect($bootstrapContent)->toContain('ALTER TABLE selfserve_wash_session_tasks MODIFY COLUMN description TEXT NULL AFTER task_text');
});

it('alters legacy bounded description columns to text', function (): void {
    $hadDb = array_key_exists('db', $GLOBALS);
    $previousDb = $GLOBALS['db'] ?? null;

    try {
        foreach (['varchar', 'tinytext'] as $legacyType) {
            $fakeDb = new class ($legacyType) {
                public array $queries = [];

                public function __construct(private readonly string $dataType)
                {
                }

                public function escape_string(string $value): string
                {
                    return addslashes($value);
                }

                public function getDatabase(): string
                {
                    return 'test_db';
                }

                public function query(string $sql): object|bool
                {
                    $this->queries[] = $sql;
                    if (str_contains($sql, 'information_schema.COLUMNS')) {
                        return new class ($this->dataType) {
                            public function __construct(private readonly string $dataType)
                            {
                            }

                            public function fetch_assoc(): array
                            {
                                return ['DATA_TYPE' => $this->dataType];
                            }
                        };
                    }

                    return true;
                }
            };
            $GLOBALS['db'] = $fakeDb;

            \classes\selfserve_schema_bootstrap::ensureColumnDataType(
                'selfserve_wash_session_tasks',
                'description',
                ['text', 'mediumtext', 'longtext'],
                'ALTER TABLE selfserve_wash_session_tasks MODIFY COLUMN description TEXT NULL AFTER task_text'
            );

            expect($fakeDb->queries)->toContain('ALTER TABLE selfserve_wash_session_tasks MODIFY COLUMN description TEXT NULL AFTER task_text');
        }

        $textDb = new class {
            public array $queries = [];

            public function escape_string(string $value): string
            {
                return addslashes($value);
            }

            public function getDatabase(): string
            {
                return 'test_db';
            }

            public function query(string $sql): object|bool
            {
                $this->queries[] = $sql;
                if (str_contains($sql, 'information_schema.COLUMNS')) {
                    return new class {
                        public function fetch_assoc(): array
                        {
                            return ['DATA_TYPE' => 'text'];
                        }
                    };
                }

                return true;
            }
        };
        $GLOBALS['db'] = $textDb;

        \classes\selfserve_schema_bootstrap::ensureColumnDataType(
            'selfserve_wash_session_tasks',
            'description',
            ['text', 'mediumtext', 'longtext'],
            'ALTER TABLE selfserve_wash_session_tasks MODIFY COLUMN description TEXT NULL AFTER task_text'
        );

        expect(implode("\n", $textDb->queries))->not->toContain('ALTER TABLE selfserve_wash_session_tasks MODIFY COLUMN description TEXT NULL AFTER task_text');
    } finally {
        if ($hadDb) {
            $GLOBALS['db'] = $previousDb;
        } else {
            unset($GLOBALS['db']);
        }
    }
});

it('adds wash_started_at column for legacy selfserve wash session schemas', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain("'selfserve_wash_sessions'");
    expect($bootstrapContent)->toContain("'wash_started_at'");
    expect($bootstrapContent)->toContain('ALTER TABLE selfserve_wash_sessions ADD COLUMN wash_started_at DATETIME NULL AFTER machine_start_triggered_at');
});

it('adds reporting indexes for completed self-serve wash session counts', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));
    $apiSchemaContent = file_get_contents(app_path('tests/Support/Api/ApiSchemaBootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse()
        ->and($apiSchemaContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain('idx_selfserve_wash_sessions_department_completed')
        ->and($bootstrapContent)->toContain('ALTER TABLE selfserve_wash_sessions ADD INDEX idx_selfserve_wash_sessions_department_completed (department_id, completed_at)')
        ->and($bootstrapContent)->toContain('idx_selfserve_wash_sessions_order')
        ->and($bootstrapContent)->toContain('ALTER TABLE selfserve_wash_sessions ADD INDEX idx_selfserve_wash_sessions_order (order_id)')
        ->and($bootstrapContent)->toContain('public static function ensureIndex');
    expect($apiSchemaContent)->toContain('idx_selfserve_wash_sessions_department_completed')
        ->and($apiSchemaContent)->toContain('idx_selfserve_wash_sessions_order');
});

it('adds lane-level self-serve enablement for existing department lanes', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain("'department_lanes'");
    expect($bootstrapContent)->toContain("'selfserve_enabled'");
    expect($bootstrapContent)->toContain('ALTER TABLE department_lanes ADD COLUMN selfserve_enabled TINYINT(1) NOT NULL DEFAULT 1 AFTER machine_type_id');
});

it('creates canvas-only self-serve studio layout storage', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain('CREATE TABLE IF NOT EXISTS department_selfserve_studio_layouts');
    expect($bootstrapContent)->toContain('layout_json JSON NOT NULL');
    expect($bootstrapContent)->toContain('idx_department_selfserve_studio_layouts_department_user');
});

it('uses mysql-safe identifiers for self-serve studio virtual hardware storage', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain('CREATE TABLE IF NOT EXISTS department_selfserve_studio_virtual_hardware');
    expect($bootstrapContent)->toContain('UNIQUE KEY uniq_selfserve_vhw_department');
    expect($bootstrapContent)->toContain('INDEX idx_selfserve_vhw_dept_updated');
    expect($bootstrapContent)->not->toContain('idx_department_selfserve_studio_virtual_hardware_department_updated');

    preg_match_all('/\b(?:UNIQUE\s+KEY|INDEX)\s+([a-zA-Z0-9_]+)/', $bootstrapContent, $matches);
    foreach ($matches[1] as $identifier) {
        expect(strlen($identifier))->toBeLessThanOrEqual(64);
    }
});

it('creates self-serve studio path confirmation storage', function (): void {
    $bootstrapContent = file_get_contents(app_path('classes/selfserve_schema_bootstrap.php'));

    expect($bootstrapContent)->not->toBeFalse();
    expect($bootstrapContent)->toContain('CREATE TABLE IF NOT EXISTS department_selfserve_path_confirmations');
    expect($bootstrapContent)->toContain('path_signature VARCHAR(128) NOT NULL');
    expect($bootstrapContent)->toContain('result_signature VARCHAR(128) NOT NULL');
    expect($bootstrapContent)->toContain('idx_selfserve_path_conf_signature');
});
