import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { Active, Over } from '@dnd-kit/core';
import noImage from "@/assets/images/noImage.png";
import { BUCKET_ROOT } from '@/utils/apis';

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

export function hasDraggableData<T extends Active | Over>(
  entry: T | null | undefined
): entry is T & {
} {
  if (!entry) {
    return false;
  }

  const data = entry.data.current;

  if (data?.type === 'Column' || data?.type === 'Task') {
    return true;
  }

  return false;
}

export function formatBytes(
  bytes: number,
  opts: {
    decimals?: number;
    sizeType?: 'accurate' | 'normal';
  } = {}
) {
  const { decimals = 0, sizeType = 'normal' } = opts;

  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const accurateSizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB'];
  if (bytes === 0) return '0 Byte';
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
  return `${(bytes / Math.pow(1024, i)).toFixed(decimals)} ${sizeType === 'accurate' ? accurateSizes[i] ?? 'Bytest' : sizes[i] ?? 'Bytes'
    }`;
}

/**
 * Get today's closing time from working schedule (with UTC conversion)
 * Converts UTC times to local time for display
 */
export const getTodayClosingTime = (schedule: any) => {
  // Get today id (1 = Monday, 7 = Sunday)
  const todayId = (((new Date().getDay() + 6) % 7) + 1).toString();

  const today = schedule?.find((day: any) => day.day_id === todayId);

  if (!today) return "Closed Today";

  // If is_24_hrs is true but timing is empty, it means closed/disabled
  if (today.is_24_hrs && (!today.timing || today.timing.length === 0)) {
    return "Closed Today";
  }

  if (today.is_24_hrs) return "Open 24 hours";

  const timings = today.timing;

  if (!timings || timings.length === 0) return "No hours available";

  // Map all slots to local time
  const formattedSlots = timings.map((slot: any) => {
    const startTime = new Date(slot.start_time);
    const endTime = new Date(slot.end_time);

    const formattedStartTime = startTime.toLocaleTimeString([], {
      hour: "2-digit",
      minute: "2-digit",
      hour12: true,
    });

    const formattedEndTime = endTime.toLocaleTimeString([], {
      hour: "2-digit",
      minute: "2-digit",
      hour12: true,
    });

    return `${formattedStartTime} - ${formattedEndTime}`;
  });

  // Join multiple slots with comma
  return formattedSlots.join(", ");
};


export function isWithinOperatingHours(timeRange: string): boolean {
  if (!timeRange) return false;

  if (timeRange.toLowerCase() === "open 24 hours") {
    return true;
  }

  if (
    timeRange.toLowerCase() === "closed today" ||
    timeRange.toLowerCase() === "no hours available"
  ) {
    return false;
  }

  const timeSlots = timeRange.split(",").map(s => s.trim());

  const now = new Date();

  const parseTime = (timeStr: string): Date => {
    const [time, modifier] = timeStr.split(" ");
    let [hours, minutes] = time.split(":").map(Number);

    if (modifier.toLowerCase() === "pm" && hours < 12) {
      hours += 12;
    }
    if (modifier.toLowerCase() === "am" && hours === 12) {
      hours = 0;
    }

    const result = new Date();
    result.setHours(hours, minutes, 0, 0);
    return result;
  };

  // Check if current time falls within any of the time slots
  for (const slot of timeSlots) {
    const [openTimeStr, closeTimeStr] = slot.split("-").map(s => s.trim());
    if (!openTimeStr || !closeTimeStr) continue;

    const openTime = parseTime(openTimeStr);
    const closeTime = parseTime(closeTimeStr);

    if (now >= openTime && now <= closeTime) {
      return true;
    }
  }

  return false;
}

export const isItemAvailableNow = (itemTiming: any[]): boolean => {
  if (!itemTiming || itemTiming.length === 0) {
    return true;
  }

  const now = new Date();
  const todayId = (((now.getDay() + 6) % 7) + 1).toString();

  const todaySchedule = itemTiming.find((timing: any) => timing.day_id === todayId);

  if (!todaySchedule) {
    return false;
  }

  const startTime = new Date(todaySchedule.start_time);
  const endTime = new Date(todaySchedule.end_time);

  const currentTime = new Date();
  const compareStart = new Date(
    currentTime.getFullYear(),
    currentTime.getMonth(),
    currentTime.getDate(),
    startTime.getHours(),
    startTime.getMinutes(),
    startTime.getSeconds()
  );

  const compareEnd = new Date(
    currentTime.getFullYear(),
    currentTime.getMonth(),
    currentTime.getDate(),
    endTime.getHours(),
    endTime.getMinutes(),
    endTime.getSeconds()
  );

  return currentTime >= compareStart && currentTime <= compareEnd;
};

export const getItemAvailabilityTime = (itemTiming: any[]): string | null => {
  if (!itemTiming || itemTiming.length === 0) {
    return null; // No timing restriction
  }

  const now = new Date();
  const todayId = (((now.getDay() + 6) % 7) + 1).toString();

  // Find today's schedule for this item
  const todaySchedule = itemTiming.find((timing: any) => timing.day_id === todayId);

  if (!todaySchedule) {
    return "Not available today";
  }

  // Convert UTC to local time
  const startTime = new Date(todaySchedule.start_time);
  const endTime = new Date(todaySchedule.end_time);

  const formattedStartTime = startTime.toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
    hour12: true,
  });

  const formattedEndTime = endTime.toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
    hour12: true,
  });

  return `${formattedStartTime} - ${formattedEndTime}`;
};

