import { Router } from '@angular/router';
import { ConsoleFormattedStream, INFO, createLogger as _createLogger, stdSerializers } from 'browser-bunyan';
import { jwtDecode } from 'jwt-decode';
import { BusinessListingCriteria, CommercialPropertyListingCriteria, JwtToken, KeycloakUser, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';

// export function createDefaultUser(email: string, firstname: string, lastname: string): User {
//   return {
//     id: undefined,
//     email,
//     firstname,
//     lastname,
//     phoneNumber: '',
//     description: '',
//     companyName: '',
//     companyOverview: '',
//     companyWebsite: '',
//     companyLocation: '',
//     offeredServices: '',
//     areasServed: [],
//     hasProfile: false,
//     hasCompanyLogo: false,
//     licensedIn: [],
//     gender: undefined,
//     customerType: undefined,
//     customerSubType: undefined,
//     created: new Date(),
//     updated: new Date(),
//   };
// }

// export function createDefaultCommercialPropertyListing(): CommercialPropertyListing {
//   return {
//     id: undefined,
//     serialId: undefined,
//     email: '',
//     type: null,
//     title: '',
//     description: '',
//     city: '',
//     state: '',
//     price: null,
//     favoritesForUser: [],
//     hideImage: false,
//     draft: false,
//     zipCode: null,
//     county: '',
//     imageOrder: [],
//     imagePath: '',
//     created: null,
//     updated: null,
//     visits: null,
//     lastVisit: null,
//     latitude: null,
//     longitude: null,
//     listingsCategory: 'commercialProperty',
//   };
// }
// export function createDefaultBusinessListing(): BusinessListing {
//   return {
//     id: undefined,
//     email: '',
//     type: null,
//     title: '',
//     description: '',
//     city: '',
//     state: '',
//     price: null,
//     favoritesForUser: [],
//     draft: false,
//     realEstateIncluded: false,
//     leasedLocation: false,
//     franchiseResale: false,
//     salesRevenue: null,
//     cashFlow: null,
//     supportAndTraining: '',
//     employees: null,
//     established: null,
//     internalListingNumber: null,
//     reasonForSale: '',
//     brokerLicencing: '',
//     internals: '',
//     created: null,
//     updated: null,
//     visits: null,
//     lastVisit: null,
//     latitude: null,
//     longitude: null,
//     listingsCategory: 'business',
//   };
// }
export function createEmptyBusinessListingCriteria(): BusinessListingCriteria {
  return {
    start: 0,
    length: 0,
    page: 0,
    state: '',
    city: '',
    types: [],
    prompt: '',
    criteriaType: 'business',
    county: '',
    minPrice: null,
    maxPrice: null,
    minRevenue: null,
    maxRevenue: null,
    minCashFlow: null,
    maxCashFlow: null,
    minNumberEmployees: null,
    maxNumberEmployees: null,
    establishedSince: null,
    establishedUntil: null,
    realEstateChecked: false,
    leasedLocation: false,
    franchiseResale: false,
    title: '',
    brokerName: '',
    searchType: 'exact',
    radius: null,
  };
}

export function createEmptyCommercialPropertyListingCriteria(): CommercialPropertyListingCriteria {
  return {
    start: 0,
    length: 0,
    page: 0,
    state: '',
    city: '',
    types: [],
    prompt: '',
    criteriaType: 'commercialProperty',
    county: '',
    minPrice: null,
    maxPrice: null,
    title: '',
    searchType: 'exact',
    radius: null,
  };
}

export function createEmptyUserListingCriteria(): UserListingCriteria {
  return {
    start: 0,
    length: 0,
    page: 0,
    city: '',
    types: [],
    prompt: '',
    criteriaType: 'broker',
    firstname: '',
    lastname: '',
    companyName: '',
    counties: [],
    state: '',
    searchType: 'exact',
    radius: null,
  };
}
export function createLogger(name: string, level: number = INFO, options: any = {}) {
  return _createLogger({
    name,
    streams: [{ level, stream: new ConsoleFormattedStream() }],
    serializers: stdSerializers,
    src: true,
    ...options,
  });
}
export function formatPhoneNumber(phone: string): string {
  const cleaned = ('' + phone).replace(/\D/g, '');
  const match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
  if (match) {
    return '(' + match[1] + ') ' + match[2] + '-' + match[3];
  }
  return phone;
}
// export const getSessionStorageHandler = function (path, value, previous, applyData) {
//   sessionStorage.setItem(applyData, JSON.stringify(this));
// };
export const getSessionStorageHandler = function (criteriaType, path, value, previous, applyData) {
  sessionStorage.setItem(`${criteriaType}_criteria`, JSON.stringify(this));
  console.log('Zusätzlicher Parameter:', criteriaType);
};
export const getSessionStorageHandlerWrapper = param => {
  return function (path, value, previous, applyData) {
    getSessionStorageHandler.call(this, param, path, value, previous, applyData);
  };
};

export function getCriteriaStateObject(criteriaType: 'business' | 'commercialProperty' | 'broker') {
  let initialState;
  if (criteriaType === 'business') {
    initialState = createEmptyBusinessListingCriteria();
  } else if (criteriaType === 'commercialProperty') {
    initialState = createEmptyCommercialPropertyListingCriteria();
  } else {
    initialState = createEmptyUserListingCriteria();
  }
  const storedState = sessionStorage.getItem(`${criteriaType}_criteria`);
  return storedState ? JSON.parse(storedState) : initialState;
}

export function routeListingWithState(router: Router, value: string, data: any) {
  if (value === 'business') {
    router.navigate(['createBusinessListing'], { state: { data } });
  } else {
    router.navigate(['createCommercialPropertyListing'], { state: { data } });
  }
}

export function map2User(jwt: string): KeycloakUser {
  if (jwt) {
    const token = jwtDecode<JwtToken>(jwt);
    return {
      id: token.user_id,
      firstName: token.given_name,
      lastName: token.family_name,
      email: token.email,
    };
  } else {
    return null;
  }
}
export function getImageDimensions(imageUrl: string): Promise<{ width: number; height: number }> {
  return new Promise(resolve => {
    const img = new Image();
    img.onload = () => {
      resolve({ width: img.width, height: img.height });
    };
    img.src = imageUrl;
  });
}

export function getDialogWidth(dimensions): string {
  const aspectRatio = dimensions.width / dimensions.height;
  let dialogWidth = '50vw'; // Standardbreite

  // Passen Sie die Breite basierend auf dem Seitenverhältnis an
  if (aspectRatio < 1) {
    dialogWidth = '30vw'; // Hochformat
  } else if (aspectRatio > 1) {
    dialogWidth = '50vw'; // Querformat
  }
  return dialogWidth;
}

import { initFlowbite } from 'flowbite';
import { Subject, concatMap, delay, of } from 'rxjs';

const flowbiteQueue = new Subject<() => void>();

flowbiteQueue.pipe(concatMap(item => of(item).pipe(delay(100)))).subscribe(x => {
  x();
});

export function Flowbite() {
  return function (target: any) {
    const originalOnInit = target.prototype.ngOnInit;
    target.prototype.ngOnInit = function () {
      if (originalOnInit) {
        originalOnInit.apply(this);
      }
      initFlowbiteFix();
    };
  };
}

export function initFlowbiteFix() {
  flowbiteQueue.next(() => {
    const elements = Array.from(document.querySelectorAll('*'));
    const flowbiteElements: Element[] = [];
    const initializedElements = Array.from(document.querySelectorAll('[flowbite-initialized]'));

    for (const element of elements) {
      const attributes = Array.from(element.attributes);

      for (const attribute of attributes) {
        if (attribute.name.startsWith('data-') && !initializedElements.includes(element)) {
          flowbiteElements.push(element);
          break;
        }
      }
    }

    for (const element of flowbiteElements) {
      element.setAttribute('flowbite-initialized', '');
    }
    initFlowbite();

    for (const element of flowbiteElements) {
      const attributes: { name: string; value: string }[] = Array.from(element.attributes);
      const dataAttributes = attributes.filter(attribute => attribute.name.startsWith('data-'));

      for (const attribute of dataAttributes) {
        element.setAttribute(attribute.name.replace('data-', 'fb-'), attribute.value);
        element.removeAttribute(attribute.name);
      }
    }
  });
}
// export function arraysEqual(arr1: any[], arr2: any[]): boolean {
//   if (arr1.length !== arr2.length) return false;
//   for (let i = 0; i < arr1.length; i++) {
//     if (arr1[i] !== arr2[i]) return false;
//   }
//   return true;
// }
export function compareObjects<T extends object>(obj1: T, obj2: T, ignoreProperties: (keyof T)[] = []): number {
  let differences = 0;
  const keys = Object.keys(obj1) as Array<keyof T>;

  for (const key of keys) {
    if (ignoreProperties.includes(key)) {
      continue; // Überspringe diese Eigenschaft, wenn sie in der Ignore-Liste ist
    }

    const value1 = obj1[key];
    const value2 = obj2[key];

    if (!areValuesEqual(value1, value2)) {
      differences++;
    }
  }

  return differences;
}

function areValuesEqual(value1: any, value2: any): boolean {
  if (Array.isArray(value1) || Array.isArray(value2)) {
    return arraysEqual(value1, value2);
  }

  if (typeof value1 === 'string' || typeof value2 === 'string') {
    return isEqualString(value1, value2);
  }

  if (typeof value1 === 'number' || typeof value2 === 'number') {
    return isEqualNumber(value1, value2);
  }

  if (typeof value1 === 'boolean' || typeof value2 === 'boolean') {
    return isEqualBoolean(value1, value2);
  }

  return value1 === value2;
}

function isEqualString(value1: any, value2: any): boolean {
  const isEmptyOrNullish1 = value1 === undefined || value1 === null || value1 === '';
  const isEmptyOrNullish2 = value2 === undefined || value2 === null || value2 === '';
  return (isEmptyOrNullish1 && isEmptyOrNullish2) || value1 === value2;
}

function isEqualNumber(value1: any, value2: any): boolean {
  const isZeroOrNullish1 = value1 === undefined || value1 === null || value1 === 0;
  const isZeroOrNullish2 = value2 === undefined || value2 === null || value2 === 0;
  return (isZeroOrNullish1 && isZeroOrNullish2) || value1 === value2;
}

function isEqualBoolean(value1: any, value2: any): boolean {
  const isFalseOrNullish1 = value1 === undefined || value1 === null || value1 === false;
  const isFalseOrNullish2 = value2 === undefined || value2 === null || value2 === false;
  return (isFalseOrNullish1 && isFalseOrNullish2) || value1 === value2;
}

function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined): boolean {
  if (arr1 === arr2) return true;
  if (arr1 == null || arr2 == null) return false;
  if (arr1.length !== arr2.length) return false;

  for (let i = 0; i < arr1.length; i++) {
    if (!areValuesEqual(arr1[i], arr2[i])) return false;
  }
  return true;
}
