// @ts-nocheck
/* eslint-disable @typescript-eslint/no-unused-vars */
import { isObject } from 'vest-utils';
import { describe, it, expect, beforeEach, vi } from 'vitest';

describe('enforce.extend', () => {
  let enforce: any;
  beforeEach(async () => {
    vi.resetModules();
    vi.clearAllMocks();

    ({ enforce } = await import('../n4s'));
  });

  describe('Basic functionality', () => {
    describe('Boolean return values', () => {
      beforeEach(() => {
        enforce.extend({
          isValidEmail: (value: string) => value.indexOf('@') > -1,
          hasKey: (value: Record<string, any>, key: string) =>
            value.hasOwnProperty(key),
        });
      });

      it('Should allow custom rule with boolean return value (true)', () => {
        expect(() => enforce('test@example.com').isValidEmail()).not.toThrow();
      });

      it('Should allow custom rule with boolean return value (false)', () => {
        expect(() => enforce('invalid-email').isValidEmail()).toThrow();
      });

      it('Should work with multiple arguments', () => {
        expect(() => enforce({ name: 'John' }).hasKey('name')).not.toThrow();
        expect(() => enforce({ name: 'John' }).hasKey('age')).toThrow();
      });

      it('Should work in lazy mode with .run()', () => {
        expect(enforce.isValidEmail().run('test@example.com').pass).toBe(true);
        expect(enforce.isValidEmail().run('invalid-email').pass).toBe(false);
      });

      it('Should work in lazy mode with .run() returning full result', () => {
        expect(enforce.isValidEmail().run('test@example.com')).toEqual({
          pass: true,
          type: 'test@example.com',
        });
        expect(enforce.isValidEmail().run('invalid-email')).toEqual({
          pass: false,
          type: 'invalid-email',
        });
      });
    });

    describe('Object return values with pass and message', () => {
      beforeEach(() => {
        enforce.extend({
          isValidEmail: (value: string) => ({
            pass: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
            message: () => `${value} is not a valid email address`,
          }),
          isWithinRange: (value: number, floor: number, ceiling: number) => {
            const pass = value >= floor && value <= ceiling;
            return {
              pass,
              message: () =>
                pass
                  ? `expected ${value} not to be within range ${floor} - ${ceiling}`
                  : `expected ${value} to be within range ${floor} - ${ceiling}`,
            };
          },
        });
      });

      it('Should handle object return with pass: true', () => {
        expect(() => enforce('test@example.com').isValidEmail()).not.toThrow();
      });

      it('Should handle object return with pass: false and use custom message', () => {
        expect(() => enforce('invalid').isValidEmail()).toThrow(
          'invalid is not a valid email address',
        );
      });

      it('Should work with multiple arguments', () => {
        expect(() => enforce(5).isWithinRange(1, 10)).not.toThrow();
        expect(() => enforce(15).isWithinRange(1, 10)).toThrow(
          'expected 15 to be within range 1 - 10',
        );
      });

      it('Should work in lazy mode with .run()', () => {
        expect(enforce.isValidEmail().run('test@example.com').pass).toBe(true);
        expect(enforce.isValidEmail().run('invalid').pass).toBe(false);
      });

      it('Should work in lazy mode with .run() returning full result', () => {
        expect(enforce.isValidEmail().run('test@example.com')).toEqual({
          pass: true,
          type: 'test@example.com',
        });
        expect(enforce.isValidEmail().run('invalid')).toEqual({
          pass: false,
          type: 'invalid',
          message: 'invalid is not a valid email address',
        });
      });
    });

    describe('Object return with just message string', () => {
      beforeEach(() => {
        enforce.extend({
          customRule: () => ({
            pass: false,
            message: 'Static error message',
          }),
        });
      });

      it('Should handle message as string instead of function', () => {
        expect(() => enforce('value').customRule()).toThrow(
          'Static error message',
        );
      });

      it('Should work with .run()', () => {
        expect(enforce.customRule().run('value')).toEqual({
          pass: false,
          type: 'value',
          message: 'Static error message',
        });
      });
    });
  });

  describe('Chaining custom rules', () => {
    beforeEach(() => {
      enforce.extend({
        startsWithUnderscore: (value: string) => ({
          pass: value.startsWith('_'),
          message: () => `${value} does not start with underscore`,
        }),
        hasLength: (value: string, length: number) => value.length === length,
        isLowerCase: (value: string) => value === value.toLowerCase(),
      });
    });

    it('Should allow chaining custom rules with built-in rules', () => {
      expect(() =>
        enforce('_test').startsWithUnderscore().isString(),
      ).not.toThrow();
    });

    it('Should allow chaining multiple custom rules', () => {
      expect(() =>
        enforce('_test').startsWithUnderscore().hasLength(5).isLowerCase(),
      ).not.toThrow();
    });

    it('Should throw on first failed rule in chain', () => {
      expect(() => enforce('test').startsWithUnderscore().hasLength(4)).toThrow(
        'test does not start with underscore',
      );
    });

    it('Should work with lazy evaluation', () => {
      expect(
        enforce.startsWithUnderscore().hasLength(5).isLowerCase().run('_test')
          .pass,
      ).toBe(true);
      expect(
        enforce.startsWithUnderscore().hasLength(5).isLowerCase().run('_TEST')
          .pass,
      ).toBe(false);
    });
  });

  describe('Edge cases and error handling', () => {
    it('Should handle custom rule that returns undefined', () => {
      enforce.extend({
        returnsUndefined: () => undefined,
      });
      expect(() => enforce('test').returnsUndefined()).toThrow();
    });

    it('Should handle custom rule that returns null', () => {
      enforce.extend({
        returnsNull: () => null,
      });
      expect(() => enforce('test').returnsNull()).toThrow();
    });

    it('Should handle custom rule that throws an error', () => {
      enforce.extend({
        throwsError: () => {
          throw new Error('Custom error');
        },
      });
      expect(() => enforce('test').throwsError()).toThrow('Custom error');
    });

    it('Should handle custom rule with no arguments', () => {
      enforce.extend({
        alwaysTrue: () => true,
        alwaysFalse: () => false,
      });
      expect(() => enforce('test').alwaysTrue()).not.toThrow();
      expect(() => enforce('test').alwaysFalse()).toThrow();
    });

    it('Should handle custom rule receiving different value types', () => {
      enforce.extend({
        checkType: (value: any) => ({
          pass: true,
          message: () => `Type: ${typeof value}`,
        }),
      });
      expect(() => enforce(123).checkType()).not.toThrow();
      expect(() => enforce('string').checkType()).not.toThrow();
      expect(() => enforce(null).checkType()).not.toThrow();
      expect(() => enforce(undefined).checkType()).not.toThrow();
      expect(() => enforce({}).checkType()).not.toThrow();
      expect(() => enforce([]).checkType()).not.toThrow();
    });

    it('Should handle custom rules with many arguments', () => {
      enforce.extend({
        sumEquals: (value: number, ...args: number[]) =>
          value === args.reduce((sum, n) => sum + n, 0),
      });
      expect(() => enforce(10).sumEquals(1, 2, 3, 4)).not.toThrow();
      expect(() => enforce(10).sumEquals(1, 2, 3)).toThrow();
    });
  });

  describe('Multiple extend calls', () => {
    it('Should allow multiple extend calls to add different rules', () => {
      enforce.extend({
        customRule1: () => true,
      });
      enforce.extend({
        customRule2: () => true,
      });
      expect(() => enforce('test').customRule1().customRule2()).not.toThrow();
    });

    it('Should allow overriding existing custom rules', () => {
      enforce.extend({
        toggleRule: () => true,
      });
      expect(() => enforce('test').toggleRule()).not.toThrow();

      enforce.extend({
        toggleRule: () => false,
      });
      expect(() => enforce('test').toggleRule()).toThrow();
    });

    it('Should not affect built-in rules', () => {
      enforce.extend({
        customRule: () => true,
      });
      // Built-in rules should still work
      expect(() => enforce('test').isString()).not.toThrow();
      expect(() => enforce(123).isNumber()).not.toThrow();
    });
  });

  describe('Integration with schema rules', () => {
    beforeEach(() => {
      enforce.extend({
        isEmail: (value: string) =>
          /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
        isAdult: (value: number) => value >= 18,
      });
    });

    it('Should work within shape()', () => {
      const schema = enforce.shape({
        email: enforce.isString().isEmail(),
        age: enforce.isNumber().isAdult(),
      });

      expect(schema.run({ email: 'test@example.com', age: 25 }).pass).toBe(
        true,
      );
      expect(schema.run({ email: 'invalid', age: 16 }).pass).toBe(false);
    });

    it('Should work within loose()', () => {
      const schema = enforce.loose({
        email: enforce.isString().isEmail(),
      });
      expect(
        schema.run({ email: 'test@example.com', extra: 'field' }).pass,
      ).toBe(true);
    });

    it('Should work within isArrayOf()', () => {
      const rule = enforce.isArrayOf(enforce.isString().isEmail());
      expect(rule.run(['test@example.com', 'another@example.com']).pass).toBe(
        true,
      );
      expect(rule.run(['test@example.com', 'invalid']).pass).toBe(false);
    });

    it('Should work within optional()', () => {
      const schema = enforce.shape({
        email: enforce.optional(enforce.isString().isEmail()),
      });
      expect(schema.run({ email: 'test@example.com' }).pass).toBe(true);
      expect(schema.run({}).pass).toBe(true);
    });
  });

  describe('Integration with compound rules', () => {
    beforeEach(() => {
      enforce.extend({
        isPositive: (value: number) => value > 0,
        isEven: (value: number) => value % 2 === 0,
        isOdd: (value: number) => value % 2 !== 0,
      });
    });

    it('Should work within allOf()', () => {
      const ok = enforce
        .allOf(enforce.isNumber(), enforce.isPositive(), enforce.isEven())
        .run(4).pass;
      expect(ok).toBe(true);

      const notOk = enforce
        .allOf(enforce.isNumber(), enforce.isPositive(), enforce.isEven())
        .run(-4).pass;
      expect(notOk).toBe(false);
    });

    it('Should work within anyOf()', () => {
      const res = enforce.anyOf(enforce.isEven(), enforce.isOdd()).run(3).pass;
      expect(res).toBe(true);
    });

    it('Should work within noneOf()', () => {
      const res = enforce
        .noneOf(enforce.isNumber(), enforce.isPositive())
        .run('string').pass;
      expect(res).toBe(true);
    });

    it('Should work within oneOf()', () => {
      expect(() =>
        enforce(3).oneOf(enforce.isEven(), enforce.isOdd(), enforce.isNumber()),
      ).toThrow(); // Fails because two rules pass (isOdd and isNumber)
    });
  });

  describe('Custom rules with enforce.context()', () => {
    beforeEach(() => {
      enforce.extend({
        contextAware: (value: string) => {
          const context = enforce.context();
          return !!context;
        },
        accessParent: (value: string) => {
          const context = enforce.context();
          return context?.parent !== undefined;
        },
        accessMeta: (value: string) => {
          const context = enforce.context();
          return context?.meta !== undefined;
        },
      });
    });

    it('Should have access to context', () => {
      expect(() => enforce('test').contextAware()).not.toThrow();
    });

    it('Should have access to parent in context', () => {
      expect(() => enforce('test').accessParent()).not.toThrow();
    });

    it('Should have access to meta in context', () => {
      expect(() => enforce('test').accessMeta()).not.toThrow();
    });

    it('Should allow traversing parent values', () => {
      enforce.extend({
        isFriendTheSameAsUser: (value: string) => {
          const context = enforce.context();
          if (value === context?.parent()?.parent()?.value.username) {
            return {
              pass: false,
              message: () => 'Friend cannot be the same as username',
            };
          }
          return true;
        },
      });

      expect(() =>
        enforce({
          username: 'johndoe',
          friends: ['Mike', 'Jim'],
        }).shape({
          username: enforce.isString(),
          friends: enforce.isArrayOf(
            enforce.isString().isFriendTheSameAsUser(),
          ),
        }),
      ).not.toThrow();

      expect(() =>
        enforce({
          username: 'johndoe',
          friends: ['Mike', 'Jim', 'johndoe'],
        }).shape({
          username: enforce.isString(),
          friends: enforce.isArrayOf(
            enforce.isString().isFriendTheSameAsUser(),
          ),
        }),
      ).toThrow(/Friend cannot be the same as username|enforce/);
    });
  });

  describe('Custom rules with enforce.message()', () => {
    beforeEach(() => {
      enforce.extend({
        ruleWithMessage: () => ({
          pass: false,
          message: () => 'Original message',
        }),
        ruleWithoutMessage: () => false,
      });
    });

    it('Should allow overriding custom rule message', () => {
      expect(() =>
        enforce('test').message('Custom message').ruleWithMessage(),
      ).toThrow('Custom message');
    });

    it('Should allow overriding message on rules without explicit message', () => {
      expect(() =>
        enforce('test').message('Custom message').ruleWithoutMessage(),
      ).toThrow('Custom message');
    });

    it('Should work with message as function', () => {
      expect(() =>
        enforce('test')
          .message(() => 'Custom message')
          .ruleWithMessage(),
      ).toThrow('Custom message');
    });
  });

  describe('Type coercion and edge cases', () => {
    beforeEach(() => {
      enforce.extend({
        checksEquality: (value: any, expected: any) => value === expected,
        checksLooseEquality: (value: any, expected: any) => value == expected,
      });
    });

    it('Should handle strict equality', () => {
      expect(() => enforce(1).checksEquality(1)).not.toThrow();
      expect(() => enforce(1).checksEquality('1')).toThrow();
      expect(() => enforce(true).checksEquality(1)).toThrow();
      expect(() => enforce(null).checksEquality(undefined)).toThrow();
    });

    it('Should handle loose equality', () => {
      expect(() => enforce(1).checksLooseEquality('1')).not.toThrow();
      expect(() => enforce(true).checksLooseEquality(1)).not.toThrow();
      expect(() => enforce(null).checksLooseEquality(undefined)).not.toThrow();
    });

    it('Should handle falsy values correctly', () => {
      enforce.extend({
        isFalsy: (value: any) => !value,
        isTruthy: (value: any) => !!value,
      });

      expect(() => enforce(0).isFalsy()).not.toThrow();
      expect(() => enforce('').isFalsy()).not.toThrow();
      expect(() => enforce(false).isFalsy()).not.toThrow();
      expect(() => enforce(null).isFalsy()).not.toThrow();
      expect(() => enforce(undefined).isFalsy()).not.toThrow();

      expect(() => enforce(1).isTruthy()).not.toThrow();
      expect(() => enforce('text').isTruthy()).not.toThrow();
      expect(() => enforce(true).isTruthy()).not.toThrow();
      expect(() => enforce({}).isTruthy()).not.toThrow();
      expect(() => enforce([]).isTruthy()).not.toThrow();
    });
  });

  describe('Complex real-world scenarios', () => {
    it('Should support password validation rules', () => {
      enforce.extend({
        hasMinLength: (value: string, length: number) => value.length >= length,
        hasUpperCase: (value: string) => /[A-Z]/.test(value),
        hasLowerCase: (value: string) => /[a-z]/.test(value),
        hasNumber: (value: string) => /[0-9]/.test(value),
        hasSpecialChar: (value: string) => /[!@#$%^&*(),.?":{}|<>]/.test(value),
      });

      const password = 'SecureP@ss123';
      expect(() =>
        enforce(password)
          .hasMinLength(8)
          .hasUpperCase()
          .hasLowerCase()
          .hasNumber()
          .hasSpecialChar(),
      ).not.toThrow();

      expect(() => enforce('weak').hasMinLength(8)).toThrow();
      expect(() => enforce('alllowercase').hasUpperCase()).toThrow();
    });

    it('Should support conditional validation', () => {
      enforce.extend({
        passwordsMatch: (passConfirm: string, password: string) =>
          passConfirm === password,
        isValidIf: (value: any, condition: boolean, validator: () => boolean) =>
          !condition || validator(),
      });

      expect(() => enforce('pass123').passwordsMatch('pass123')).not.toThrow();
      expect(() => enforce('pass123').passwordsMatch('different')).toThrow();
    });

    it('Should support date range validation', () => {
      enforce.extend({
        isAfter: (value: Date, date: Date) => value > date,
        isBefore: (value: Date, date: Date) => value < date,
        isBetween: (value: Date, start: Date, end: Date) =>
          value >= start && value <= end,
      });

      const now = new Date();
      const yesterday = new Date(now.getTime() - 86400000);
      const tomorrow = new Date(now.getTime() + 86400000);

      expect(() => enforce(now).isAfter(yesterday)).not.toThrow();
      expect(() => enforce(now).isBefore(tomorrow)).not.toThrow();
      expect(() => enforce(now).isBetween(yesterday, tomorrow)).not.toThrow();
    });
  });

  describe('Performance and stress tests', () => {
    it('Should handle many custom rules', () => {
      const rules: Record<string, () => boolean> = {};
      for (let i = 0; i < 100; i++) {
        rules[`rule${i}`] = () => true;
      }
      enforce.extend(rules);

      expect(() => enforce('test').rule0().rule50().rule99()).not.toThrow();
    });

    it('Should handle deeply nested validation with custom rules', () => {
      enforce.extend({
        isEmail: (value: string) =>
          /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
        isAdult: (value: number) => value >= 18,
      });

      const schema = enforce.shape({
        user: enforce.shape({
          profile: enforce.shape({
            contact: enforce.shape({
              email: enforce.isString().isEmail(),
            }),
            age: enforce.isNumber().isAdult(),
          }),
        }),
      });
      expect(
        schema.run({
          user: {
            profile: { contact: { email: 'test@example.com' }, age: 25 },
          },
        }).pass,
      ).toBe(true);
    });
  });

  describe('Error message customization', () => {
    it('Should support dynamic error messages based on input', () => {
      enforce.extend({
        isInRange: (value: number, min: number, max: number) => ({
          pass: value >= min && value <= max,
          message: () =>
            `Value ${value} is outside the allowed range of ${min}-${max}`,
        }),
      });

      expect(() => enforce(15).isInRange(1, 10)).toThrow(
        'Value 15 is outside the allowed range of 1-10',
      );
    });

    it('Should support error messages with context', () => {
      enforce.extend({
        notSameAsField: (value: string, fieldName: string) => {
          const context = enforce.context();
          const parentValue = context?.parent()?.value;
          return {
            pass: value !== parentValue?.[fieldName],
            message: () =>
              `Value cannot be the same as ${fieldName}: ${parentValue?.[fieldName]}`,
          };
        },
      });

      expect(() =>
        enforce({
          username: 'johndoe',
          displayName: 'johndoe',
        }).shape({
          username: enforce.isString(),
          displayName: enforce.isString().notSameAsField('username'),
        }),
      ).toThrow(/Value cannot be the same as username|enforce/);
    });
  });

  describe('Async behavior considerations', () => {
    it('Should handle custom rules that might be used async (returning promises should fail sync)', () => {
      enforce.extend({
        // This simulates someone accidentally returning a promise
        asyncRule: () => Promise.resolve(true),
      });

      // In n4spath, invalid return values should throw
      expect(() => enforce('test').asyncRule()).toThrow();
    });
  });

  describe('Cleanup and isolation', () => {
    it('Should not leak custom rules between test runs', () => {
      // This test ensures that custom rules don't persist unexpectedly
      // Note: In actual implementation, this might require cleanup between tests

      enforce.extend({
        temporaryRule: () => true,
      });

      expect(enforce.temporaryRule).toBeDefined();
    });
  });

  describe('Integration with condition()', () => {
    it('Should work alongside enforce.condition()', () => {
      enforce.extend({
        isEven: (value: number) => value % 2 === 0,
      });

      expect(enforce.condition(() => true).run(4).pass).toBe(true);
      expect(enforce.condition(() => false).run(3).pass).toBe(false);
    });
  });

  describe('Comprehensive Lazy API tests', () => {
    describe('Boolean return values with lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          isValidEmail: (value: string) => value.indexOf('@') > -1,
          hasKey: (value: Record<string, any>, key: string) =>
            value.hasOwnProperty(key),
          isPositive: (value: number) => value > 0,
          isEven: (value: number) => value % 2 === 0,
          isLengthBetween: (value: string, min: number, max: number) =>
            value.length >= min && value.length <= max,
        });
      });

      it('Should work with single argument - passing case', () => {
        const result = enforce.isValidEmail().run('test@example.com');
        expect(result).toEqual({
          pass: true,
          type: 'test@example.com',
        });
      });

      it('Should work with single argument - failing case', () => {
        const result = enforce.isValidEmail().run('invalid-email');
        expect(result).toEqual({
          pass: false,
          type: 'invalid-email',
        });
      });

      it('Should work with multiple arguments - passing case', () => {
        const result = enforce.hasKey('name').run({ name: 'John', age: 30 });
        expect(result).toEqual({
          pass: true,
          type: { name: 'John', age: 30 },
        });
      });

      it('Should work with multiple arguments - failing case', () => {
        const result = enforce.hasKey('email').run({ name: 'John', age: 30 });
        expect(result).toEqual({
          pass: false,
          type: { name: 'John', age: 30 },
        });
      });

      it('Should work with numeric validations', () => {
        expect(enforce.isPositive().run(5)).toEqual({
          pass: true,
          type: 5,
        });
        expect(enforce.isPositive().run(-5)).toEqual({
          pass: false,
          type: -5,
        });
        expect(enforce.isEven().run(4)).toEqual({
          pass: true,
          type: 4,
        });
        expect(enforce.isEven().run(3)).toEqual({
          pass: false,
          type: 3,
        });
      });

      it('Should work with multiple arguments and complex types', () => {
        expect(enforce.isLengthBetween(3, 10).run('hello')).toEqual({
          pass: true,
          type: 'hello',
        });
        expect(enforce.isLengthBetween(3, 10).run('hi')).toEqual({
          pass: false,
          type: 'hi',
        });
        expect(enforce.isLengthBetween(3, 10).run('this is too long')).toEqual({
          pass: false,
          type: 'this is too long',
        });
      });

      it('Should handle different data types', () => {
        enforce.extend({
          alwaysTrue: () => true,
          alwaysFalse: () => false,
        });

        // String
        expect(enforce.alwaysTrue().run('string')).toEqual({
          pass: true,
          type: 'string',
        });

        // Number
        expect(enforce.alwaysTrue().run(42)).toEqual({
          pass: true,
          type: 42,
        });

        // Boolean
        expect(enforce.alwaysTrue().run(true)).toEqual({
          pass: true,
          type: true,
        });

        // Object
        const obj = { key: 'value' };
        expect(enforce.alwaysTrue().run(obj)).toEqual({
          pass: true,
          type: obj,
        });

        // Array
        const arr = [1, 2, 3];
        expect(enforce.alwaysTrue().run(arr)).toEqual({
          pass: true,
          type: arr,
        });

        // Null
        expect(enforce.alwaysTrue().run(null)).toEqual({
          pass: true,
          type: null,
        });

        // Undefined
        expect(enforce.alwaysTrue().run(undefined)).toEqual({
          pass: true,
          type: undefined,
        });
      });
    });

    describe('Object return values with lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          isValidEmailWithMessage: (value: string) => ({
            pass: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
            message: () => `${value} is not a valid email address`,
          }),
          isWithinRange: (value: number, floor: number, ceiling: number) => {
            const pass = value >= floor && value <= ceiling;
            return {
              pass,
              message: () =>
                pass
                  ? `expected ${value} not to be within range ${floor} - ${ceiling}`
                  : `expected ${value} to be within range ${floor} - ${ceiling}`,
            };
          },
          hasExactLength: (value: string, length: number) => ({
            pass: value.length === length,
            message: () => `Expected length ${length}, got ${value.length}`,
          }),
        });
      });

      it('Should work with object return - passing case', () => {
        const result = enforce
          .isValidEmailWithMessage()
          .run('test@example.com');
        expect(result).toEqual({
          pass: true,
          type: 'test@example.com',
        });
      });

      it('Should work with object return - failing case', () => {
        const result = enforce.isValidEmailWithMessage().run('invalid');
        expect(result).toEqual({
          pass: false,
          type: 'invalid',
          message: 'invalid is not a valid email address',
        });
      });

      it('Should work with multiple arguments and object return', () => {
        expect(enforce.isWithinRange(1, 10).run(5)).toEqual({
          pass: true,
          type: 5,
        });
        expect(enforce.isWithinRange(1, 10).run(15)).toEqual({
          pass: false,
          type: 15,
          message: 'expected 15 to be within range 1 - 10',
        });
      });

      it('Should work with complex validation scenarios', () => {
        expect(enforce.hasExactLength(5).run('hello')).toEqual({
          pass: true,
          type: 'hello',
        });
        expect(enforce.hasExactLength(5).run('hi')).toEqual({
          pass: false,
          type: 'hi',
          message: 'Expected length 5, got 2',
        });
      });
    });

    describe('Chaining with lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          startsWithUnderscore: (value: string) => value.startsWith('_'),
          hasMinLength: (value: string, length: number) =>
            value.length >= length,
          isLowerCase: (value: string) => value === value.toLowerCase(),
          isAlphanumeric: (value: string) => /^[a-zA-Z0-9]+$/.test(value),
        });
      });

      it('Should work with chained custom rules', () => {
        const result = enforce
          .startsWithUnderscore()
          .hasMinLength(5)
          .isLowerCase()
          .run('_test');
        expect(result).toEqual({
          pass: true,
          type: '_test',
        });
      });

      it('Should fail on first failed rule in chain', () => {
        const result = enforce
          .startsWithUnderscore()
          .hasMinLength(5)
          .isLowerCase()
          .run('test');
        expect(result).toEqual({
          pass: false,
          type: 'test',
        });
      });

      it('Should work with mix of custom and built-in rules', () => {
        const result = enforce
          .isString()
          .startsWithUnderscore()
          .hasMinLength(3)
          .run('_ab');
        expect(result).toEqual({
          pass: true,
          type: '_ab',
        });
      });

      it('Should work with complex chaining scenarios', () => {
        expect(
          enforce.isString().hasMinLength(1).isAlphanumeric().run('test123'),
        ).toEqual({
          pass: true,
          type: 'test123',
        });

        expect(
          enforce.isString().hasMinLength(1).isAlphanumeric().run('test-123'),
        ).toEqual({
          pass: false,
          type: 'test-123',
        });
      });
    });

    describe('Error handling in lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          throwsError: () => {
            throw new Error('Custom validation error');
          },
          returnsUndefined: () => undefined,
          returnsNull: () => null,
          returnsInvalidObject: () => ({ invalid: true }),
        });
      });

      it('Should handle rules that throw errors', () => {
        expect(() => enforce.throwsError().run('test')).toThrow(
          'Custom validation error',
        );
      });

      it('Should handle rules that return undefined', () => {
        const result = enforce.returnsUndefined().run('test');
        expect(result).toEqual({
          pass: false,
          type: 'test',
        });
      });

      it('Should handle rules that return null', () => {
        const result = enforce.returnsNull().run('test');
        expect(result).toEqual({
          pass: false,
          type: 'test',
        });
      });

      it('Should handle rules that return invalid objects', () => {
        const result = enforce.returnsInvalidObject().run('test');
        expect(result).toEqual({
          pass: false,
          type: 'test',
        });
      });
    });

    describe('Type coercion and edge cases in lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          strictEquals: (value: any, expected: any) => value === expected,
          looseEquals: (value: any, expected: any) => value == expected,
          isTruthy: (value: any) => !!value,
          isFalsy: (value: any) => !value,
          typeCheck: (value: any, expectedType: string) =>
            typeof value === expectedType,
        });
      });

      it('Should handle strict equality comparisons', () => {
        expect(enforce.strictEquals(1).run(1)).toEqual({
          pass: true,
          type: 1,
        });
        expect(enforce.strictEquals(1).run('1')).toEqual({
          pass: false,
          type: '1',
        });
        expect(enforce.strictEquals(true).run(1)).toEqual({
          pass: false,
          type: 1,
        });
      });

      it('Should handle loose equality comparisons', () => {
        expect(enforce.looseEquals(1).run('1')).toEqual({
          pass: true,
          type: '1',
        });
        expect(enforce.looseEquals(true).run(1)).toEqual({
          pass: true,
          type: 1,
        });
        expect(enforce.looseEquals(null).run(undefined)).toEqual({
          pass: true,
          type: undefined,
        });
      });

      it('Should handle truthy/falsy checks', () => {
        // Truthy values
        expect(enforce.isTruthy().run(1)).toEqual({ pass: true, type: 1 });
        expect(enforce.isTruthy().run('text')).toEqual({
          pass: true,
          type: 'text',
        });
        expect(enforce.isTruthy().run(true)).toEqual({
          pass: true,
          type: true,
        });
        expect(enforce.isTruthy().run({})).toEqual({ pass: true, type: {} });
        expect(enforce.isTruthy().run([])).toEqual({ pass: true, type: [] });

        // Falsy values
        expect(enforce.isFalsy().run(0)).toEqual({ pass: true, type: 0 });
        expect(enforce.isFalsy().run('')).toEqual({ pass: true, type: '' });
        expect(enforce.isFalsy().run(false)).toEqual({
          pass: true,
          type: false,
        });
        expect(enforce.isFalsy().run(null)).toEqual({ pass: true, type: null });
        expect(enforce.isFalsy().run(undefined)).toEqual({
          pass: true,
          type: undefined,
        });
      });

      it('Should handle type checking', () => {
        expect(enforce.typeCheck('string').run('hello')).toEqual({
          pass: true,
          type: 'hello',
        });
        expect(enforce.typeCheck('number').run(42)).toEqual({
          pass: true,
          type: 42,
        });
        expect(enforce.typeCheck('boolean').run(true)).toEqual({
          pass: true,
          type: true,
        });
        expect(enforce.typeCheck('object').run({})).toEqual({
          pass: true,
          type: {},
        });
        expect(enforce.typeCheck('object').run(null)).toEqual({
          pass: true,
          type: null,
        });
        expect(enforce.typeCheck('undefined').run(undefined)).toEqual({
          pass: true,
          type: undefined,
        });

        // Type mismatches
        expect(enforce.typeCheck('string').run(42)).toEqual({
          pass: false,
          type: 42,
        });
        expect(enforce.typeCheck('number').run('hello')).toEqual({
          pass: false,
          type: 'hello',
        });
      });
    });

    describe('Complex scenarios with lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          isEmail: (value: string) =>
            /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
          isStrongPassword: (value: string) => {
            const hasLength = value.length >= 8;
            const hasUpper = /[A-Z]/.test(value);
            const hasLower = /[a-z]/.test(value);
            const hasNumber = /[0-9]/.test(value);
            const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(value);
            return hasLength && hasUpper && hasLower && hasNumber && hasSpecial;
          },
          isPhoneNumber: (value: string) =>
            /^\+?[\d\s\-\(\)]{10,}$/.test(value),
          isValidAge: (value: number) => value >= 0 && value <= 150,
          isValidDate: (value: Date) =>
            value instanceof Date && !isNaN(value.getTime()),
        });
      });

      it('Should work with email validation', () => {
        expect(enforce.isEmail().run('test@example.com')).toEqual({
          pass: true,
          type: 'test@example.com',
        });
        expect(enforce.isEmail().run('invalid-email')).toEqual({
          pass: false,
          type: 'invalid-email',
        });
      });

      it('Should work with password validation', () => {
        expect(enforce.isStrongPassword().run('StrongP@ss123')).toEqual({
          pass: true,
          type: 'StrongP@ss123',
        });
        expect(enforce.isStrongPassword().run('weak')).toEqual({
          pass: false,
          type: 'weak',
        });
      });

      it('Should work with phone number validation', () => {
        expect(enforce.isPhoneNumber().run('+1234567890')).toEqual({
          pass: true,
          type: '+1234567890',
        });
        expect(enforce.isPhoneNumber().run('123')).toEqual({
          pass: false,
          type: '123',
        });
      });

      it('Should work with age validation', () => {
        expect(enforce.isValidAge().run(25)).toEqual({
          pass: true,
          type: 25,
        });
        expect(enforce.isValidAge().run(-5)).toEqual({
          pass: false,
          type: -5,
        });
        expect(enforce.isValidAge().run(200)).toEqual({
          pass: false,
          type: 200,
        });
      });

      it('Should work with date validation', () => {
        const validDate = new Date('2023-01-01');
        const invalidDate = new Date('invalid');

        expect(enforce.isValidDate().run(validDate)).toEqual({
          pass: true,
          type: validDate,
        });
        expect(enforce.isValidDate().run(invalidDate)).toEqual({
          pass: false,
          type: invalidDate,
        });
      });
    });

    describe('Integration with schema rules in lazy API', () => {
      beforeEach(() => {
        enforce.extend({
          isEmail: (value: string) =>
            /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value),
          isAdult: (value: number) => value >= 18,
          hasValidPassword: (value: string) => {
            return (
              value.length >= 8 && /[A-Z]/.test(value) && /[0-9]/.test(value)
            );
          },
        });
      });

      it('Should work within shape() using lazy API', () => {
        const schema = enforce.shape({
          email: enforce.isString().isEmail(),
          age: enforce.isNumber().isAdult(),
          password: enforce.isString().hasValidPassword(),
        });

        const validData = {
          email: 'test@example.com',
          age: 25,
          password: 'SecurePass123',
        };

        const invalidData = {
          email: 'invalid-email',
          age: 16,
          password: 'weak',
        };

        expect(schema.run(validData)).toEqual({
          pass: true,
          type: validData,
        });
        const res = schema.run(invalidData);
        expect(res).toMatchObject({ pass: false, type: invalidData });
      });

      it('Should work within isArrayOf() using lazy API', () => {
        const emailArrayRule = enforce.isArrayOf(enforce.isString().isEmail());

        const validEmails = ['test@example.com', 'another@example.com'];
        const invalidEmails = ['test@example.com', 'invalid-email'];

        expect(emailArrayRule.run(validEmails)).toEqual({
          pass: true,
          type: validEmails,
        });
        const res2 = emailArrayRule.run(invalidEmails);
        expect(res2).toMatchObject({ pass: false });
      });

      it('Should work within optional() using lazy API', () => {
        const schema = enforce.shape({
          email: enforce.optional(enforce.isString().isEmail()),
          age: enforce.optional(enforce.isNumber().isAdult()),
        });

        expect(schema.run({ email: 'test@example.com', age: 25 })).toEqual({
          pass: true,
          type: { email: 'test@example.com', age: 25 },
        });
        expect(schema.run({ email: 'test@example.com' })).toEqual({
          pass: true,
          type: { email: 'test@example.com' },
        });
        expect(schema.run({})).toEqual({
          pass: true,
          type: {},
        });
      });
    });

    describe('Performance and edge cases in lazy API', () => {
      it('Should handle many custom rules with lazy API', () => {
        const rules: Record<string, () => boolean> = {};
        for (let i = 0; i < 50; i++) {
          rules[`rule${i}`] = () => true;
        }
        enforce.extend(rules);

        const result = enforce.rule0().rule25().rule49().run('test');
        expect(result).toEqual({
          pass: true,
          type: 'test',
        });
      });

      it('Should handle rules with many arguments in lazy API', () => {
        enforce.extend({
          sumEquals: (value: number, ...args: number[]) =>
            value === args.reduce((sum, n) => sum + n, 0),
          concatenatesTo: (value: string, ...parts: string[]) =>
            value === parts.join(''),
        });

        expect(enforce.sumEquals(1, 2, 3, 4).run(10)).toEqual({
          pass: true,
          type: 10,
        });
        expect(enforce.sumEquals(1, 2, 3).run(10)).toEqual({
          pass: false,
          type: 10,
        });

        expect(
          enforce.concatenatesTo('hello', 'world').run('helloworld'),
        ).toEqual({
          pass: true,
          type: 'helloworld',
        });
        expect(
          enforce.concatenatesTo('hello', 'world').run('hello world'),
        ).toEqual({
          pass: false,
          type: 'hello world',
        });
      });

      it('Should handle complex nested objects and arrays', () => {
        enforce.extend({
          hasProperty: (value: any, prop: string) =>
            value && value.hasOwnProperty(prop),
          arrayContains: (value: any[], item: any) =>
            value.some(v =>
              v && item && isObject(v) && isObject(item)
                ? JSON.stringify(v) === JSON.stringify(item)
                : v === item,
            ),
          objectDeepEquals: (value: any, expected: any) =>
            JSON.stringify(value) === JSON.stringify(expected),
        });

        const complexObject = {
          nested: { deep: { value: 'test' } },
          array: [1, 2, 3],
          mixed: [{ id: 1 }, { id: 2 }],
        };

        expect(enforce.hasProperty('nested').run(complexObject)).toEqual({
          pass: true,
          type: complexObject,
        });

        expect(
          enforce.arrayContains({ id: 1 }).run(complexObject.mixed),
        ).toEqual({
          pass: true,
          type: complexObject.mixed,
        });

        const expectedObject = { a: 1, b: 2 };
        expect(
          enforce.objectDeepEquals(expectedObject).run({ a: 1, b: 2 }),
        ).toEqual({
          pass: true,
          type: { a: 1, b: 2 },
        });
      });
    });
  });
});
