"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.IGNORE_PATTERNS = exports.FastAPIProjectType = void 0;
exports.getFastAPIVersionBucket = getFastAPIVersionBucket;
exports.getFastAPIVersion = getFastAPIVersion;
exports.getFastAPIProjectType = getFastAPIProjectType;
exports.getFastAPIProjectTypeName = getFastAPIProjectTypeName;
exports.findFastAPIAppFile = findFastAPIAppFile;
const semver_1 = require("semver");
const fast_glob_1 = __importDefault(require("fast-glob"));
const ui_1 = require("../../ui");
const fs = __importStar(require("node:fs"));
const path = __importStar(require("node:path"));
var FastAPIProjectType;
(function (FastAPIProjectType) {
    FastAPIProjectType["STANDARD"] = "standard";
    FastAPIProjectType["ROUTER"] = "router";
    FastAPIProjectType["FULLSTACK"] = "fullstack";
})(FastAPIProjectType || (exports.FastAPIProjectType = FastAPIProjectType = {}));
exports.IGNORE_PATTERNS = [
    '**/node_modules/**',
    '**/dist/**',
    '**/build/**',
    '**/venv/**',
    '**/.venv/**',
    '**/env/**',
    '**/.env/**',
    '**/__pycache__/**',
    '**/migrations/**',
];
/**
 * Get FastAPI version bucket for analytics
 */
function getFastAPIVersionBucket(version) {
    if (!version) {
        return 'none';
    }
    try {
        const minVer = (0, semver_1.minVersion)(version);
        if (!minVer) {
            return 'invalid';
        }
        const majorVersion = (0, semver_1.major)(minVer);
        // FastAPI 0.x is still the common version range
        if (majorVersion === 0) {
            return '0.x';
        }
        return `${majorVersion}.x`;
    }
    catch {
        return 'unknown';
    }
}
/**
 * Extract FastAPI version from requirements files or pyproject.toml
 */
async function getFastAPIVersion(options) {
    const { installDir } = options;
    // Check requirements files
    const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'], {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
    });
    for (const reqFile of requirementsFiles) {
        try {
            const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');
            // Try to extract version from requirements.txt format (fastapi==0.109.0 or fastapi>=0.100)
            const requirementsMatch = content.match(/[Ff]ast[Aa][Pp][Ii][=<>~!]+([0-9]+\.[0-9]+(?:\.[0-9]+)?)/);
            if (requirementsMatch) {
                return requirementsMatch[1];
            }
            // Try to extract from pyproject.toml format
            const pyprojectMatch = content.match(/[Ff]ast[Aa][Pp][Ii]["\s]*[=<>~!]+\s*["']?([0-9]+\.[0-9]+(?:\.[0-9]+)?)/);
            if (pyprojectMatch) {
                return pyprojectMatch[1];
            }
        }
        catch {
            // Skip files that can't be read
            continue;
        }
    }
    return undefined;
}
/**
 * Check if app uses FastAPI APIRouter
 */
async function hasAPIRouter({ installDir, }) {
    const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
    });
    for (const pyFile of pyFiles) {
        try {
            const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
            if (content.includes('APIRouter(') ||
                content.includes('include_router(') ||
                content.includes('from fastapi import APIRouter')) {
                return true;
            }
        }
        catch {
            continue;
        }
    }
    return false;
}
/**
 * Check if app uses Jinja2 templates (fullstack pattern)
 */
async function hasTemplates({ installDir, }) {
    // Check for Jinja2Templates usage in Python files
    const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
    });
    for (const pyFile of pyFiles) {
        try {
            const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
            if (content.includes('Jinja2Templates') ||
                content.includes('from fastapi.templating import')) {
                return true;
            }
        }
        catch {
            continue;
        }
    }
    // Check for templates directory
    const templateDirs = await (0, fast_glob_1.default)(['**/templates'], {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
        onlyDirectories: true,
    });
    return templateDirs.length > 0;
}
/**
 * Detect FastAPI project type
 */
async function getFastAPIProjectType(options) {
    const { installDir } = options;
    // Check for fullstack pattern (templates)
    if (await hasTemplates({ installDir })) {
        (0, ui_1.getUI)().setDetectedFramework('FastAPI fullstack with templates');
        return FastAPIProjectType.FULLSTACK;
    }
    // Check for APIRouter (modular structure)
    if (await hasAPIRouter({ installDir })) {
        (0, ui_1.getUI)().setDetectedFramework('FastAPI with APIRouter');
        return FastAPIProjectType.ROUTER;
    }
    // Default to standard FastAPI
    (0, ui_1.getUI)().setDetectedFramework('FastAPI');
    return FastAPIProjectType.STANDARD;
}
/**
 * Get human-readable name for FastAPI project type
 */
function getFastAPIProjectTypeName(projectType) {
    switch (projectType) {
        case FastAPIProjectType.STANDARD:
            return 'Standard FastAPI';
        case FastAPIProjectType.ROUTER:
            return 'FastAPI with APIRouter';
        case FastAPIProjectType.FULLSTACK:
            return 'FastAPI Fullstack';
    }
}
/**
 * Find the main FastAPI app file
 */
async function findFastAPIAppFile(options) {
    const { installDir } = options;
    // Common FastAPI app file patterns
    const commonPatterns = [
        '**/main.py',
        '**/app.py',
        '**/application.py',
        '**/api.py',
        '**/__init__.py',
    ];
    const appFiles = await (0, fast_glob_1.default)(commonPatterns, {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
    });
    // Look for files with FastAPI() instantiation
    for (const appFile of appFiles) {
        try {
            const content = fs.readFileSync(path.join(installDir, appFile), 'utf-8');
            // Check for FastAPI app instantiation
            if (content.includes('FastAPI(') ||
                content.includes('from fastapi import FastAPI')) {
                return appFile;
            }
        }
        catch {
            continue;
        }
    }
    // If no file with FastAPI() found, check all Python files
    const allPyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
        cwd: installDir,
        ignore: exports.IGNORE_PATTERNS,
    });
    for (const pyFile of allPyFiles) {
        try {
            const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
            if (content.includes('FastAPI(')) {
                return pyFile;
            }
        }
        catch {
            continue;
        }
    }
    // Return first common pattern file if exists
    if (appFiles.length > 0) {
        return appFiles[0];
    }
    return undefined;
}
