/**
 * MSW Templates for Mock Service Worker integration
 * Using MSW v2.x (2025 latest version)
 */

/**
 * Generate MSW setup configuration
 */
export const getMswSetupTemplate = (): string => {
  return `// MSW Setup Configuration
// This file configures Mock Service Worker for the entire application

import { setupWorker } from 'msw/browser';
import { setupServer } from 'msw/node';
import { handlers } from './handlers/index';

// Browser worker for development
export const worker = setupWorker(...handlers);

// Node server for testing
export const server = setupServer(...handlers);

// Setup for different environments
export const setupMsw = async () => {
  if (typeof window !== 'undefined') {
    // Browser environment
    await worker.start({
      onUnhandledRequest: 'bypass',
      serviceWorker: {
        url: '/mockServiceWorker.js'
      }
    });
  }
};
`;
};

/**
 * Generate MSW browser configuration
 */
export const getMswBrowserTemplate = (): string => {
  return `// MSW Browser Worker Configuration
// This file sets up MSW for browser/development environment

import { setupWorker } from 'msw/browser';
import { handlers } from './handlers/index';

// Setup worker with all domain handlers
export const worker = setupWorker(...handlers);

// Start worker for development
export const startMsw = async () => {
  if (process.env.NODE_ENV === 'development') {
    await worker.start({
      onUnhandledRequest: 'bypass',
      serviceWorker: {
        url: '/mockServiceWorker.js'
      }
    });
    console.log('🔧 MSW: Mock Service Worker started');
  }
};
`;
};

/**
 * Generate MSW server configuration for Node.js/testing
 */
export const getMswServerTemplate = (): string => {
  return `// MSW Server Configuration
// This file sets up MSW for Node.js/testing environment

import { setupServer } from 'msw/node';
import { handlers } from './handlers/index';

// Setup server with all domain handlers
export const server = setupServer(...handlers);

// Server lifecycle for tests
export const startMswServer = () => {
  server.listen({ onUnhandledRequest: 'warn' });
};

export const resetMswServer = () => {
  server.resetHandlers();
};

export const stopMswServer = () => {
  server.close();
};
`;
};

/**
 * Generate handlers index file that exports all domain handlers
 */
export const getMswHandlersIndexTemplate = (domains: string[]): string => {
  const imports = domains.map(domain => 
    `import { ${domain}Handlers } from './${domain}';`
  ).join('\n');

  const exports = domains.map(domain => 
    `  ...${domain}Handlers,`
  ).join('\n');

  return `// MSW Handlers Index
// This file aggregates all domain handlers for MSW

${imports}

// Export all handlers for MSW setup
export const handlers = [
${exports}
];
`;
};

/**
 * Generate MSW handlers template for a specific domain
 */
export const getMswHandlersTemplate = (domainName: string): string => {
  const capitalizedDomain = domainName.charAt(0).toUpperCase() + domainName.slice(1);
  
  return `// ${capitalizedDomain} Domain MSW Handlers
// This file contains Mock Service Worker handlers for ${domainName} domain API endpoints

import { http, HttpResponse } from 'msw';
import { mock${capitalizedDomain}Data } from '../../../domains/${domainName}/mocks/mockData';

const API_BASE = '/api/${domainName}';

export const ${domainName}Handlers = [
  // GET /${domainName} - List all ${domainName} items
  http.get(\`\${API_BASE}\`, () => {
    return HttpResponse.json(mock${capitalizedDomain}Data.getAll());
  }),

  // GET /${domainName}/:id - Get single ${domainName} item
  http.get(\`\${API_BASE}/:id\`, ({ params }) => {
    const { id } = params;
    const item = mock${capitalizedDomain}Data.getById(id as string);
    
    if (!item) {
      return new HttpResponse(null, { 
        status: 404,
        statusText: '${capitalizedDomain} not found'
      });
    }
    
    return HttpResponse.json(item);
  }),

  // POST /${domainName} - Create new ${domainName} item
  http.post(\`\${API_BASE}\`, async ({ request }) => {
    try {
      const newItem = await request.json();
      const createdItem = mock${capitalizedDomain}Data.create(newItem);
      
      return HttpResponse.json(createdItem, { status: 201 });
    } catch (error) {
      return new HttpResponse(null, { 
        status: 400,
        statusText: 'Invalid ${domainName} data'
      });
    }
  }),

  // PUT /${domainName}/:id - Update ${domainName} item
  http.put(\`\${API_BASE}/:id\`, async ({ params, request }) => {
    const { id } = params;
    
    try {
      const updates = await request.json();
      const updatedItem = mock${capitalizedDomain}Data.update(id as string, updates);
      
      if (!updatedItem) {
        return new HttpResponse(null, { 
          status: 404,
          statusText: '${capitalizedDomain} not found'
        });
      }
      
      return HttpResponse.json(updatedItem);
    } catch (error) {
      return new HttpResponse(null, { 
        status: 400,
        statusText: 'Invalid ${domainName} data'
      });
    }
  }),

  // DELETE /${domainName}/:id - Delete ${domainName} item
  http.delete(\`\${API_BASE}/:id\`, ({ params }) => {
    const { id } = params;
    const deleted = mock${capitalizedDomain}Data.delete(id as string);
    
    if (!deleted) {
      return new HttpResponse(null, { 
        status: 404,
        statusText: '${capitalizedDomain} not found'
      });
    }
    
    return new HttpResponse(null, { status: 204 });
  }),

  // Add more ${domainName}-specific endpoints here
  // Example: GET /${domainName}/:id/relationships
  // http.get(\`\${API_BASE}/:id/relationships\`, ({ params }) => {
  //   const { id } = params;
  //   const relationships = mock${capitalizedDomain}Data.getRelationships(id as string);
  //   return HttpResponse.json(relationships);
  // }),
];
`;
};

