import { z } from 'zod';
import {
  User,
  Customer,
  AdminUser,
  SuperUser,
  PhysicalProduct,
  DigitalProduct,
  RegularProduct,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zUser,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zCustomer,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zAdminUser,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zSuperUser,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zPhysicalProduct,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zDigitalProduct,
  // @ts-ignore - These schemas are generated by the type-compiler at build time
  zRegularProduct
} from './types';

/**
 * Helper function to validate and print the result
 */
function validateAndPrint<T>(schema: z.ZodType<T>, data: any, label: string): T | null {
  console.log(`\n--- Validating ${label} ---`);
  console.log('Input data:', data);
  
  try {
    const validatedData = schema.parse(data);
    console.log('✅ Validation passed');
    console.log('Validated data:', validatedData);
    return validatedData;
  } catch (error) {
    if (error instanceof z.ZodError) {
      console.log('❌ Validation failed');
      console.log('Errors:', error.errors.map(err => ({
        path: err.path.join('.'),
        message: err.message
      })));
    } else {
      console.log('❌ Unexpected error:', error);
    }
    return null;
  }
}

/**
 * Main function to demonstrate contextual validators
 */
function main() {
  console.log('======================================================');
  console.log('   CONTEXTUAL VALIDATORS EXAMPLE');
  console.log('======================================================');
  console.log('This example demonstrates how validation rules differ');
  console.log('for the same field name in different contexts (types)');
  console.log('======================================================\n');

  // Example 1: Compare User vs Customer email validation
  console.log('\n[EXAMPLE 1] Different email validation rules');
  
  // Valid User (company email)
  const validUser: User = {
    id: '1',
    name: 'John Employee',
    email: 'john@company.com',       // Must end with @company.com
    role: 'admin',                   // Must be admin, user, or guest
    status: 'active',                // Must be active or inactive
    createdAt: new Date()
  };
  
  // Invalid User (wrong email domain)
  const invalidUser = {
    id: '2',
    name: 'Jane Employee',
    email: 'jane@gmail.com',         // Invalid (wrong domain)
    role: 'admin',
    status: 'active',
    createdAt: new Date()
  };
  
  // Valid Customer (any email domain)
  const validCustomer: Customer = {
    id: '3',
    name: 'Bob Client',
    email: 'bob@gmail.com',          // Any valid email works
    type: 'individual',              // Must be individual or business
    status: 'pending',               // Can be active, inactive, pending, or suspended
    createdAt: new Date()
  };
  
  validateAndPrint(zUser, validUser, 'Valid User');
  validateAndPrint(zUser, invalidUser, 'Invalid User (wrong email domain)');
  validateAndPrint(zCustomer, validCustomer, 'Valid Customer');
  
  // Example 2: Different status values for User vs Customer
  console.log('\n[EXAMPLE 2] Different status values');
  
  const userWithInvalidStatus = {
    ...validUser,
    status: 'pending'                // Invalid for User (only active/inactive allowed)
  };
  
  const customerWithSameStatus = {
    ...validCustomer,
    status: 'pending'                // Valid for Customer
  };
  
  validateAndPrint(zUser, userWithInvalidStatus, 'User with "pending" status');
  validateAndPrint(zCustomer, customerWithSameStatus, 'Customer with "pending" status');
  
  // Example 3: Pattern-based type matching for Products
  console.log('\n[EXAMPLE 3] Pattern-based validation for Products');
  
  const validPhysicalProduct: PhysicalProduct = {
    id: '4',
    name: 'Desk Chair',
    description: 'Ergonomic office chair',
    price: 199.99,                   // Must be >= 0.01
    inventory: 42,                   // Must be integer >= 0
    weight: 15.5,
    dimensions: {
      length: 24,
      width: 24,
      height: 48
    },
    createdAt: new Date()
  };
  
  const invalidPhysicalProduct = {
    ...validPhysicalProduct,
    price: 0,                        // Invalid (must be >= 0.01)
    inventory: -5                    // Invalid (must be >= 0)
  };
  
  // Regular product doesn't get the stricter price validation
  const validRegularProduct: RegularProduct = {
    id: '5',
    name: 'Generic Item',
    price: 0.001,                    // Only needs to be positive, no minimum
    createdAt: new Date()
  };
  
  validateAndPrint(zPhysicalProduct, validPhysicalProduct, 'Valid Physical Product');
  validateAndPrint(zPhysicalProduct, invalidPhysicalProduct, 'Invalid Physical Product');
  validateAndPrint(zRegularProduct, validRegularProduct, 'Valid Regular Product (less strict price validation)');
  
  // Example 4: Pattern matching for Admin/Super users
  console.log('\n[EXAMPLE 4] Pattern matching for Admin/Super users');
  
  const validAdminUser: AdminUser = {
    id: '6',
    name: 'Admin Person',
    email: 'admin@company.com',
    role: 'admin',
    permissions: ['read', 'write', 'delete'],  // Must be non-empty array
    createdAt: new Date()
  };
  
  const invalidAdminUser = {
    ...validAdminUser,
    permissions: []                  // Invalid (must have at least one permission)
  };
  
  const validSuperUser: SuperUser = {
    id: '7',
    name: 'Super Person',
    email: 'super@company.com',
    role: 'admin',
    permissions: ['read', 'write', 'delete', 'admin'],  // Must be non-empty array
    createdAt: new Date()
  };
  
  validateAndPrint(zAdminUser, validAdminUser, 'Valid Admin User');
  validateAndPrint(zAdminUser, invalidAdminUser, 'Invalid Admin User (empty permissions)');
  validateAndPrint(zSuperUser, validSuperUser, 'Valid Super User (same validation rules)');
  
  console.log('\n======================================================');
  console.log('Contextual validators enable type-specific validation');
  console.log('rules even for fields with the same name.');
  console.log('======================================================');
}

// Run the examples
main(); 