#!/usr/bin/env php
<?php
/**
 * ptyMysqlQuery
 *
 * MySQL 쿼리 실행 도구
 * 설정 파일: ~/.ptyMysqlConfig.ini
 *
 * Usage: ./ptyMysqlQuery "SQL" [options]
 */

namespace platyFramework;

require_once __DIR__ . '/ptyLibrary_PHP/cli/ptyCliOptionParser.php';
require_once __DIR__ . '/ptyLibrary_PHP/mysql/ptyMysqlConfig.php';

// 인자 파싱
$parsed = ptyCliOptionParser::parse($argv);
$positionalArgs = $parsed['positional'];
$options = $parsed['options'];
$mysqlSection = isset($options['mysql']) ? $options['mysql'] : 'default';
$verbose = isset($options['verbose']);
$showTable = isset($options['table']);
$showJson = isset($options['json']);
$showDump = isset($options['dump']);
$showCsv = isset($options['csv']);
$showMarkdown = isset($options['markdown']);

// ============================================================
// 1. --help: 최우선 처리
// ============================================================
if (isset($options['help'])) {
    echo "사용법: {$argv[0]} [\"SQL\"] [옵션]\n";
    echo "\n";
    echo "MySQL 쿼리를 실행하고 결과를 출력합니다.\n";
    echo "SQL 인자가 없으면 stdin에서 읽습니다 (Ctrl+D로 완료).\n";
    echo "\n";
    echo "옵션:\n";
    echo "  --mysql=섹션명      INI 파일 섹션 (기본값: default)\n";
    echo "  --database=DB명     데이터베이스 지정 (미지정시 INI 설정 사용)\n";
    echo "  --table             테이블 형태로 출력 (기본값: key:value 형태)\n";
    echo "  --json              JSON 형태로 출력\n";
    echo "  --dump              INSERT INTO SQL 형태로 출력\n";
    echo "  --csv               CSV 형태로 출력\n";
    echo "  --markdown          Markdown 테이블 형태로 출력\n";
    echo "  --verbose           상세 로그 출력\n";
    echo "  --edit              설정 파일을 에디터로 열기\n";
    echo "  --help              도움말 출력\n";
    echo "\n";
    echo "예시:\n";
    echo "  {$argv[0]} \"SELECT * FROM users LIMIT 10\"\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --table\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --json\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --dump\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --csv\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --markdown\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --mysql=production\n";
    echo "  {$argv[0]} \"SELECT * FROM users\" --database=mydb\n";
    echo "  {$argv[0]} \"SHOW TABLES\"\n";
    echo "  {$argv[0]} \"DESCRIBE users\"\n";
    echo "\n";
    echo "입력 방법:\n";
    echo "  {$argv[0]} --mysql=production                     # stdin에서 입력 (Ctrl+D로 완료)\n";
    echo "  {$argv[0]} < query.sql                            # 파일에서 입력 (리다이렉션)\n";
    echo "  cat query.sql | {$argv[0]}                        # 파일에서 입력 (파이프)\n";
    echo "  {$argv[0]} \"\$(pbpaste)\"                           # 클립보드에서 입력 (macOS)\n";
    echo "  {$argv[0]} \"\$(xclip -o)\"                          # 클립보드에서 입력 (Linux)\n";
    echo "\n";
    echo "설정 파일: ~/.ptyMysqlConfig.ini\n";
    echo ptyMysqlConfig::getConfigExample() . "\n";
    exit(0);
}

// ============================================================
// 2. --edit: 설정 파일 편집
// ============================================================
if (isset($options['edit'])) {
    $editor = getenv('EDITOR') ? getenv('EDITOR') : 'vi';
    $configFile = getenv('HOME') . '/.ptyMysqlConfig.ini';
    passthru("$editor " . escapeshellarg($configFile));
    exit(0);
}

