import { ClasswiseClass } from "../services/classwiseClassesService";
import { ClassListingItem } from "@/src/lib/types/classes";
import { withCDN } from "@/src/lib/utils";
import { getFeeBasisPriceLabel } from "@/src/lib/utils/registrationPricing";

/**
 * Explicit "show everything" option shown at the top of each filter dropdown.
 * Selecting it clears that dimension's filter (same as the placeholder / X).
 */
export const ALL_FILTER_OPTION = "All";

/**
 * Brand colour and ribbon artwork per program/workshop, keyed by the normalized
 * name the class-wise API returns.
 *
 * Colour and ribbon live in one entry on purpose. They used to be two separate
 * maps, and anything present in only one of them rendered mismatched — the
 * workshops (Build Up, Golden Age…) were missing from both, so they fell back
 * to a blue heading over a teal Robo Toys ribbon.
 *
 * Values mirror the `borderColor` / `mobileRibbonImage` in programDetailService
 * and workshopDetailService, so a card matches its own detail page.
 */
const PROGRAM_THEMES: Record<string, { color: string; ribbon: string }> = {
  // Study programs — see programDetailService.ts
  smartivo: { color: "#0091D6", ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png") },
  algo_buddy: { color: "#0091D6", ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png") },
  big_builders: { color: "#F49800", ribbon: withCDN("/Workshop/bg%20%285%29.png") },
  bricks_challenge: { color: "#95C11F", ribbon: withCDN("/Workshop/bg%20%284%29.png") },
  algo_play: { color: "#9E358C", ribbon: withCDN("/programs-page/bg%20%287%29%20%281%29.png") },
  algo_c: { color: "#E89163", ribbon: withCDN("/programs-page/bg%20%286%29%20%281%29.png") },
  galileo_technic: { color: "#DD043E", ribbon: withCDN("/programs-page/bg%20%284%29%20%281%29.png") },
  robo_toys: { color: "#01A498", ribbon: withCDN("/programs-page/bg%20%285%29%20%281%29.png") },
  robotics: { color: "#0097DC", ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png") },
  robobricks: { color: "#0097DC", ribbon: withCDN("/programs-page/bg%20%283%29%20%282%29.png") },

  // Workshops — see workshopDetailService.ts
  build_up: { color: "#3A82C5", ribbon: withCDN("/Workshop/bg%20%286%29.png") },
  golden_age: { color: "#DDBD48", ribbon: withCDN("/Workshop/bg%20%288%29%20%281%29.png") },
  birthday_parties: { color: "#F49800", ribbon: withCDN("/Workshop/bg%20%285%29.png") },
  camps: { color: "#95C11F", ribbon: withCDN("/Workshop/bg%20%284%29.png") },
  summer_camp: { color: "#95C11F", ribbon: withCDN("/Workshop/bg%20%284%29.png") },
  coding_camps: { color: "#95C11F", ribbon: withCDN("/Workshop/bg%20%284%29.png") },
  mechanics_camps: { color: "#226B20", ribbon: withCDN("/Workshop/bg%20%284%29.png") },
  pro: { color: "#0B253C", ribbon: withCDN("/Workshop/bg%20%287%29.png") },
};

const DEFAULT_THEME = {
  color: "#0091D6",
  ribbon: withCDN("/programs-page/bg%20%285%29%20%281%29.png"),
};

/**
 * Our own branded logos, keyed by normalized program/workshop name (or slug).
 * Used instead of the class-wise API's `program.image`/`program_logo` so the
 * card shows the same logo we use across the rest of the site. Covers both
 * study programs (see ProgramCard) and workshops (see workshopMapper), because
 * the classes API returns both.
 */
const PROGRAM_LOGOS: Record<string, string> = {
  // Study programs
  smartivo: withCDN("/program-logo/logo_smartivo.svg"),
  algo_buddy: withCDN("/program-logo/logo_algo_buddy.svg"),
  algo_play: withCDN("/program-logo/logo_algo_play.svg"),
  algo_c: withCDN("/program-logo/logo_algo_c.svg"),
  big_builders: withCDN("/program-logo/logo_big_builders.svg"),
  bricks_challenge: withCDN("/program-logo/logo_bricks_chalenge.svg"),
  robo_toys: withCDN("/program-logo/logo_robo_toys.svg"),
  robobricks: withCDN("/program-logo/logo_robo_bricks.svg"),
  galileo_technic: withCDN("/program-logo/logo_galileo_technic.svg"),
  pro: withCDN("/program-logo/logo_pro.svg"),
  // Workshops
  build_up: withCDN("/workshop-logo/logo_build_up.svg"),
  golden_age: withCDN("/workshop-logo/logo_golden_age.svg"),
  summer_camp: withCDN("/workshop-logo/logo_camps.svg"),
  camps: withCDN("/workshop-logo/logo_camps.svg"),
  coding_camps: withCDN("/workshop-logo/logo_camps.svg"),
  mechanics_camps: withCDN("/workshop-logo/logo_camps.svg"),
  birthday_parties: withCDN("/workshop-logo/logo_birthday.svg"),
};

const DEFAULT_PROGRAM_LOGO = withCDN("/programs-page/AllPrograms/logo.svg");

/**
 * Resolve the theme for a program/workshop, by name or slug.
 * Falls back to blue + the Robo Toys ribbon when it isn't mapped.
 */
function getThemeForProgram(programName?: string, programSlug?: string) {
  const normalize = (v: string) => v.toLowerCase().replace(/[\s-]+/g, "_");
  const byName = programName ? PROGRAM_THEMES[normalize(programName)] : undefined;
  const bySlug = programSlug ? PROGRAM_THEMES[normalize(programSlug)] : undefined;
  return byName || bySlug || DEFAULT_THEME;
}

/**
 * Get our own branded logo for a program/workshop.
 * Resolves by program name or slug; never uses the class-wise API image.
 * Falls back to a default code logo when the program isn't mapped.
 */
function getLogoForProgram(programName?: string, programSlug?: string): string {
  const normalize = (v: string) => v.toLowerCase().replace(/[\s-]+/g, "_");
  const byName = programName ? PROGRAM_LOGOS[normalize(programName)] : undefined;
  const bySlug = programSlug ? PROGRAM_LOGOS[normalize(programSlug)] : undefined;
  return byName || bySlug || DEFAULT_PROGRAM_LOGO;
}

/**
 * Format age range (e.g., "6–10")
 */
function formatAgeRange(minAge: number, maxAge: number): string {
  return `${minAge}–${maxAge}`;
}

/**
 * Format price with currency symbol
 */
function formatPrice(value: string | number, currency?: any): string {
  const amount = typeof value === "string" ? value : value.toString();
  const symbol = currency?.symbol || "$";
  return `${symbol}${amount}`;
}

/**
 * Format date (e.g., "05/02/2026")
 */
function formatDate(dateString: string): string {
  if (!dateString) return "";
  const date = new Date(dateString);
  const day = String(date.getDate()).padStart(2, "0");
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const year = date.getFullYear();
  return `${day}/${month}/${year}`;
}

/**
 * Format time (e.g., "12:30 – 14:45")
 */
function formatTime(startTime: string, endTime: string): string {
  if (!startTime || !endTime) return "";
  // Handle cases where time includes AM/PM
  const start = startTime.includes("AM") || startTime.includes("PM")
    ? startTime
    : convertTo12Hour(startTime);
  const end = endTime.includes("AM") || endTime.includes("PM")
    ? endTime
    : convertTo12Hour(endTime);
  return `${start} – ${end}`;
}

/**
 * Convert 24-hour format to 12-hour format
 */
function convertTo12Hour(time24: string): string {
  const [hours, minutes] = time24.split(":").map(Number);
  const period = hours >= 12 ? "PM" : "AM";
  const hours12 = hours % 12 || 12;
  return `${hours12}:${String(minutes).padStart(2, "0")} ${period}`;
}

/**
 * Format study period (e.g., "05/02/2026 – 25/06/2026")
 */
function formatPeriod(startDate: string, endDate?: string): string {
  if (!startDate) return "";
  const formattedStart = formatDate(startDate);
  // For now, we don't have end_date in API, so just show start date or estimate
  if (!endDate) {
    return formattedStart; // Can extend based on number_of_lessons if needed
  }
  return `${formattedStart} – ${formatDate(endDate)}`;
}

/**
 * Extract map URL from latlng coordinates
 */
function getMapUrl(latlng?: string): string {
  if (!latlng) return "https://www.google.com/maps";
  const [lat, lng] = latlng.split(",");
  if (!lat || !lng) return "https://www.google.com/maps";
  return `https://www.google.com/maps?q=${lat},${lng}`;
}

/**
 * Transform a single Classwise class to ClassListing format
 */
export function transformClass(classItem: ClasswiseClass): ClassListingItem {
  const program = classItem.program || {};
  const location = classItem.p_o_s || {};
  const currency = classItem.currency;
  // One lookup for both the border/heading colour and the ribbon, so a card can
  // never end up with one program's colour over another's artwork.
  const theme = getThemeForProgram(program.name, program.slug);

  return {
    id: classItem.id as number,
    title: program.name || "Unknown Program",
    groupName: classItem.group_name || "",
    age: formatAgeRange(classItem.min_age, classItem.max_age),
    lessons: classItem.totalLessons || 0,
    price: formatPrice(classItem.value || "0", currency),
    period: formatPeriod(classItem.start_date),
    time: formatTime(classItem.start_time, classItem.end_time),
    days: classItem.frequency === "weekly" && Array.isArray(classItem.day) && classItem.day.length > 0 
      ? classItem.day.join(", ") 
      : classItem.frequency || "N/A",
    ribbon: theme.ribbon,
    iconSrc: getLogoForProgram(program.name, program.slug),
    address: location.location || location.name || "N/A",
    locationName: location.name || "N/A",
    mapUrl: getMapUrl(location.latlng),
    borderColor: theme.color,
    priceLabel: `${getFeeBasisPriceLabel(classItem.fee_basis)}:`,
  };
}

/**
 * Transform array of Classwise classes to ClassListing format
 */
export function transformClasses(classes: ClasswiseClass[]): ClassListingItem[] {
  return classes.map(transformClass);
}

/**
 * Build filter options from classes data
 */
export function buildFilterOptions(
  classes: ClassListingItem[]
): Record<string, string[]> {
  const options: Record<string, string[]> = {
    Age: ["Age"],
    Location: ["Location"],
    "Study Program": ["Study Program"],
    "Preferable days": ["Preferable days"],
  };

  // Collect unique age ranges
  const ageRanges = new Set<string>();
  classes.forEach((cls) => {
    ageRanges.add(cls.age);
  });
  options.Age.push(...Array.from(ageRanges).sort());

  // Collect unique location names (POS names like "paragon"), not full street addresses.
  const locations = new Set<string>();
  classes.forEach((cls) => {
    if (cls.locationName && cls.locationName !== "N/A") {
      locations.add(cls.locationName);
    }
  });
  options.Location.push(...Array.from(locations).sort());

  // Collect unique programs
  const programs = new Set<string>();
  classes.forEach((cls) => {
    programs.add(cls.title);
  });
  options["Study Program"].push(...Array.from(programs).sort());

  // Collect unique days/frequencies
  const days = new Set<string>();
  classes.forEach((cls) => {
    if (cls.days && cls.days !== "N/A") {
      days.add(cls.days);
    }
  });
  options["Preferable days"].push(...Array.from(days).sort());

  return options;
}

/**
 * Filter classes based on selected filter values
 */
export function filterClasses(
  classes: ClassListingItem[],
  filters: Record<string, string>
): ClassListingItem[] {
  // A filter is active only when a real value is chosen. The placeholder label
  // and the explicit "All" option both mean "no filter for this dimension".
  const isActive = (value: string | undefined, label: string) =>
    !!value && value !== label && value !== ALL_FILTER_OPTION;

  return classes.filter((cls) => {
    // Age filter: check if class age matches filter
    if (isActive(filters.Age, "Age") && cls.age !== filters.Age) return false;

    // Location filter — match on POS name (locationName), not full address.
    if (isActive(filters.Location, "Location") && cls.locationName !== filters.Location)
      return false;

    // Program filter
    if (
      isActive(filters["Study Program"], "Study Program") &&
      cls.title !== filters["Study Program"]
    )
      return false;

    // Days filter
    if (
      isActive(filters["Preferable days"], "Preferable days") &&
      cls.days !== filters["Preferable days"]
    )
      return false;

    return true;
  });
}
