#!/usr/bin/env php
<?php
/**
 * ptyElasticgetIndexs
 *
 * Elasticsearch 인덱스 정보를 조회하는 도구
 * 설정 파일: ~/.ptyElasticConfig.ini
 */

// 설정 파일 경로
$configFile = getenv('HOME') . '/.ptyElasticConfig.ini';

// 설정 파일 확인
if (!file_exists($configFile)) {
    echo "Error: 설정 파일을 찾을 수 없습니다: $configFile\n";
    echo "\n설정 파일 예시:\n";
    echo "[elastic]\n";
    echo "host=https://localhost:9200\n";
    echo "user=elastic\n";
    echo "password=yourpassword\n";
    exit(1);
}

// 설정 파일 읽기
$config = parse_ini_file($configFile, true);

if (!isset($config['elastic'])) {
    echo "Error: 설정 파일에 [elastic] 섹션이 없습니다.\n";
    exit(1);
}

$elasticConfig = $config['elastic'];
$host = $elasticConfig['host'] ?? '';
$user = $elasticConfig['user'] ?? '';
$password = $elasticConfig['password'] ?? '';

if (empty($host)) {
    echo "Error: host 설정이 필요합니다.\n";
    exit(1);
}

// Elasticsearch API 호출
function callElasticAPI($url, $user, $password) {
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    if (!empty($user) && !empty($password)) {
        curl_setopt($ch, CURLOPT_USERPWD, "$user:$password");
    }

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
        $error = curl_error($ch);
        curl_close($ch);
        throw new Exception("cURL Error: $error");
    }

    curl_close($ch);

    if ($httpCode !== 200) {
        throw new Exception("HTTP Error: $httpCode - $response");
    }

    return $response;
}

// 타임스탬프 형식 변환
function formatTimestamp($timestamp) {
    // 밀리초 타임스탬프인 경우 (13자리 숫자)
    if (is_numeric($timestamp) && strlen($timestamp) >= 13) {
        $seconds = intval($timestamp / 1000);
        return date('Y-m-d H:i:s', $seconds);
    }
    // 초 타임스탬프인 경우 (10자리 숫자)
    if (is_numeric($timestamp) && strlen($timestamp) == 10) {
        return date('Y-m-d H:i:s', intval($timestamp));
    }
    // 이미 문자열 형식인 경우
    if (is_string($timestamp)) {
        return substr($timestamp, 0, 19);
    }
    return $timestamp;
}

// 인덱스의 마지막 문서 시간 조회
function getLastDocumentTime($host, $user, $password, $indexName) {
    try {
        $searchUrl = rtrim($host, '/') . '/' . urlencode($indexName) . '/_search';
        $searchBody = json_encode([
            'size' => 1,
            'sort' => [
                ['_index' => ['order' => 'desc']]
            ],
            'query' => ['match_all' => (object)[]]
        ]);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $searchUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $searchBody);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

        if (!empty($user) && !empty($password)) {
            curl_setopt($ch, CURLOPT_USERPWD, "$user:$password");
        }

        $response = curl_exec($ch);
        curl_close($ch);

        $data = json_decode($response, true);
        if (isset($data['hits']['hits'][0]['_source'])) {
            $source = $data['hits']['hits'][0]['_source'];
            // 일반적인 타임스탬프 필드 찾기
            foreach (['@timestamp', 'timestamp', 'created_at', 'updated_at', 'date', 'createdAt', 'updatedAt'] as $field) {
                if (isset($source[$field])) {
                    return formatTimestamp($source[$field]);
                }
            }
        }
        return 'N/A';
    } catch (Exception $e) {
        return 'N/A';
    }
}

try {
    // 인덱스 정보 조회 (_cat/indices API 사용)
    $url = rtrim($host, '/') . '/_cat/indices?v&format=json&bytes=mb&h=index,status,docs.count,store.size,health,pri,rep,creation.date.string';

    echo "Elasticsearch 인덱스 정보 조회 중...\n";
    echo "Host: $host\n";
    echo str_repeat("=", 80) . "\n\n";

    $response = callElasticAPI($url, $user, $password);
    $indices = json_decode($response, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception("JSON 파싱 오류: " . json_last_error_msg());
    }

    if (empty($indices)) {
        echo "인덱스가 없습니다.\n";
        exit(0);
    }

    // 결과 정렬 (인덱스 이름순)
    usort($indices, function($a, $b) {
        return strcmp($a['index'], $b['index']);
    });

    // 헤더 출력
    printf("%-40s %-10s %-12s %-12s %-10s %-10s %-20s %-20s\n",
        "INDEX", "STATUS", "DOCS.COUNT", "STORE.SIZE", "HEALTH", "PRI/REP", "CREATED", "LAST INDEXED");
    echo str_repeat("-", 165) . "\n";

    // 각 인덱스 정보 출력
    $totalDocs = 0;
    $totalSize = 0;

    foreach ($indices as $index) {
        $indexName = $index['index'] ?? 'N/A';
        $status = $index['status'] ?? 'N/A';
        $docsCount = $index['docs.count'] ?? '0';
        $storeSize = $index['store.size'] ?? '0';
        $health = $index['health'] ?? 'N/A';
        $pri = $index['pri'] ?? '0';
        $rep = $index['rep'] ?? '0';
        $creationDate = $index['creation.date.string'] ?? 'N/A';

        // 마지막 색인 시간 조회
        $lastIndexed = 'N/A';
        if ($docsCount !== '0' && is_numeric($docsCount)) {
            $lastIndexed = getLastDocumentTime($host, $user, $password, $indexName);
        }

        // 숫자 형식 정리
        $docsCount = is_numeric($docsCount) ? number_format($docsCount) : $docsCount;

        // 용량 형식 정리 (234mb -> 234 MB)
        $storeSizeFormatted = is_numeric($storeSize) ? number_format($storeSize, 2) . ' MB' : $storeSize;

        printf("%-40s %-10s %-12s %-12s %-10s %-10s %-20s %-20s\n",
            substr($indexName, 0, 40),
            $status,
            $docsCount,
            $storeSizeFormatted,
            $health,
            $pri . '/' . $rep,
            substr($creationDate, 0, 20),
            substr($lastIndexed, 0, 20)
        );

        // 총합 계산
        if (is_numeric($index['docs.count'] ?? null)) {
            $totalDocs += intval($index['docs.count']);
        }
        if (is_numeric($index['store.size'] ?? null)) {
            $totalSize += floatval($index['store.size']);
        }
    }

    // 요약 정보 출력
    echo str_repeat("=", 165) . "\n";
    printf("총 인덱스 수: %d\n", count($indices));
    printf("총 문서 수: %s\n", number_format($totalDocs));
    printf("총 용량: %.2f MB (%.2f GB)\n", $totalSize, $totalSize / 1024);

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