<?php

namespace MintyPHP\Support;

use RuntimeException;

/**
 * Splits a SQL string into individual statements, respecting quoted strings,
 * backtick identifiers, and comments.
 *
 * DELIMITER directives are intentionally unsupported — module migrations must
 * use individual statement files or avoid stored procedures that need them.
 */
final class SqlStatementParser
{
    /**
     * @return list<string>
     *
     * @throws RuntimeException If a DELIMITER directive is encountered
     */
    public static function splitStatements(string $sql): array
    {
        if (preg_match('/^\s*DELIMITER\s+/mi', $sql) === 1) {
            throw new RuntimeException('DELIMITER directives are not supported in module migration SQL files.');
        }

        $statements = [];
        $buffer = '';
        $length = strlen($sql);
        $inSingleQuote = false;
        $inDoubleQuote = false;
        $inBacktick = false;
        $inLineComment = false;
        $inBlockComment = false;
        $escapeNext = false;

        for ($i = 0; $i < $length; $i++) {
            $char = $sql[$i];
            $next = $i + 1 < $length ? $sql[$i + 1] : '';

            if ($inLineComment) {
                $buffer .= $char;
                if ($char === "\n") {
                    $inLineComment = false;
                }
                continue;
            }

            if ($inBlockComment) {
                $buffer .= $char;
                if ($char === '*' && $next === '/') {
                    $buffer .= $next;
                    $i++;
                    $inBlockComment = false;
                }
                continue;
            }

            if (!$inSingleQuote && !$inDoubleQuote && !$inBacktick) {
                if ($char === '-' && $next === '-' && ($i + 2 >= $length || ctype_space($sql[$i + 2]))) {
                    $buffer .= $char . $next;
                    $i++;
                    $inLineComment = true;
                    continue;
                }
                if ($char === '#') {
                    $buffer .= $char;
                    $inLineComment = true;
                    continue;
                }
                if ($char === '/' && $next === '*') {
                    $buffer .= $char . $next;
                    $i++;
                    $inBlockComment = true;
                    continue;
                }
            }

            if ($escapeNext) {
                $buffer .= $char;
                $escapeNext = false;
                continue;
            }

            if (($inSingleQuote || $inDoubleQuote) && $char === '\\') {
                $buffer .= $char;
                $escapeNext = true;
                continue;
            }

            if (!$inDoubleQuote && !$inBacktick && $char === '\'') {
                $inSingleQuote = !$inSingleQuote;
                $buffer .= $char;
                continue;
            }

            if (!$inSingleQuote && !$inBacktick && $char === '"') {
                $inDoubleQuote = !$inDoubleQuote;
                $buffer .= $char;
                continue;
            }

            if (!$inSingleQuote && !$inDoubleQuote && $char === '`') {
                $inBacktick = !$inBacktick;
                $buffer .= $char;
                continue;
            }

            if (!$inSingleQuote && !$inDoubleQuote && !$inBacktick && $char === ';') {
                $statement = trim($buffer);
                if ($statement !== '') {
                    $statements[] = $statement;
                }
                $buffer = '';
                continue;
            }

            $buffer .= $char;
        }

        $tail = trim($buffer);
        if ($tail !== '') {
            $statements[] = $tail;
        }

        return $statements;
    }
}
