import { describe, it, expect } from 'vitest';
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
// Removed unused imports for new 12-factor pattern
import { setupAgileManagementTools } from '../../modules/agile-management/tools.js';
import { setupKanbanTools } from '../../modules/kanban/tools.js';
import { setupDataManagementTools } from '../../modules/data-management/tools.js';
import { setupDocumentationTools } from '../../modules/documentation/tools.js';
import { setupBusinessGuidanceTools } from '../../modules/business-guidance/tools.js';
import { setupCodeAnalysisTools } from '../../modules/code-analysis/tools.js';
import { setupDevelopmentTools } from '../../modules/development/tools.js';
import { setupMemoryManagementTools } from '../../modules/memory-management/tools.js';

describe('JSON Schema Draft 2020-12 Validation', () => {
  // Create AJV instance with draft 2020-12 support
  const ajv = new Ajv({
    strict: true,
    validateFormats: true,
    allErrors: true,
  });
  
  // Add format validators
  addFormats(ajv);
  
  // No longer need mocks for new 12-factor pattern

  const testModuleSchemas = async (moduleName: string, setupFunction: Function) => {
    const module = await setupFunction();
    
    if (!module.tools || module.tools.length === 0) {
      return;
    }
    
    for (const tool of module.tools) {
      if (tool.inputSchema) {
        // Validate the schema itself is valid JSON Schema
        const schemaSchema = {
          type: 'object',
          properties: {
            type: { type: 'string' },
            properties: { type: 'object' },
            required: { type: 'array', items: { type: 'string' } }
          },
          required: ['type']
        };
        
        const validateSchema = ajv.compile(schemaSchema);
        const schemaValid = validateSchema(tool.inputSchema);
        
        if (!schemaValid) {
          console.error(`Schema validation errors for ${moduleName} - ${tool.name}:`, validateSchema.errors);
        }
        
        expect(schemaValid, `${moduleName} - ${tool.name} schema structure is invalid`).toBe(true);
        
        // Test that the schema can be compiled (validates pattern syntax, etc.)
        try {
          const validate = ajv.compile(tool.inputSchema);
          expect(validate).toBeDefined();
          
          // Test with a sample valid input
          if (tool.inputSchema.properties) {
            const sampleInput: any = {};
            
            // Generate sample data based on schema
            for (const [key, prop] of Object.entries(tool.inputSchema.properties as any)) {
              if (prop.type === 'string') {
                // For enum fields, use the first allowed value
                if (prop.enum && prop.enum.length > 0) {
                  sampleInput[key] = prop.default || prop.enum[0];
                } else if (prop.pattern) {
                  // Generate a value that matches the pattern
                  if (prop.pattern === '^[a-zA-Z0-9-]+$') {
                    sampleInput[key] = 'test-id-123';
                  } else {
                    sampleInput[key] = prop.default || 'test';
                  }
                } else {
                  sampleInput[key] = prop.default || 'test';
                }
              } else if (prop.type === 'number' || prop.type === 'integer') {
                sampleInput[key] = prop.default || 1;
              } else if (prop.type === 'boolean') {
                sampleInput[key] = prop.default || false;
              } else if (prop.type === 'array') {
                // For arrays with minItems, ensure we meet the requirement
                if (prop.minItems && prop.minItems > 0) {
                  const items = [];
                  for (let i = 0; i < prop.minItems; i++) {
                    if (prop.items && prop.items.type === 'object') {
                      // Create object with required properties
                      const itemObj: any = {};
                      if (prop.items.properties) {
                        for (const [itemKey, itemProp] of Object.entries(prop.items.properties as any)) {
                          if (prop.items.required && prop.items.required.includes(itemKey)) {
                            if (itemProp.type === 'string') {
                              itemObj[itemKey] = itemProp.enum ? itemProp.enum[0] : 'test';
                            } else if (itemProp.type === 'boolean') {
                              itemObj[itemKey] = false;
                            }
                          }
                        }
                      }
                      items.push(itemObj);
                    } else if (prop.items && prop.items.type === 'string') {
                      items.push('test');
                    } else {
                      items.push(null);
                    }
                  }
                  sampleInput[key] = prop.default || items;
                } else {
                  sampleInput[key] = prop.default || [];
                }
              } else if (prop.type === 'object') {
                sampleInput[key] = prop.default || {};
              }
            }
            
            // Only include required fields
            if (tool.inputSchema.required && tool.inputSchema.required.length > 0) {
              const requiredInput: any = {};
              for (const field of tool.inputSchema.required) {
                if (sampleInput[field] !== undefined) {
                  requiredInput[field] = sampleInput[field];
                }
              }
              
              const isValid = validate(requiredInput);
              if (!isValid && validate.errors) {
                console.error(`Validation errors for ${moduleName} - ${tool.name}:`, validate.errors);
              }
            }
          }
        } catch (error) {
          throw new Error(`Failed to compile schema for ${moduleName} - ${tool.name}: ${error.message}`);
        }
      }
    }
  };

  it('should validate agile management module schemas', async () => {
    await testModuleSchemas('agile-management', setupAgileManagementTools);
  });

  it('should validate kanban module schemas', async () => {
    await testModuleSchemas('kanban', setupKanbanTools);
  });

  it('should validate data management module schemas', async () => {
    await testModuleSchemas('data-management', setupDataManagementTools);
  });

  it('should validate documentation module schemas', async () => {
    await testModuleSchemas('documentation', setupDocumentationTools);
  });

  it('should validate business guidance module schemas', async () => {
    await testModuleSchemas('business-guidance', setupBusinessGuidanceTools);
  });

  it('should validate code analysis module schemas', async () => {
    await testModuleSchemas('code-analysis', setupCodeAnalysisTools);
  });

  it('should validate development module schemas', async () => {
    await testModuleSchemas('development', setupDevelopmentTools);
  });

  it('should validate memory management module schemas', async () => {
    await testModuleSchemas('memory-management', setupMemoryManagementTools);
  });
  
  it('should validate pattern regex syntax', async () => {
    // Test specific patterns that might be problematic
    const testPatterns = [
      { pattern: '^[a-zA-Z0-9 _-]+$', description: 'alphanumeric with space, underscore, hyphen' },
      { pattern: '^[a-zA-Z0-9]+$', description: 'alphanumeric only' },
      { pattern: '^.+$', description: 'any non-empty string' }
    ];
    
    for (const { pattern, description } of testPatterns) {
      const schema = {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            pattern: pattern
          }
        }
      };
      
      try {
        const validate = ajv.compile(schema);
        expect(validate).toBeDefined();
        
        // Test valid inputs based on pattern
        if (pattern === '^[a-zA-Z0-9 _-]+$') {
          // Pattern allows spaces, underscores and hyphens
          expect(validate({ name: 'Test_Name-123' })).toBe(true);
          expect(validate({ name: 'Test Name' })).toBe(true);
        } else if (pattern === '^[a-zA-Z0-9]+$') {
          // Pattern only allows alphanumeric
          expect(validate({ name: 'test123' })).toBe(true);
          expect(validate({ name: 'Test_Name-123' })).toBe(false);
          expect(validate({ name: 'Test Name' })).toBe(false);
        } else if (pattern === '^.+$') {
          // Pattern allows any non-empty string
          expect(validate({ name: 'Any string!' })).toBe(true);
        }
        
        // Test invalid inputs
        expect(validate({ name: '' })).toBe(false);
      } catch (error) {
        throw new Error(`Pattern validation failed for "${description}": ${error.message}`);
      }
    }
  });
});