// ============================================================
// 3. SQL 입력: 인자 또는 stdin
// ============================================================
if (count($positionalArgs) < 1) {
    // stdin에서 읽기
    if (posix_isatty(STDIN)) {
        fwrite(STDERR, "SQL을 입력하세요 (Ctrl+D로 완료):\n");
    }
    $sql = file_get_contents('php://stdin');
    $sql = trim($sql);
    if (empty($sql)) {
        echo "Error: SQL 쿼리가 필요합니다.\n";
        echo "도움말: {$argv[0]} --help\n";
        exit(1);
    }
} else {
    $sql = $positionalArgs[0];
}

// ANSI 색상 코드
$RED = "\033[1;31m";
$GREEN = "\033[1;32m";
$YELLOW = "\033[1;33m";
$CYAN = "\033[1;36m";
$MAGENTA = "\033[1;35m";
$RESET = "\033[0m";

// 한글 포함 문자열 너비 계산
function getDisplayWidth($str) {
    $width = 0;
    $len = mb_strlen($str, 'UTF-8');
    for ($i = 0; $i < $len; $i++) {
        $char = mb_substr($str, $i, 1, 'UTF-8');
        $ord = mb_ord($char, 'UTF-8');
        // CJK 문자 범위 (한글, 한자, 일본어 등)
        if ($ord >= 0x1100 && $ord <= 0x11FF ||   // 한글 자모
            $ord >= 0x3000 && $ord <= 0x9FFF ||   // CJK
            $ord >= 0xAC00 && $ord <= 0xD7AF ||   // 한글 음절
            $ord >= 0xF900 && $ord <= 0xFAFF ||   // CJK 호환
            $ord >= 0xFF00 && $ord <= 0xFFEF) {   // 전각 문자
            $width += 2;
        } else {
            $width += 1;
        }
    }
    return $width;
}

// mb_ord 폴리필 (PHP 7.2 미만)
if (!function_exists('mb_ord')) {
    function mb_ord($char, $encoding = 'UTF-8') {
        $result = unpack('N', mb_convert_encoding($char, 'UCS-4BE', $encoding));
        return $result[1];
    }
}

// 문자열 패딩 (한글 지원)
function padString($str, $width, $align = 'left') {
    $displayWidth = getDisplayWidth($str);
    $padding = $width - $displayWidth;
    if ($padding <= 0) {
        return $str;
    }
    if ($align === 'right') {
        return str_repeat(' ', $padding) . $str;
    }
    return $str . str_repeat(' ', $padding);
}

// 값 포맷팅 (NULL, 긴 문자열 처리)
function formatValue($value, $maxLen = 100) {
    if ($value === null) {
        return 'NULL';
    }
    $value = str_replace(array("\r\n", "\r", "\n"), ' ', $value);
    if (mb_strlen($value) > $maxLen) {
        return mb_substr($value, 0, $maxLen - 3) . '...';
    }
    return $value;
}

// 테이블 형태 출력 함수
function printAsTable($rows, $columns, $colors) {
    extract($colors);

    $widths = array();
    foreach ($columns as $col) {
        $widths[$col] = getDisplayWidth($col);
    }

    foreach ($rows as $row) {
        foreach ($columns as $col) {
            $value = formatValue($row[$col], 50);
            $w = getDisplayWidth($value);
            if ($w > $widths[$col]) {
                $widths[$col] = $w;
            }
        }
    }

    // 최대 너비 제한
    foreach ($widths as $col => $w) {
        if ($w > 50) {
            $widths[$col] = 50;
        }
    }

    // 헤더 출력
    $headerLine = "";
    $separatorLine = "";
    foreach ($columns as $col) {
        $headerLine .= padString($col, $widths[$col]) . "  ";
        $separatorLine .= str_repeat("-", $widths[$col]) . "  ";
    }

    echo "{$CYAN}" . rtrim($headerLine) . "{$RESET}\n";
    echo rtrim($separatorLine) . "\n";

    // 데이터 출력
    foreach ($rows as $row) {
        $line = "";
        foreach ($columns as $col) {
            $value = formatValue($row[$col], 50);
            if ($row[$col] === null) {
                $line .= "{$MAGENTA}" . padString($value, $widths[$col]) . "{$RESET}  ";
            } else {
                $line .= padString($value, $widths[$col]) . "  ";
            }
        }
        echo rtrim($line) . "\n";
    }
}

