import { useCallback, useEffect, useMemo, useState } from 'react';

import { ZodError } from 'zod';

import { isArray, isNullOrUndefined, isObject } from '@/utils/validator';

export const hasAnyTrue = (obj: { [key: string]: boolean }): boolean => {
  for (const key in obj) {
    if (obj.hasOwnProperty(key) && obj[key] === true) {
      return true;
    }
  }
  return false;
};

export function getDifferences(
  obj1: object,
  obj2: object
): { [key: string]: boolean } {
  // Create an empty object to store the differences
  const result: { [key: string]: boolean } = {};
  // Recursive function to compare values
  function compareValues(value1: any, value2: any): boolean {
    // If both values are objects, compare their properties recursively
    if (isObject(value1) && isObject(value2)) {
      return hasAnyTrue(getDifferences(value1, value2));
    }
    // If both values are arrays, compare their elements
    if (isArray(value1) && isArray(value2)) {
      //console.log(`Check is array: ${JSON.stringify(value1)} =?= ${JSON.stringify(value2)}`);
      if (value1.length !== value2.length) {
        return true;
      }
      for (let i = 0; i < value1.length; i++) {
        if (compareValues(value1[i], value2[i])) {
          return true;
        }
      }
      return false;
    }
    // Otherwise, compare the values directly
    //console.log(`compare : ${value1} =?= ${value2}`);
    return value1 !== value2;
  }

  // Get all keys from both objects
  const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);

  // Iterate over all keys
  for (const key of allKeys) {
    if (compareValues(obj1[key], obj2[key])) {
      result[key] = true;
    } else {
      result[key] = false;
    }
  }
  return result;
}

export const zodResolver = (zodModel) => {
  return (data: any) => {
    try {
      console.log(`check resolver of: ${JSON.stringify(data, null, 2)}`);
      zodModel.parse(data);
      return {};
    } catch (error) {
      if (error instanceof ZodError) {
        console.log(
          `catch error with resolver: ${JSON.stringify(error, null, 2)}`
        );
        const formattedErrors = error.issues.reduce(
          (acc, issue) => {
            if (issue.path.length > 0) {
              acc[issue.path[0]] = issue.message;
            }
            return acc;
          },
          {} as Record<string, string>
        );
        console.log(`get errors: ${JSON.stringify(formattedErrors, null, 2)}`);
        return formattedErrors;
      }
      // prevent zod error
      throw error;
    }
  };
};