export const calculateActiveDuration = (createdAt: string | number | Date) => {
  if (!createdAt) return 'N/A';

  const createdDate = new Date(createdAt);
  const currentDate = new Date();

  const diffInMs = currentDate.getTime() - createdDate.getTime();
  const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));

  if (diffInDays < 1) return 'Less than a day';
  if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''}`;

  const diffInMonths = Math.floor(diffInDays / 30);
  if (diffInMonths < 12) return `${diffInMonths} month${diffInMonths > 1 ? 's' : ''}`;

  const diffInYears = Math.floor(diffInMonths / 12);
  return `${diffInYears} year${diffInYears > 1 ? 's' : ''}`;
};

export const getValidImage = (image?: string) => {
  if (!image || image.trim() === "" || image === BUCKET_ROOT) {
    return noImage.src;
  }

  if (image.startsWith("http") || image.startsWith("https")) {
    return image;
  }
  return `${BUCKET_ROOT}${image}`;
};

export const getDayName = (date = new Date()) =>
  date.toLocaleDateString("en-US", { weekday: "long" });

export const formatTime = (timeString: string) => {
  if (!timeString) return "";
  const time = new Date(timeString);
  return time.toLocaleTimeString("en-US", {
    hour: "numeric",
    minute: "2-digit",
    hour12: true,
  });
};

export const normalizeTime = (timeStr: string) => {
  if (!timeStr) return null;

  const time = new Date(timeStr);
  if (isNaN(time.getTime())) return null;

  const now = new Date();
  return new Date(
    now.getFullYear(),
    now.getMonth(),
    now.getDate(),
    time.getHours(),
    time.getMinutes(),
    time.getSeconds()
  );
};

export const getTodayStatus = (workingDays: any[]) => {
  if (!workingDays) return { isOpen: false, nextOpen: null, closeAt: null };

  const today = new Date().toLocaleDateString("en-US", { weekday: "long" });
  const now = new Date();

  const todaySchedule = workingDays.find((d) => d.day === today);
  if (!todaySchedule || !todaySchedule.timing?.length) {
    return { isOpen: false, nextOpen: null, closeAt: null };
  }

  for (let slot of todaySchedule.timing) {
    const start = normalizeTime(slot.start_time);
    const end = normalizeTime(slot.end_time);

    if (!start || !end) continue;

    if (now >= start && now <= end) {
      return { isOpen: true, closeAt: end, nextOpen: null };
    }
    if (now < start) {
      return { isOpen: false, nextOpen: start, closeAt: null };
    }
  }

  return { isOpen: false, nextOpen: null, closeAt: null };
};

export const formatTimeToUTC = (time: string): string => {
  const dateTimeString = `2024-01-01T${time}:00.000`;
  const localDate = new Date(dateTimeString);
  return localDate.toISOString();
};

export const formatUTCToLocalTime = (utcDateTime: string): string => {
  const date = new Date(utcDateTime);
  const hours = date.getHours().toString().padStart(2, '0');
  const minutes = date.getMinutes().toString().padStart(2, '0');
  return `${hours}:${minutes}`;
};

export const formatDateStringToUTC = (dateString: string): string => {
  const [year, month, day] = dateString.split("-").map(Number);
  // Create date in UTC to avoid timezone shifts
  const utcDate = new Date(Date.UTC(year, month - 1, day));
  return utcDate.toISOString();
};

export const formatUTCToDateString = (utcDateTime: string): string => {
  const date = new Date(utcDateTime);
  const year = date.getUTCFullYear();
  const month = (date.getUTCMonth() + 1).toString().padStart(2, "0");
  const day = date.getUTCDate().toString().padStart(2, "0");
  return `${year}-${month}-${day}`;
};

export const formatDateTimeToUTC = (dateTime: string): string => {
  const localDate = new Date(dateTime);
  return localDate.toISOString();
};

export const currency = '$'

export function maskPhoneNumber(phone: string | null) {
  if (!phone || phone.length < 3) return phone;
  const firstTwo = phone.slice(0, 2);
  const lastOne = phone.slice(-1);
  return `${firstTwo}*******${lastOne}`;
}

export function maskEmail(email: string | null) {
  if (!email) return "";
  const [name, domain] = email.split("@");
  if (name.length <= 2) return `***@${domain}`;
  const firstTwo = name.slice(0, 2);
  return `${firstTwo}***@${domain}`;
}

export const getTodayTimings = (workingDays: any[]) => {
  if (!workingDays) return ["Hours not available"];
  const todayId = (((new Date().getDay() + 6) % 7) + 1).toString();
  const today = workingDays.find((day: any) => day.day_id === todayId);

  if (!today) return ["Closed Today"];
  if (today.is_24_hrs && (!today.timing || today.timing.length === 0)) {
    return ["Closed Today"];
  }
  if (today.is_24_hrs) return ["Open 24 hours"];
  if (!today.timing || today.timing.length === 0) return ["No hours available"];

  return today.timing.map((slot: any) => {
    const startTime = new Date(slot.start_time);
    const endTime = new Date(slot.end_time);
    return `${startTime.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: true })} - ${endTime.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: true })}`;
  });
};

export const formatOrderCount = (count: any) => {
  if (count < 10) return null; // hide below 10
  const thresholds = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000];

  // Find the highest threshold less than or equal to count
  const threshold = thresholds.reduce((acc, val) => (count >= val ? val : acc), 10);
  return `${threshold}+`;
};