// CSV 형태 출력 함수
function printAsCsv($rows, $columns) {
    // 헤더
    $header = array();
    foreach ($columns as $col) {
        $header[] = '"' . str_replace('"', '""', $col) . '"';
    }
    echo implode(',', $header) . "\n";

    // 데이터
    foreach ($rows as $row) {
        $values = array();
        foreach ($columns as $col) {
            $value = $row[$col];
            if ($value === null) {
                $values[] = '';
            } else {
                $values[] = '"' . str_replace('"', '""', $value) . '"';
            }
        }
        echo implode(',', $values) . "\n";
    }
}

// Markdown 테이블 형태 출력 함수
function printAsMarkdown($rows, $columns) {
    // 헤더
    echo '| ' . implode(' | ', $columns) . " |\n";

    // 구분선
    $separators = array();
    foreach ($columns as $col) {
        $separators[] = '---';
    }
    echo '| ' . implode(' | ', $separators) . " |\n";

    // 데이터
    foreach ($rows as $row) {
        $values = array();
        foreach ($columns as $col) {
            $value = $row[$col];
            if ($value === null) {
                $values[] = 'NULL';
            } else {
                // 파이프와 줄바꿈 이스케이프
                $value = str_replace(array('|', "\n", "\r"), array('\\|', ' ', ''), $value);
                $values[] = $value;
            }
        }
        echo '| ' . implode(' | ', $values) . " |\n";
    }
}

// INSERT INTO SQL 형태 출력 함수
function printAsDump($rows, $columns, $tableName, $connection) {
    foreach ($rows as $row) {
        $values = array();
        foreach ($columns as $col) {
            $value = $row[$col];
            if ($value === null) {
                $values[] = 'NULL';
            } else {
                $values[] = "'" . mysqli_real_escape_string($connection, $value) . "'";
            }
        }

        $sql = "INSERT INTO `" . $tableName . "` (`" . implode("`, `", $columns) . "`) VALUES (" . implode(", ", $values) . ");";
        echo $sql . "\n";
    }
}

// SQL에서 테이블명 추출
function extractTableName($sql) {
    // SELECT ... FROM table_name 패턴
    if (preg_match('/\bFROM\s+[`"]?(\w+)[`"]?/i', $sql, $matches)) {
        return $matches[1];
    }
    return 'table_name';
}

// key:value 형태 출력 함수
function printAsKeyValue($rows, $columns, $colors) {
    extract($colors);

    // 컬럼명 최대 너비 계산
    $maxKeyWidth = 0;
    foreach ($columns as $col) {
        $w = getDisplayWidth($col);
        if ($w > $maxKeyWidth) {
            $maxKeyWidth = $w;
        }
    }

    $rowNum = 0;
    foreach ($rows as $row) {
        $rowNum++;

        // 행 구분선
        if ($rowNum > 1) {
            echo "\n";
        }

        // 행 번호 (여러 행일 때만)
        if (count($rows) > 1) {
            echo "{$YELLOW}--- [$rowNum] ---{$RESET}\n";
        }

        foreach ($columns as $col) {
            $value = $row[$col];
            $formattedValue = formatValue($value);

            $paddedKey = padString($col, $maxKeyWidth);

            if ($value === null) {
                echo "{$CYAN}{$paddedKey}{$RESET}: {$MAGENTA}{$formattedValue}{$RESET}\n";
            } else {
                echo "{$CYAN}{$paddedKey}{$RESET}: {$formattedValue}\n";
            }
        }
    }
}

