/**
 * ESLint rules for RSC Boundary Guardrails
 * 
 * Enforces server-side code boundaries in Next.js app directory
 */

module.exports = {
  // Rule 1: No ContainerManager in server code
  'no-container-manager-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid ContainerManager usage in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'ContainerManager usage forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        Identifier(node) {
          if (node.name === 'ContainerManager' && !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 2: No PageDataFetcher.fetch() in server code
  'no-page-data-fetcher-fetch-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid PageDataFetcher.fetch() in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'PageDataFetcher.fetch() forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        CallExpression(node) {
          if (node.callee.type === 'MemberExpression' &&
              node.callee.object.name === 'PageDataFetcher' &&
              node.callee.property.name === 'fetch' &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 3: No ViewModels/ViewModels imports in server code
  'no-view-models-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid ViewModels/Presenters imports in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'ViewModels or Presenters import forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        ImportDeclaration(node) {
          const importPath = node.source.value;
          if ((importPath.includes('@/lib/view-models/') || 
               importPath.includes('@/lib/presenters/')) &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 4: No Presenter imports in server code
  'no-presenters-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid Presenter imports in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Presenter import forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        ImportDeclaration(node) {
          const importPath = node.source.value;
          if ((importPath.includes('@/lib/presenters/') || 
               importPath.includes('@/lib/presenters/')) &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 5: No Intl usage in presentation paths
  'no-intl-in-presentation': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid Intl.* or toLocale* usage in presentation paths',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        MemberExpression(node) {
          if ((node.object.name === 'Intl' || 
               (node.property && node.property.name && node.property.name.startsWith('toLocale'))) &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 6: No sorting/filtering/reduce in server code
  'no-sorting-filtering-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid sorting/filtering/reduce operations in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      const sourceCode = context.getSourceCode();
      const hasUseClient = sourceCode.getText().includes("'use client'") || sourceCode.getText().includes('"use client"');

      return {
        CallExpression(node) {
          if (hasUseClient) return;
          if (node.callee.type === 'MemberExpression' &&
              ['sort', 'filter', 'reduce'].includes(node.callee.property.name) &&
              !isInComment(node) &&
              !node.loc.start.line.toString().includes('null check')) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 7: No DisplayObjects imports in server code
  'no-display-objects-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid DisplayObjects imports in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'DisplayObjects import forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        ImportDeclaration(node) {
          const importPath = node.source.value;
          if (importPath.includes('@/lib/display-objects/') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 8: No unsafe services imports in server code
  'no-unsafe-services-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid unsafe services imports in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Services import must be explicitly marked as server-safe - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        ImportDeclaration(node) {
          const importPath = node.source.value;
          if (importPath.includes('@/lib/services/') &&
              !isInComment(node) &&
              !isMarkedServerSafe(context.getSourceCode().getText(node))) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 9: No DI imports in server code
  'no-di-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid DI imports in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'DI import forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        ImportDeclaration(node) {
          const importPath = node.source.value;
          if (importPath.includes('@/lib/di/') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 10: No local helpers in server code
  'no-local-helpers-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid local helper functions in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      const sourceCode = context.getSourceCode();
      const hasUseClient = sourceCode.getText().includes("'use client'") || sourceCode.getText().includes('"use client"');

      return {
        FunctionDeclaration(node) {
          if (hasUseClient) return;
          // Skip if this is the main component (default export or ends with Page/Template)
          const filename = context.getFilename();
          const isMainComponent =
            (node.parent && node.parent.type === 'ExportDefaultDeclaration') ||
            (node.id && node.id.name && (node.id.name.endsWith('Page') || node.id.name.endsWith('Template') || node.id.name.endsWith('Component')));
          
          if (isMainComponent) return;
          
          // Only flag nested helper functions
          if (!node.id.name.startsWith('assert') &&
              !node.id.name.startsWith('invariant') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
        VariableDeclarator(node) {
          if (hasUseClient) return;
          // Skip if this is the main component
          const isMainComponent =
            (node.parent && node.parent.parent && node.parent.parent.type === 'ExportDefaultDeclaration') ||
            (node.id && node.id.name && (node.id.name.endsWith('Page') || node.id.name.endsWith('Template') || node.id.name.endsWith('Component')));
          
          if (isMainComponent) return;
          
          if (node.init &&
              (node.init.type === 'FunctionExpression' || node.init.type === 'ArrowFunctionExpression') &&
              !node.id.name.startsWith('assert') &&
              !node.id.name.startsWith('invariant') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 11: No object construction in server code
  'no-object-construction-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid object construction with new in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      const sourceCode = context.getSourceCode();
      const hasUseClient = sourceCode.getText().includes("'use client'") || sourceCode.getText().includes('"use client"');

      return {
        NewExpression(node) {
          if (hasUseClient) return;
          if (node.callee.type === 'Identifier' &&
              /^[A-Z]/.test(node.callee.name) &&
              !node.callee.name.endsWith('PageQuery') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },

  // Rule 12: No ContainerManager calls in server code
  'no-container-manager-calls-in-server': {
    meta: {
      type: 'problem',
      docs: {
        description: 'Forbid ContainerManager calls in server code',
        category: 'RSC Boundary',
      },
      messages: {
        message: 'ContainerManager calls forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts',
      },
    },
    create(context) {
      return {
        CallExpression(node) {
          if (node.callee.type === 'MemberExpression' &&
              node.callee.object.name === 'ContainerManager' &&
              (node.callee.property.name === 'getInstance' || 
               node.callee.property.name === 'getContainer') &&
              !isInComment(node)) {
            context.report({
              node,
              messageId: 'message',
            });
          }
        },
      };
    },
  },
};

// Helper functions
function isInComment(node) {
  // This is a simplified check - in practice you'd need to check the actual comment
  return false;
}

function isMarkedServerSafe(text) {
  return text.includes('// @server-safe') || text.includes('/* @server-safe */');
}