#!/usr/bin/env node
/**
 * MSW Handler Generator
 *
 * Automatically generates MSW request handlers from OpenAPI specification.
 * This keeps mock API in sync with real backend automatically.
 *
 * Usage: node scripts/generate-msw-handlers.ts /tmp/openapi.json
 */

import fs from 'fs';
import path from 'path';

interface OpenAPISpec {
  paths: {
    [path: string]: {
      [method: string]: {
        operationId?: string;
        summary?: string;
        responses: {
          [status: string]: {
            description: string;
            content?: {
              'application/json'?: {
                schema?: unknown;
              };
            };
          };
        };
        parameters?: Array<{
          name: string;
          in: string;
          required?: boolean;
          schema?: { type: string };
        }>;
        requestBody?: {
          content?: {
            'application/json'?: {
              schema?: unknown;
            };
          };
        };
      };
    };
  };
}

function parseOpenAPISpec(specPath: string): OpenAPISpec {
  const spec = JSON.parse(fs.readFileSync(specPath, 'utf-8'));
  return spec;
}

function getMethodName(method: string): string {
  const methodMap: Record<string, string> = {
    get: 'get',
    post: 'post',
    put: 'put',
    patch: 'patch',
    delete: 'delete',
  };
  return methodMap[method.toLowerCase()] || method;
}

function convertPathToMSWPattern(path: string): string {
  // Convert OpenAPI path params {id} to MSW params :id
  return path.replace(/\{([^}]+)\}/g, ':$1');
}

function shouldSkipEndpoint(path: string, _method: string): boolean {
  // Skip health check and root endpoints
  if (path === '/' || path === '/health') return true;

  // Skip OAuth endpoints (handled by regular login)
  if (path.includes('/oauth')) return true;

  return false;
}

function getHandlerCategory(path: string): 'auth' | 'users' | 'admin' | 'organizations' {
  if (path.startsWith('/api/v1/auth')) return 'auth';
  if (path.startsWith('/api/v1/admin')) return 'admin';
  if (path.startsWith('/api/v1/organizations')) return 'organizations';
  return 'users';
}

function generateMockResponse(path: string, method: string, _operation: any): string {
  const category = getHandlerCategory(path);

  // Auth endpoints
  if (category === 'auth') {
    if (path.includes('/login') && method === 'post') {
      return `
    const body = (await request.json()) as any;
    const user = validateCredentials(body.email, body.password);

    if (!user) {
      return HttpResponse.json(
        { detail: 'Incorrect email or password' },
        { status: 401 }
      );
    }

    const accessToken = \`demo-access-\${user.id}-\${Date.now()}\`;
    const refreshToken = \`demo-refresh-\${user.id}-\${Date.now()}\`;

    setCurrentUser(user);

    return HttpResponse.json({
      access_token: accessToken,
      refresh_token: refreshToken,
      token_type: 'bearer',
      expires_in: 900,
    });`;
    }

    if (path.includes('/register') && method === 'post') {
      return `
    const body = (await request.json()) as any;

    const newUser = {
      id: \`new-user-\${Date.now()}\`,
      email: body.email,
      first_name: body.first_name,
      last_name: body.last_name || null,
      phone_number: body.phone_number || null,
      is_active: true,
      is_superuser: false,
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
      last_login: null,
      organization_count: 0,
    };

    setCurrentUser(newUser);

    return HttpResponse.json({
      user: newUser,
      access_token: \`demo-access-\${Date.now()}\`,
      refresh_token: \`demo-refresh-\${Date.now()}\`,
      token_type: 'bearer',
      expires_in: 900,
    });`;
    }

    if (path.includes('/refresh') && method === 'post') {
      return `
    return HttpResponse.json({
      access_token: \`demo-access-refreshed-\${Date.now()}\`,
      refresh_token: \`demo-refresh-refreshed-\${Date.now()}\`,
      token_type: 'bearer',
      expires_in: 900,
    });`;
    }

    // Generic auth success
    return `
    return HttpResponse.json({
      success: true,
      message: 'Operation successful',
    });`;
  }

  // User endpoints
  if (category === 'users') {
    if (path === '/api/v1/users/me' && method === 'get') {
      return `
    if (!currentUser) {
      return HttpResponse.json({ detail: 'Not authenticated' }, { status: 401 });
    }
    return HttpResponse.json(currentUser);`;
    }

    if (path === '/api/v1/users/me' && method === 'patch') {
      return `
    if (!currentUser) {
      return HttpResponse.json({ detail: 'Not authenticated' }, { status: 401 });
    }
    const body = (await request.json()) as any;
    updateCurrentUser(body);
    return HttpResponse.json(currentUser);`;
    }

    if (path === '/api/v1/organizations/me' && method === 'get') {
      return `
    if (!currentUser) {
      return HttpResponse.json({ detail: 'Not authenticated' }, { status: 401 });
    }
    const orgs = getUserOrganizations(currentUser.id);
    return HttpResponse.json(orgs);`;
    }

    if (path === '/api/v1/sessions' && method === 'get') {
      return `
    if (!currentUser) {
      return HttpResponse.json({ detail: 'Not authenticated' }, { status: 401 });
    }
    return HttpResponse.json({ sessions: [] });`;
    }
  }

  // Admin endpoints
  if (category === 'admin') {
    const authCheck = `
    if (!currentUser?.is_superuser) {
      return HttpResponse.json({ detail: 'Admin access required' }, { status: 403 });
    }`;

    if (path === '/api/v1/admin/stats' && method === 'get') {
      return `${authCheck}
    return HttpResponse.json(adminStats);`;
    }

    if (path === '/api/v1/admin/users' && method === 'get') {
      return `${authCheck}
    const url = new URL(request.url);
    const page = parseInt(url.searchParams.get('page') || '1');
    const pageSize = parseInt(url.searchParams.get('page_size') || '50');

    const start = (page - 1) * pageSize;
    const end = start + pageSize;
    const paginatedUsers = sampleUsers.slice(start, end);

    return HttpResponse.json({
      data: paginatedUsers,
      pagination: {
        total: sampleUsers.length,
        page,
        page_size: pageSize,
        total_pages: Math.ceil(sampleUsers.length / pageSize),
        has_next: end < sampleUsers.length,
        has_prev: page > 1,
      },
    });`;
    }

    if (path === '/api/v1/admin/organizations' && method === 'get') {
      return `${authCheck}
    const url = new URL(request.url);
    const page = parseInt(url.searchParams.get('page') || '1');
    const pageSize = parseInt(url.searchParams.get('page_size') || '50');

    const start = (page - 1) * pageSize;
    const end = start + pageSize;
    const paginatedOrgs = sampleOrganizations.slice(start, end);

    return HttpResponse.json({
      data: paginatedOrgs,
      pagination: {
        total: sampleOrganizations.length,
        page,
        page_size: pageSize,
        total_pages: Math.ceil(sampleOrganizations.length / pageSize),
        has_next: end < sampleOrganizations.length,
        has_prev: page > 1,
      },
    });`;
    }
  }

  // Generic success response
  return `
    return HttpResponse.json({
      success: true,
      message: 'Operation successful'
    });`;
}

