/**
 * ESLint rule to forbid instantiation in services
 * 
 * Services should not instantiate other services, API clients, or adapters.
 * They should receive dependencies via constructor injection.
 */

module.exports = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Forbid instantiation in services',
      category: 'Services',
      recommended: true,
    },
    fixable: null,
    schema: [],
    messages: {
      noInstantiation: 'Services should not instantiate {{type}} "{{name}}". Use constructor injection instead.',
      noNewInServices: 'Services should not use new keyword. Use constructor injection.',
    },
  },

  create(context) {
    const filename = context.getFilename();
    const isInServices = filename.includes('/lib/services/');

    if (!isInServices) return {};

    return {
      // Track new keyword usage
      NewExpression(node) {
        const callee = node.callee;
        
        // Get the name being instantiated
        let instantiatedName = '';
        if (callee.type === 'Identifier') {
          instantiatedName = callee.name;
        } else if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
          instantiatedName = callee.property.name;
        }

        // Check if it's a service, API client, or adapter
        const isService = instantiatedName.endsWith('Service');
        const isApiClient = instantiatedName.endsWith('ApiClient') || 
                           instantiatedName.endsWith('Client');
        const isAdapter = instantiatedName.includes('Adapter');
        const isRepository = instantiatedName.includes('Repository');
        const isGateway = instantiatedName.includes('Gateway');

        if (isService || isApiClient || isAdapter || isRepository || isGateway) {
          const type = isService ? 'Service' : 
                      isApiClient ? 'API Client' :
                      isAdapter ? 'Adapter' :
                      isRepository ? 'Repository' : 'Gateway';
          
          context.report({
            node,
            messageId: 'noInstantiation',
            data: { type, name: instantiatedName },
          });
        } else {
          // Any new keyword in services is suspicious
          context.report({
            node,
            messageId: 'noNewInServices',
          });
        }
      },

      // Also check for object literal instantiation
      ObjectExpression(node) {
        // Check if this is being assigned to a variable that looks like a service
        const parent = node.parent;
        if (parent && parent.type === 'VariableDeclarator') {
          const varName = parent.id.name;
          if (varName.endsWith('Service') || 
              varName.endsWith('Client') ||
              varName.includes('Adapter')) {
            context.report({
              node,
              messageId: 'noInstantiation',
              data: { type: 'object literal', name: varName },
            });
          }
        }
      },
    };
  },
};
