import _ from 'lodash';

import {
  AllFieldsEnum,
  StructureType,
} from '@/api/types';
import { toast } from '@/componentsRoot/ToastRoot';
import { Lang } from '@/lang/Lang';

import { colorNames } from './colorNames';

export const generateUUID = (length: number) => {
  var baseStr = '';
  if (length) {
    for (var i = 0; i < length; i++) baseStr += 'x';
  } else {
    baseStr = 'xxxxxxxxxx';
  }
  var d = new Date().getTime();
  var uuid = baseStr.replace(/[xy]/g, function (c) {
    var r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
  });
  return uuid;
};

export const getAlphaNumericRandom = (len: number): string => {
  if (len == undefined || len <= 0) {
    len = 1;
  }
  var characters =
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  var result = '';
  var iffirst = 0;
  for (var i = 0; i < len; i++) {
    if (i == 0) {
      iffirst = 10;
    } else {
      iffirst = 0;
    }
    result +=
      characters[Math.round(Math.random() * (characters.length - iffirst - 1))];
  }
  return result;
};


const fallbackCopyTextToClipboard = (text: string) => {
  var textArea = document.createElement('textarea');
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = '0';
  textArea.style.left = '0';
  textArea.style.position = 'fixed';

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    if (successful) {
      toast.success(Lang.key('copiedToClipboard'));
    }
  } catch (err) { }

  document.body.removeChild(textArea);
};
export const copyTextToClipboard = (text: string) => {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(
    function () {
      toast.success(Lang.key('copiedToClipboard'));
    },
    function (err) { }
  );
};


const parseHexToRgb = (hex: string): [number, number, number] | null => {
  let normalized = hex.trim().replace(/^#/, '');

  if (normalized.length === 8) {
    normalized = normalized.slice(0, 6);
  }

  if (normalized.length === 3) {
    normalized = normalized.split('').map((char) => char + char).join('');
  }

  if (!/^[0-9a-fA-F]{6}$/.test(normalized)) {
    return null;
  }

  return [
    parseInt(normalized.slice(0, 2), 16),
    parseInt(normalized.slice(2, 4), 16),
    parseInt(normalized.slice(4, 6), 16),
  ];
};

const colorRgbCache = colorNames.map((color) => ({
  ...color,
  rgb: parseHexToRgb(color.hex)!,
}));

export const getColorName = (hex?: string | null): string | null => {
  if (!hex) return null;

  const rgb = parseHexToRgb(hex);
  if (!rgb) return null;

  const normalizedHex = `#${rgb.map((channel) => channel.toString(16).padStart(2, '0')).join('')}`;
  const exactMatch = colorNames.find((color) => color.hex === normalizedHex);
  if (exactMatch) {
    if (Lang.getCurrentLang() == "ru") {
      return exactMatch.ru;
    } else {
      return exactMatch.en;
    }
  }

  let closest = colorRgbCache[0];
  let minDistance = Infinity;

  for (const color of colorRgbCache) {
    const [r, g, b] = rgb;
    const [cr, cg, cb] = color.rgb;
    const distance = Math.sqrt((r - cr) ** 2 + (g - cg) ** 2 + (b - cb) ** 2);

    if (distance < minDistance) {
      minDistance = distance;
      closest = color;
    }
  }

  if (Lang.getCurrentLang() == "ru") {
    return closest.ru;
  } else {
    return closest.en;
  }
};

export const hexToRgb = (hex: string) => {
  const bigint = parseInt(hex.substring(1), 16);
  const r = (bigint >> 16) & 255;
  const g = (bigint >> 8) & 255;
  const b = bigint & 255;

  return [r, g, b];
};


export const structureHaveType = (type: AllFieldsEnum, structure: StructureType | null): boolean => {

  if (!structure) return false;

  let have = false;

  _.map(structure.items, (field, key) => {
    if (field.type === type) {
      have = true;
    }
  });

  return have;


}



const getAllValues = (obj: any) => {
  let result: any[] = [];

  _.forOwn(obj, (value) => {
    if (_.isPlainObject(value)) {
      result = result.concat(getAllValues(value));
    } else if (_.isArray(value)) {
      value.forEach((item) => {
        if (_.isPlainObject(item)) {
          result = result.concat(getAllValues(item));
        } else {
          result.push(item);
        }
      });
    } else {
      result.push(value);
    }
  });

  return result;
}

export const isFilled = (values: any) => {

  if (!values) return false;

  let allValues = getAllValues(values);


  return allValues.filter((e) => e).length > 0;
}



export const getAnyGeoPointFormData = (
  data: any,
  structure: StructureType
): {
  lat: number;
  lng: number;
} | null => {
  let center: {
    lat: number;
    lng: number;
  } | null = null;

  _.map(structure.items, (val, key) => {
    if (center) return;

    if (val.type == 'geopoint' && data?.[key]?.lat && data?.[key]?.lng) {
      center = {
        lat: data?.[key]?.lat,
        lng: data?.[key]?.lng,
      };
    }
  });

  return center;
};