/**
 * Generate mock data template for a specific domain
 */
export const getMswMocksTemplate = (domainName: string): string => {
  const capitalizedDomain = domainName.charAt(0).toUpperCase() + domainName.slice(1);
  
  return `// ${capitalizedDomain} Domain Mock Data
// This file contains mock data and utilities for ${domainName} domain testing

/**
 * TODO: Replace this interface with your actual ${capitalizedDomain} entity
 * Import from: '../entities/${capitalizedDomain}'
 */
interface ${capitalizedDomain} {
  id: string;
  name: string;
  createdAt: string;
  updatedAt: string;
  // Add your domain-specific fields here
}

/**
 * Mock ${domainName} data store
 */
class Mock${capitalizedDomain}Data {
  private data: ${capitalizedDomain}[] = [
    {
      id: '1',
      name: 'Sample ${capitalizedDomain} 1',
      createdAt: '2025-01-01T00:00:00Z',
      updatedAt: '2025-01-01T00:00:00Z',
    },
    {
      id: '2',
      name: 'Sample ${capitalizedDomain} 2',
      createdAt: '2025-01-02T00:00:00Z',
      updatedAt: '2025-01-02T00:00:00Z',
    },
    {
      id: '3',
      name: 'Sample ${capitalizedDomain} 3',
      createdAt: '2025-01-03T00:00:00Z',
      updatedAt: '2025-01-03T00:00:00Z',
    },
  ];

  /**
   * Get all ${domainName} items
   */
  getAll(): ${capitalizedDomain}[] {
    return [...this.data];
  }

  /**
   * Get ${domainName} item by ID
   */
  getById(id: string): ${capitalizedDomain} | undefined {
    return this.data.find(item => item.id === id);
  }

  /**
   * Create new ${domainName} item
   */
  create(item: Partial<${capitalizedDomain}>): ${capitalizedDomain} {
    const newItem: ${capitalizedDomain} = {
      id: Date.now().toString(),
      name: item.name || 'New ${capitalizedDomain}',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      ...item,
    };
    
    this.data.push(newItem);
    return newItem;
  }

  /**
   * Update ${domainName} item
   */
  update(id: string, updates: Partial<${capitalizedDomain}>): ${capitalizedDomain} | undefined {
    const index = this.data.findIndex(item => item.id === id);
    
    if (index === -1) {
      return undefined;
    }
    
    this.data[index] = {
      ...this.data[index],
      ...updates,
      updatedAt: new Date().toISOString(),
    };
    
    return this.data[index];
  }

  /**
   * Delete ${domainName} item
   */
  delete(id: string): boolean {
    const index = this.data.findIndex(item => item.id === id);
    
    if (index === -1) {
      return false;
    }
    
    this.data.splice(index, 1);
    return true;
  }

  /**
   * Reset data to initial state (useful for tests)
   */
  reset(): void {
    this.data = [
      {
        id: '1',
        name: 'Sample ${capitalizedDomain} 1',
        createdAt: '2025-01-01T00:00:00Z',
        updatedAt: '2025-01-01T00:00:00Z',
      },
      {
        id: '2',
        name: 'Sample ${capitalizedDomain} 2',
        createdAt: '2025-01-02T00:00:00Z',
        updatedAt: '2025-01-02T00:00:00Z',
      },
      {
        id: '3',
        name: 'Sample ${capitalizedDomain} 3',
        createdAt: '2025-01-03T00:00:00Z',
        updatedAt: '2025-01-03T00:00:00Z',
      },
    ];
  }

  /**
   * Add custom methods for your domain-specific operations
   * Example: getByStatus, getByUser, etc.
   */
}

// Export singleton instance
export const mock${capitalizedDomain}Data = new Mock${capitalizedDomain}Data();
`;
};

/**
 * Generate setupTests.ts configuration for MSW
 */
export const getMswSetupTestsTemplate = (): string => {
  return `// Global Test Setup with MSW
// This file configures testing environment with Mock Service Worker

import '@testing-library/jest-dom';
import { server } from './mocks/server';

// Enable MSW server before all tests
beforeAll(() => {
  server.listen({ onUnhandledRequest: 'warn' });
});

// Reset handlers between tests to ensure test isolation
afterEach(() => {
  server.resetHandlers();
});

// Close server after all tests
afterAll(() => {
  server.close();
});

// Global test utilities
global.ResizeObserver = class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
};

// Mock console.error for cleaner test output
const originalError = console.error;
beforeAll(() => {
  console.error = (...args: any[]) => {
    if (
      typeof args[0] === 'string' &&
      args[0].includes('Warning: ReactDOM.render is deprecated')
    ) {
      return;
    }
    originalError.call(console, ...args);
  };
});

afterAll(() => {
  console.error = originalError;
});
`;
}; 