try {
    // MySQL 설정 로드
    $config = ptyMysqlConfig::load($mysqlSection);

    // --database 옵션이 있으면 우선 사용
    $database = isset($options['database']) ? $options['database'] : $config['database'];

    // 연결
    $connection = mysqli_connect(
        $config['host'],
        $config['username'],
        $config['password'],
        $database
    );

    if (!$connection) {
        throw new \Exception("MySQL 연결 실패: " . mysqli_connect_error());
    }

    if (!empty($config['charset'])) {
        mysqli_set_charset($connection, $config['charset']);
    }

    // 데이터 출력 모드가 아닐 때만 정보 표시
    $dataOnlyMode = $showJson || $showDump || $showCsv || $showMarkdown;

    if (!$dataOnlyMode) {
        echo "{$CYAN}Section:{$RESET} {$mysqlSection}";
        echo "  {$CYAN}Host:{$RESET} {$config['host']}";
        echo "  {$CYAN}Database:{$RESET} " . ($database ? $database : '(none)') . "\n";
        echo "{$CYAN}SQL:{$RESET} $sql\n";
        echo str_repeat("-", 60) . "\n";
    }

    // 쿼리 실행
    $startTime = microtime(true);
    $result = mysqli_query($connection, $sql);
    $endTime = microtime(true);
    $elapsed = ($endTime - $startTime) * 1000; // ms

    if ($result === false) {
        throw new \Exception("쿼리 실행 실패: " . mysqli_error($connection));
    }

    // SELECT 등 결과셋이 있는 경우
    if ($result instanceof \mysqli_result) {
        $rows = array();
        while ($row = mysqli_fetch_assoc($result)) {
            $rows[] = $row;
        }

        $rowCount = count($rows);

        if ($rowCount === 0) {
            echo "{$YELLOW}결과 없음{$RESET}\n";
        } else {
            $columns = array_keys($rows[0]);
            $colors = array(
                'RED' => $RED,
                'GREEN' => $GREEN,
                'YELLOW' => $YELLOW,
                'CYAN' => $CYAN,
                'MAGENTA' => $MAGENTA,
                'RESET' => $RESET
            );

            if ($showJson) {
                // JSON 출력 (아래에서 처리)
            } elseif ($showDump) {
                $tableName = extractTableName($sql);
                printAsDump($rows, $columns, $tableName, $connection);
            } elseif ($showCsv) {
                printAsCsv($rows, $columns);
            } elseif ($showMarkdown) {
                printAsMarkdown($rows, $columns);
            } elseif ($showTable) {
                printAsTable($rows, $columns, $colors);
            } else {
                printAsKeyValue($rows, $columns, $colors);
            }
        }

        mysqli_free_result($result);

        // JSON 출력
        if ($showJson) {
            $output = array(
                'rows' => $rows,
                'count' => $rowCount,
                'elapsed_ms' => round($elapsed, 2)
            );
            echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
        } elseif ($showDump || $showCsv || $showMarkdown) {
            // dump/csv/markdown 모드는 데이터만 출력
        } else {
            echo "\n";
            echo "{$GREEN}$rowCount 행{$RESET}";

            // 실행 시간 출력
            if ($elapsed < 1000) {
                $elapsedStr = sprintf("%.2f ms", $elapsed);
            } else {
                $elapsedStr = sprintf("%.2f sec", $elapsed / 1000);
            }
            echo " ({$CYAN}$elapsedStr{$RESET})\n";
        }
    } else {
        // INSERT, UPDATE, DELETE 등
        $affectedRows = mysqli_affected_rows($connection);

        if ($showJson) {
            $output = array(
                'affected_rows' => $affectedRows,
                'elapsed_ms' => round($elapsed, 2)
            );
            echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
        } else {
            echo "{$GREEN}$affectedRows 행 영향 받음{$RESET}";

            // 실행 시간 출력
            if ($elapsed < 1000) {
                $elapsedStr = sprintf("%.2f ms", $elapsed);
            } else {
                $elapsedStr = sprintf("%.2f sec", $elapsed / 1000);
            }
            echo " ({$CYAN}$elapsedStr{$RESET})\n";
        }
    }

    mysqli_close($connection);

} catch (\Exception $e) {
    echo "{$RED}Error:{$RESET} " . $e->getMessage() . "\n";
    exit(1);
}
