import { Router } from '@angular/router';
import { createLogger as _createLogger } from './logger';
import { jwtDecode } from 'jwt-decode';
import onChange from 'on-change';
import { SortByOptions, User } from '../../../../bizmatch-server/src/models/db.model';
import { BusinessListingCriteria, CommercialPropertyListingCriteria, JwtToken, KeycloakUser, MailInfo, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../environments/environment';

export function createEmptyBusinessListingCriteria(): BusinessListingCriteria {
  return {
    start: 0,
    length: 0,
    page: 0,
    state: null,
    city: null,
    types: [],
    prompt: '',
    criteriaType: 'businessListings',
    minPrice: null,
    maxPrice: null,
    minRevenue: null,
    maxRevenue: null,
    minCashFlow: null,
    maxCashFlow: null,
    minNumberEmployees: null,
    maxNumberEmployees: null,
    establishedMin: null,
    realEstateChecked: false,
    leasedLocation: false,
    franchiseResale: false,
    title: '',
    email: '',
    brokerName: '',
    searchType: 'exact',
    radius: null,
  };
}

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

export function createEmptyUserListingCriteria(): UserListingCriteria {
  return {
    start: 0,
    length: 12,
    page: 1,
    city: null,
    types: [],
    prompt: '',
    criteriaType: 'brokerListings',
    brokerName: '',
    companyName: '',
    counties: [],
    state: '',
    searchType: 'exact',
    radius: null,
  };
}
export function resetBusinessListingCriteria(criteria: BusinessListingCriteria) {
  criteria.start = 0;
  criteria.length = 0;
  criteria.page = 0;
  criteria.state = null;
  criteria.city = null;
  criteria.types = [];
  criteria.prompt = '';
  criteria.criteriaType = 'businessListings';
  criteria.minPrice = null;
  criteria.maxPrice = null;
  criteria.minRevenue = null;
  criteria.maxRevenue = null;
  criteria.minCashFlow = null;
  criteria.maxCashFlow = null;
  criteria.minNumberEmployees = null;
  criteria.maxNumberEmployees = null;
  criteria.establishedMin = null;
  criteria.realEstateChecked = false;
  criteria.leasedLocation = false;
  criteria.franchiseResale = false;
  criteria.title = '';
  criteria.brokerName = '';
  criteria.searchType = 'exact';
  criteria.radius = null;
}

export function resetCommercialPropertyListingCriteria(criteria: CommercialPropertyListingCriteria) {
  criteria.start = 0;
  criteria.length = 0;
  criteria.page = 0;
  criteria.state = null;
  criteria.city = null;
  criteria.types = [];
  criteria.prompt = '';
  criteria.criteriaType = 'commercialPropertyListings';
  criteria.minPrice = null;
  criteria.maxPrice = null;
  criteria.title = '';
  criteria.searchType = 'exact';
  criteria.radius = null;
}

export function resetUserListingCriteria(criteria: UserListingCriteria) {
  criteria.start = 0;
  criteria.length = 0;
  criteria.page = 0;
  criteria.city = null;
  criteria.types = [];
  criteria.prompt = '';
  criteria.criteriaType = 'brokerListings';
  criteria.brokerName = '';
  criteria.companyName = '';
  criteria.counties = [];
  criteria.state = '';
  criteria.searchType = 'exact';
  criteria.radius = null;
}

export function createMailInfo(user?: User): MailInfo {
  return {
    sender: user
      ? { name: `${user.firstname} ${user.lastname}`, email: user.email, phoneNumber: user.phoneNumber, state: user.location?.state, comments: null }
      : { name: '', email: '', phoneNumber: '', state: '', comments: '' },
    email: null,
    url: environment.mailinfoUrl,
    listing: null,
  };
}
export function createLogger(name: string, level?: number, options?: any) {
  return _createLogger(name);
}
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 (criteriaType, path, value, previous, applyData) {
  if (typeof sessionStorage !== 'undefined') {
    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 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 | null): 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 => {
    // Only use Image in browser context
    if (typeof Image === 'undefined') {
      resolve({ width: 0, height: 0 });
      return;
    }
    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;
}

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;
}
export function assignProperties(target, source) {
  for (let key in source) {
    if (source.hasOwnProperty(key)) {
      target[key] = source[key];
    }
  }
  return target;
}
export function checkAndUpdate(changed: boolean, condition: boolean, assignment: () => any): boolean {
  if (condition) {
    assignment();
  }
  return changed || condition;
}
export function removeSortByStorage() {
  if (typeof sessionStorage !== 'undefined') {
    sessionStorage.removeItem('businessSortBy');
    sessionStorage.removeItem('commercialSortBy');
    sessionStorage.removeItem('professionalsSortBy');
  }
}
// -----------------------------
// Criteria Proxy
// -----------------------------
export function getCriteriaStateObject(criteriaType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings') {
  let initialState;
  if (criteriaType === 'businessListings') {
    initialState = createEmptyBusinessListingCriteria();
  } else if (criteriaType === 'commercialPropertyListings') {
    initialState = createEmptyCommercialPropertyListingCriteria();
  } else {
    initialState = createEmptyUserListingCriteria();
  }
  if (typeof sessionStorage !== 'undefined') {
    const storedState = sessionStorage.getItem(`${criteriaType}`);
    return storedState ? JSON.parse(storedState) : initialState;
  }
  return initialState;
}
export function getCriteriaProxy(path: string, component: any): BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria {
  if ('businessListings' === path) {
    return createEnhancedProxy(getCriteriaStateObject('businessListings'), component);
  } else if ('commercialPropertyListings' === path) {
    return createEnhancedProxy(getCriteriaStateObject('commercialPropertyListings'), component);
  } else if ('brokerListings' === path) {
    return createEnhancedProxy(getCriteriaStateObject('brokerListings'), component);
  } else {
    return undefined;
  }
}
export function createEnhancedProxy(obj: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria, component: any) {
  const sessionStorageHandler = function (path, value, previous, applyData) {
    if (typeof sessionStorage !== 'undefined') {
      sessionStorage.setItem(`${obj.criteriaType}`, JSON.stringify(this));
    }
  };

  return onChange(obj, function (path, value, previous, applyData) {
    // Call the original sessionStorageHandler
    sessionStorageHandler.call(this, path, value, previous, applyData);

    // Notify about the criteria change using the component's context
    if (component.criteriaChangeService) {
      component.criteriaChangeService.notifyCriteriaChange();
    }
  });
}
export function getCriteriaByListingCategory(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
  if (typeof sessionStorage === 'undefined') return null;

  const storedState =
    listingsCategory === 'business'
      ? sessionStorage.getItem('businessListings')
      : listingsCategory === 'commercialProperty'
        ? sessionStorage.getItem('commercialPropertyListings')
        : sessionStorage.getItem('brokerListings');
  return storedState ? JSON.parse(storedState) : null;
}

export function getSortByListingCategory(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
  if (typeof sessionStorage === 'undefined') return null;

  const storedSortBy =
    listingsCategory === 'business' ? sessionStorage.getItem('businessSortBy') : listingsCategory === 'commercialProperty' ? sessionStorage.getItem('commercialSortBy') : sessionStorage.getItem('professionalsSortBy');
  const sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
  return sortBy;
}
