"use strict";
/**
 * Migration: Update UnisphereVisualTarget usage
 *
 * 1. Renames `target` property to `type` in visual target object literals
 *    (where value is 'body' or 'element')
 * 2. Converts string visual targets to { type: 'element', elementId: '<string>' }
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = update;
const devkit_1 = require("@nx/devkit");
const ts_morph_1 = require("ts-morph");
async function update(tree) {
    devkit_1.logger.info('🔄 Updating UnisphereVisualTarget usage...');
    const project = new ts_morph_1.Project({
        manipulationSettings: { quoteKind: ts_morph_1.QuoteKind.Single },
    });
    let updatedCount = 0;
    (0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
        if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx'))
            return;
        if (!filePath.includes('unisphere/'))
            return;
        const content = tree.read(filePath, 'utf-8');
        if (!content)
            return;
        if (!content.includes('target'))
            return;
        const sourceFile = project.createSourceFile(filePath, content, {
            overwrite: true,
        });
        let hasChanges = false;
        // Pass 1: Rename target → type in object literals where value is 'body' or 'element'
        // Only in visual target contexts (mountVisual args, visuals config, nested in target property)
        const allPropertyAssignments = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment);
        for (const prop of allPropertyAssignments) {
            if (prop.getName() !== 'target')
                continue;
            const initializer = prop.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
            if (!initializer)
                continue;
            const value = initializer.getLiteralValue();
            if (value !== 'body' && value !== 'element')
                continue;
            if (!isVisualTargetObjectContext(prop))
                continue;
            prop.getNameNode().replaceWithText('type');
            hasChanges = true;
        }
        // Pass 2: Convert string targets to objects in mountVisual calls and visuals config
        // Re-query after Pass 1 modifications
        const propertyAssignments = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAssignment);
        for (const prop of propertyAssignments) {
            if (prop.getName() !== 'target')
                continue;
            const initializer = prop.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
            if (!initializer)
                continue;
            const value = initializer.getLiteralValue();
            // Skip 'body' and 'element' - those were handled in Pass 1
            if (value === 'body' || value === 'element')
                continue;
            // Check if this is in a visual target context
            if (!isVisualTargetContext(prop))
                continue;
            // Transform string to { type: 'element', elementId: '<string>' }
            initializer.replaceWithText(`{ type: 'element', elementId: '${value}' }`);
            hasChanges = true;
        }
        if (hasChanges) {
            tree.write(filePath, sourceFile.getFullText());
            updatedCount++;
            devkit_1.logger.info(`  ✅ Updated ${filePath}`);
        }
    });
    if (updatedCount === 0) {
        devkit_1.logger.info('ℹ️ No UnisphereVisualTarget usages needed transformation');
    }
    else {
        await (0, devkit_1.formatFiles)(tree);
        devkit_1.logger.info(`✅ Updated UnisphereVisualTarget usage in ${updatedCount} file(s)`);
    }
}
/**
 * Checks if a `target` property with value 'body'/'element' is inside a UnisphereVisualTarget object.
 * The object itself (containing target: 'body') is the visual target value, so we check
 * whether it's nested inside a `target` property of a parent, a mountVisual call, or visuals array.
 */
function isVisualTargetObjectContext(prop) {
    const objLiteral = prop.getParent();
    if (!ts_morph_1.Node.isObjectLiteralExpression(objLiteral))
        return false;
    const objParent = objLiteral.getParent();
    // Context 1: Object is value of a `target` property in a parent object
    // e.g., mountVisual({ target: { target: 'body' } }) — inner object is the visual target
    if (ts_morph_1.Node.isPropertyAssignment(objParent) && objParent.getName() === 'target')
        return true;
    // Context 2: Object is inside a mountVisual() call directly
    // e.g., mountVisual({ target: 'body' }) — less common but possible
    if (ts_morph_1.Node.isCallExpression(objParent)) {
        const expr = objParent.getExpression();
        if (expr.getText().endsWith('mountVisual'))
            return true;
    }
    // Context 3: Object is inside a visuals array item's target property
    // e.g., visuals: [{ target: { target: 'body' } }]
    if (ts_morph_1.Node.isPropertyAssignment(objParent) && objParent.getName() === 'target') {
        const outerObj = objParent.getParent();
        if (ts_morph_1.Node.isObjectLiteralExpression(outerObj)) {
            const arrayParent = outerObj.getParent();
            if (ts_morph_1.Node.isArrayLiteralExpression(arrayParent)) {
                const arrayPropParent = arrayParent.getParent();
                if (ts_morph_1.Node.isPropertyAssignment(arrayPropParent) &&
                    arrayPropParent.getName() === 'visuals')
                    return true;
            }
        }
    }
    // Context 4: Object has sibling properties that indicate it's a visual target
    // (has elementId for 'element' type, or classNames/style for 'body' type)
    if (objLiteral.getProperty('elementId'))
        return true;
    if (objLiteral.getProperty('classNames'))
        return true;
    if (objLiteral.getProperty('style'))
        return true;
    return false;
}
/**
 * Checks if a `target` property with a string value is in a visual target context
 * (the string IS the visual target value, needing conversion to object).
 */
function isVisualTargetContext(prop) {
    const parent = prop.getParent();
    if (!ts_morph_1.Node.isObjectLiteralExpression(parent))
        return false;
    // Context 1: Inside mountVisual() call argument
    // e.g., super.mountVisual({ type: 'popup', target: 'someId', settings: {} })
    const grandparent = parent.getParent();
    if (ts_morph_1.Node.isCallExpression(grandparent)) {
        const expr = grandparent.getExpression();
        if (expr.getText().endsWith('mountVisual'))
            return true;
    }
    // Context 2: Inside a visuals array item
    // e.g., visuals: [{ target: 'someId', ... }]
    if (ts_morph_1.Node.isArrayLiteralExpression(grandparent)) {
        const arrayParent = grandparent.getParent();
        if (ts_morph_1.Node.isPropertyAssignment(arrayParent)) {
            if (arrayParent.getName() === 'visuals')
                return true;
        }
    }
    // Context 3: Parent object has siblings suggesting visual config
    // (has 'type' property with value like 'popup', 'inline', etc.)
    const typeProp = parent.getProperty('type');
    if (typeProp && ts_morph_1.Node.isPropertyAssignment(typeProp)) {
        const typeInit = typeProp.getInitializerIfKind(ts_morph_1.SyntaxKind.StringLiteral);
        if (typeInit) {
            const typeValue = typeInit.getLiteralValue();
            if (typeValue === 'popup' ||
                typeValue === 'inline' ||
                typeValue === 'drawer')
                return true;
        }
    }
    return false;
}
