/**
 * Version Checker Utility
 * Reads local version from __init__.py and checks PyPI for latest published version
 */

const fs = require('fs').promises;
const path = require('path');
const https = require('https');

/**
 * Read version from __init__.py
 * @param {string} projectRoot - Path to project root directory
 * @returns {Promise<string|null>} Version string or null if not found
 */
async function readLocalVersion(projectRoot) {
    try {
        const initPath = path.join(projectRoot, 'src', 'mcp_memory_service', '__init__.py');
        const content = await fs.readFile(initPath, 'utf8');

        // Match __version__ = "X.Y.Z" or __version__ = 'X.Y.Z'
        const versionMatch = content.match(/__version__\s*=\s*['"]([\d.]+)['"]/);

        if (versionMatch && versionMatch[1]) {
            return versionMatch[1];
        }

        return null;
    } catch (error) {
        return null;
    }
}

/**
 * Fetch latest version from PyPI
 * @param {string} packageName - Name of the package on PyPI
 * @param {number} timeout - Request timeout in ms (default: 2000)
 * @returns {Promise<string|null>} Latest version string or null if error
 */
async function fetchPyPIVersion(packageName = 'mcp-memory-service', timeout = 2000) {
    return new Promise((resolve) => {
        const url = `https://pypi.org/pypi/${packageName}/json`;

        const timeoutId = setTimeout(() => {
            resolve(null);
        }, timeout);

        https.get(url, {
            headers: {
                'User-Agent': 'mcp-memory-service-hook'
            }
        }, (res) => {
            let data = '';

            res.on('data', (chunk) => {
                data += chunk;
            });

            res.on('end', () => {
                clearTimeout(timeoutId);
                try {
                    const parsed = JSON.parse(data);
                    const latestVersion = parsed?.info?.version;
                    resolve(latestVersion || null);
                } catch (error) {
                    resolve(null);
                }
            });
        }).on('error', () => {
            clearTimeout(timeoutId);
            resolve(null);
        });
    });
}

/**
 * Compare two semantic versions
 * @param {string} local - Local version (e.g., "8.39.1")
 * @param {string} pypi - PyPI version (e.g., "8.38.0")
 * @returns {number} -1 if local < pypi, 0 if equal, 1 if local > pypi
 */
function compareVersions(local, pypi) {
    const localParts = local.split('.').map(Number);
    const pypiParts = pypi.split('.').map(Number);

    for (let i = 0; i < Math.max(localParts.length, pypiParts.length); i++) {
        const localPart = localParts[i] || 0;
        const pypiPart = pypiParts[i] || 0;

        if (localPart < pypiPart) return -1;
        if (localPart > pypiPart) return 1;
    }

    return 0;
}

/**
 * Get version information with local and PyPI comparison
 * @param {string} projectRoot - Path to project root directory
 * @param {Object} options - Options for version check
 * @param {boolean} options.checkPyPI - Whether to check PyPI (default: true)
 * @param {number} options.timeout - PyPI request timeout in ms (default: 2000)
 * @returns {Promise<Object>} Version info object
 */
async function getVersionInfo(projectRoot, options = {}) {
    const { checkPyPI = true, timeout = 2000 } = options;

    const localVersion = await readLocalVersion(projectRoot);

    const result = {
        local: localVersion,
        pypi: null,
        comparison: null,
        status: 'unknown'
    };

    if (!localVersion) {
        result.status = 'error';
        return result;
    }

    if (checkPyPI) {
        const pypiVersion = await fetchPyPIVersion('mcp-memory-service', timeout);
        result.pypi = pypiVersion;

        if (pypiVersion) {
            const comparison = compareVersions(localVersion, pypiVersion);
            result.comparison = comparison;

            if (comparison === 0) {
                result.status = 'published';
            } else if (comparison > 0) {
                result.status = 'development';
            } else {
                result.status = 'outdated';
            }
        } else {
            result.status = 'local-only';
        }
    } else {
        result.status = 'local-only';
    }

    return result;
}

/**
 * Format version information for display
 * @param {Object} versionInfo - Version info from getVersionInfo()
 * @param {Object} colors - Console color codes
 * @returns {string} Formatted version string
 */
function formatVersionDisplay(versionInfo, colors) {
    const { local, pypi, status } = versionInfo;

    if (!local) {
        return `${colors.CYAN}📦 Version${colors.RESET} ${colors.DIM}→${colors.RESET} ${colors.GRAY}Unable to read version${colors.RESET}`;
    }

    let statusLabel = '';
    let pypiDisplay = '';

    switch (status) {
        case 'published':
            statusLabel = `${colors.GRAY}(published)${colors.RESET}`;
            break;
        case 'development':
            statusLabel = `${colors.GRAY}(local)${colors.RESET}`;
            pypiDisplay = pypi ? ` ${colors.DIM}•${colors.RESET} PyPI: ${colors.YELLOW}${pypi}${colors.RESET}` : '';
            break;
        case 'outdated':
            statusLabel = `${colors.RED}(outdated)${colors.RESET}`;
            pypiDisplay = pypi ? ` ${colors.DIM}•${colors.RESET} PyPI: ${colors.GREEN}${pypi}${colors.RESET}` : '';
            break;
        case 'local-only':
            statusLabel = `${colors.GRAY}(local)${colors.RESET}`;
            break;
        default:
            statusLabel = `${colors.GRAY}(unknown)${colors.RESET}`;
    }

    return `${colors.CYAN}📦 Version${colors.RESET} ${colors.DIM}→${colors.RESET} ${colors.BRIGHT}${local}${colors.RESET} ${statusLabel}${pypiDisplay}`;
}

module.exports = {
    readLocalVersion,
    fetchPyPIVersion,
    compareVersions,
    getVersionInfo,
    formatVersionDisplay
};
