import { clsx, type ClassValue } from "clsx";
import EventEmitter from "events";
import moment from "moment-jalaali";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export const formatNumber = (value: string | number) => {
  // if (!value) return "0";
  const numericValue = typeof value === "string" ? parseFloat(value) : value;
  if (isNaN(numericValue)) return "0";
  return new Intl.NumberFormat("fa-IR").format(numericValue);
};

export const formatCurrency = (amount: string | number) => {
  if (!amount) return "0 ریال";
  // Remove commas and convert to number
  const numericAmount =
    typeof amount === "string" ? parseFloat(amount.replace(/,/g, "")) : amount;
  if (isNaN(numericAmount)) return "0 ریال";
  return new Intl.NumberFormat("fa-IR").format(numericAmount) + " ریال";
};

/**
 * محاسبه دامنه nice numbers برای محور Y نمودارها
 * @param values آرایه از مقادیر داده‌ها
 * @param minValue حداقل مقدار (پیش‌فرض: 0 برای داده‌های درصدی)
 * @param marginPercent درصد حاشیه اضافی (پیش‌فرض: 5%)
 * @returns شیء شامل حداکثر nice، فاصله tick ها، و آرایه tick ها
 */
export function calculateNiceRange(
  values: number[],
  minValue: number = 0,
  marginPercent: number = 5
): {
  niceMax: number;
  tickInterval: number;
  ticks: number[];
} {
  if (values.length === 0) {
    return { niceMax: 100, tickInterval: 20, ticks: [0, 20, 40, 60, 80, 100] };
  }

  // پیدا کردن حداکثر مقدار در داده‌ها
  const dataMax = Math.max(...values);

  // اگر همه مقادیر صفر یا منفی هستند
  if (dataMax <= 0) {
    return { niceMax: 100, tickInterval: 20, ticks: [0, 20, 40, 60, 80, 100] };
  }

  // اضافه کردن حاشیه
  const maxWithMargin = dataMax * (1 + marginPercent / 100);

  // محاسبه nice upper limit
  const niceMax = calculateNiceNumber(maxWithMargin, true);

  // محاسبه فاصله مناسب tick ها بر اساس niceMax
  const range = niceMax - minValue;
  const targetTicks = 5; // هدف: 5 tick
  const roughTickInterval = range / (targetTicks - 1);
  const niceTickInterval = calculateNiceNumber(roughTickInterval, false);

  // ایجاد آرایه tick ها
  const ticks: number[] = [];
  for (let i = minValue; i <= niceMax; i += niceTickInterval) {
    ticks.push(Math.round(i));
  }

  // اطمینان از اینکه niceMax در آرایه tick ها باشد
  if (ticks[ticks.length - 1] !== niceMax) {
    ticks.push(niceMax);
  }

  return {
    niceMax,
    tickInterval: niceTickInterval,
    ticks,
  };
}

/**
 * محاسبه عدد nice (گرد و خوانا) بر اساس الگوریتم nice numbers
 * @param value مقدار ورودی
 * @param round آیا به سمت بالا گرد شود یا نه
 * @returns عدد nice
 */
function calculateNiceNumber(value: number, round: boolean): number {
  if (value <= 0) return 0;

  // پیدا کردن قدرت 10
  const exponent = Math.floor(Math.log10(value));
  const fraction = value / Math.pow(10, exponent);

  let niceFraction: number;

  if (round) {
    // برای حداکثر: به سمت بالا گرد می‌کنیم با دقت بیشتر
    if (fraction <= 1.0) niceFraction = 1;
    else if (fraction <= 2.0) niceFraction = 2;
    else if (fraction <= 2.5) niceFraction = 2.5;
    else if (fraction <= 5.0) niceFraction = 5;
    else if (fraction <= 7.5) niceFraction = 7.5;
    else niceFraction = 10;
  } else {
    // برای فاصله tick ها: اعداد ساده‌تر
    if (fraction <= 1.0) niceFraction = 1;
    else if (fraction <= 2.0) niceFraction = 2;
    else if (fraction <= 5.0) niceFraction = 5;
    else niceFraction = 10;
  }

  return niceFraction * Math.pow(10, exponent);
}

export const handleDataValue = (val: any): any => {
  moment.loadPersian({ usePersianDigits: true });
  if (val == null) return val;
  if (
    typeof val === "string" &&
    /^\d{4}[-/]\d{2}[-/]\d{2}( \d{2}:\d{2}(:\d{2})?)?$/.test(val)
  ) {
    return moment(val, "YYYY-MM-DD HH:mm:ss").format("YYYY/MM/DD");
  }
  if (
    typeof val === "number" ||
    (typeof val === "string" && /^-?\d+$/.test(val))
  ) {
    return val.toString().replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[+d]);
  }
  return val;
};

export const EventBus = new EventEmitter();