function generateHandlers(spec: OpenAPISpec): string {
  const handlers: string[] = [];

  for (const [pathPattern, pathItem] of Object.entries(spec.paths)) {
    for (const [method, operation] of Object.entries(pathItem)) {
      if (!['get', 'post', 'put', 'patch', 'delete'].includes(method.toLowerCase())) {
        continue;
      }

      if (shouldSkipEndpoint(pathPattern, method)) {
        continue;
      }

      const mswPath = convertPathToMSWPattern(pathPattern);
      const httpMethod = getMethodName(method);
      const summary = operation.summary || `${method.toUpperCase()} ${pathPattern}`;
      const mockResponse = generateMockResponse(pathPattern, method, operation);

      const handler = `
  /**
   * ${summary}
   */
  http.${httpMethod}(\`\${API_BASE_URL}${mswPath}\`, async ({ request, params }) => {
    await delay(NETWORK_DELAY);
    ${mockResponse}
  }),`;

      handlers.push(handler);
    }
  }

  return handlers.join('\n');
}

function generateHandlerFile(spec: OpenAPISpec): string {
  const handlersCode = generateHandlers(spec);

  return `/**
 * Auto-generated MSW Handlers
 *
 * ⚠️  DO NOT EDIT THIS FILE MANUALLY
 *
 * This file is automatically generated from the OpenAPI specification.
 * To regenerate: npm run generate:api
 *
 * For custom handler behavior, use src/mocks/handlers/overrides.ts
 *
 * Generated: ${new Date().toISOString()}
 */

import { http, HttpResponse, delay } from 'msw';
import {
  validateCredentials,
  setCurrentUser,
  updateCurrentUser,
  currentUser,
  sampleUsers,
} from '../data/users';
import {
  sampleOrganizations,
  getUserOrganizations,
  getOrganizationMembersList,
} from '../data/organizations';
import { adminStats } from '../data/stats';

const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8000';
const NETWORK_DELAY = 300; // ms - simulate realistic network delay

/**
 * Auto-generated request handlers
 * Covers all endpoints defined in OpenAPI spec
 */
export const generatedHandlers = [${handlersCode}
];
`;
}

// Main execution
function main() {
  const specPath = process.argv[2] || '/tmp/openapi.json';

  if (!fs.existsSync(specPath)) {
    console.error(`❌ OpenAPI spec not found at: ${specPath}`);
    console.error('   Make sure backend is running and OpenAPI spec is available');
    process.exit(1);
  }

  console.log('📖 Reading OpenAPI specification...');
  const spec = parseOpenAPISpec(specPath);

  console.log('🔨 Generating MSW handlers...');
  const handlerCode = generateHandlerFile(spec);

  const outputPath = path.join(__dirname, '../src/mocks/handlers/generated.ts');
  fs.writeFileSync(outputPath, handlerCode);

  console.log(`✅ Generated MSW handlers: ${outputPath}`);
  console.log(`📊 Generated ${Object.keys(spec.paths).length} endpoint handlers`);
}

main();
