// Constants for Bangla calendar
export const BANGLA_MONTHS = [
  "বৈশাখ", // Boishakh
  "জ্যৈষ্ঠ", // Jyoishtho
  "আষাঢ়", // Asharh
  "শ্রাবণ", // Shrabon
  "ভাদ্র", // Bhadro
  "আশ্বিন", // Ashwin
  "কার্তিক", // Kartik
  "অগ্রহায়ণ", // Ogrohayon
  "পৌষ", // Poush
  "মাঘ", // Magh
  "ফাল্গুন", // Falgun
  "চৈত্র", // Choitro
]

export const BANGLA_SEASONS = [
  "গ্রীষ্ম", // Grishmo (Summer)
  "বর্ষা", // Borsha (Rainy)
  "শরৎ", // Shorot (Autumn)
  "হেমন্ত", // Hemonto (Late Autumn)
  "শীত", // Sheet (Winter)
  "বসন্ত", // Boshonto (Spring)
]

export const BANGLA_WEEKDAYS = [
  "রবিবার", // Sunday
  "সোমবার", // Monday
  "মঙ্গলবার", // Tuesday
  "বুধবার", // Wednesday
  "বৃহস্পতিবার", // Thursday
  "শুক্রবার", // Friday
  "শনিবার", // Saturday
]

// Bangla date structure
export interface BanglaDate {
  year: number
  month: number // 1-12
  date: number // 1-31
  monthName: string
  season: string
}

/**
 * Determines if the given Bangla year is a leap year
 * @param year Bangla year
 * @returns boolean indicating if it's a leap year
 */
export const isBanglaLeapYear = (year: number): boolean => {
  // Convert Bangla year to Gregorian year (approximate)
  const gregorianYear = year - 593

  // Gregorian leap year calculation
  return (gregorianYear % 4 === 0 && gregorianYear % 100 !== 0) || gregorianYear % 400 === 0
}

/**
 * Get the number of days in a Bangla month
 * @param month Bangla month (1-12)
 * @param year Bangla year
 * @returns number of days in the month
 */
export const getDaysInBanglaMonth = (month: number, year: number): number => {
  // Bangla months have either 30 or 31 days
  // Falgun (11th month) has 29 days in non-leap years and 30 days in leap years
  if (month === 11) {
    return isBanglaLeapYear(year) ? 30 : 29
  }

  // Chaitra (12th month) has 30 days
  if (month === 12) {
    return 30
  }

  // Other months alternate between 31 and 30 days
  return month % 2 === 1 ? 31 : 30
}

/**
 * Convert Gregorian date to Bangla date
 * @param date Gregorian date
 * @returns BanglaDate object
 */
export const convertGregorianToBangla = (date: Date): BanglaDate => {
  const gregorianDate = date.getDate()
  const gregorianMonth = date.getMonth() + 1 // 1-12
  const gregorianYear = date.getFullYear()

  let banglaDate: number
  let banglaMonth: number
  let banglaYear: number

  // Bangla new year starts around April 14
  // This is a simplified calculation - a more accurate one would account for leap years
  if (gregorianMonth < 4 || (gregorianMonth === 4 && gregorianDate < 14)) {
    // Jan to mid-April: Bangla year is Gregorian year - 594
    banglaYear = gregorianYear - 594
  } else {
    // Mid-April to Dec: Bangla year is Gregorian year - 593
    banglaYear = gregorianYear - 593
  }

  // Approximate mapping of Gregorian to Bangla dates
  // This is a simplified version - a more accurate version would use astronomical calculations
  if (gregorianMonth === 4) {
    // April
    if (gregorianDate < 14) {
      banglaMonth = 12 // Chaitra
      banglaDate = gregorianDate + 17
    } else {
      banglaMonth = 1 // Boishakh
      banglaDate = gregorianDate - 13
    }
  } else if (gregorianMonth === 5) {
    // May
    if (gregorianDate < 15) {
      banglaMonth = 1 // Boishakh
      banglaDate = gregorianDate + 17
    } else {
      banglaMonth = 2 // Jyoishtho
      banglaDate = gregorianDate - 14
    }
  } else if (gregorianMonth === 6) {
    // June
    if (gregorianDate < 15) {
      banglaMonth = 2 // Jyoishtho
      banglaDate = gregorianDate + 17
    } else {
      banglaMonth = 3 // Asharh
      banglaDate = gregorianDate - 14
    }
  } else if (gregorianMonth === 7) {
    // July
    if (gregorianDate < 16) {
      banglaMonth = 3 // Asharh
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 4 // Shrabon
      banglaDate = gregorianDate - 15
    }
  } else if (gregorianMonth === 8) {
    // August
    if (gregorianDate < 16) {
      banglaMonth = 4 // Shrabon
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 5 // Bhadro
      banglaDate = gregorianDate - 15
    }
  } else if (gregorianMonth === 9) {
    // September
    if (gregorianDate < 16) {
      banglaMonth = 5 // Bhadro
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 6 // Ashwin
      banglaDate = gregorianDate - 15
    }
  } else if (gregorianMonth === 10) {
    // October
    if (gregorianDate < 16) {
      banglaMonth = 6 // Ashwin
      banglaDate = gregorianDate + 15
    } else {
      banglaMonth = 7 // Kartik
      banglaDate = gregorianDate - 15
    }
  } else if (gregorianMonth === 11) {
    // November
    if (gregorianDate < 15) {
      banglaMonth = 7 // Kartik
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 8 // Ogrohayon
      banglaDate = gregorianDate - 14
    }
  } else if (gregorianMonth === 12) {
    // December
    if (gregorianDate < 15) {
      banglaMonth = 8 // Ogrohayon
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 9 // Poush
      banglaDate = gregorianDate - 14
    }
  } else if (gregorianMonth === 1) {
    // January
    if (gregorianDate < 14) {
      banglaMonth = 9 // Poush
      banglaDate = gregorianDate + 17
    } else {
      banglaMonth = 10 // Magh
      banglaDate = gregorianDate - 13
    }
  } else if (gregorianMonth === 2) {
    // February
    if (gregorianDate < 13) {
      banglaMonth = 10 // Magh
      banglaDate = gregorianDate + 18
    } else {
      banglaMonth = 11 // Falgun
      banglaDate = gregorianDate - 12
    }
  } else {
    // March
    if (gregorianDate < 15) {
      banglaMonth = 11 // Falgun
      banglaDate = gregorianDate + 16
    } else {
      banglaMonth = 12 // Chaitra
      banglaDate = gregorianDate - 14
    }
  }

  // Get season based on Bangla month
  let seasonIndex = Math.floor((banglaMonth - 1) / 2)
  if (seasonIndex > 5) seasonIndex = 5

  return {
    year: banglaYear,
    month: banglaMonth,
    date: banglaDate,
    monthName: BANGLA_MONTHS[banglaMonth - 1],
    season: BANGLA_SEASONS[seasonIndex],
  }
}

/**
 * Convert Bangla date to Gregorian date
 * @param banglaDate Bangla date (day)
 * @param banglaMonth Bangla month (1-12)
 * @param banglaYear Bangla year
 * @returns JavaScript Date object
 */
export const convertBanglaToGregorian = (banglaDate: number, banglaMonth: number, banglaYear: number): Date => {
  let gregorianYear = banglaYear + 593
  let gregorianMonth = 0 // 0-11 for JavaScript Date
  let gregorianDate = 0

  // Approximate mapping of Bangla to Gregorian dates
  // This is a simplified version - a more accurate version would use astronomical calculations
  if (banglaMonth === 1) {
    // Boishakh (mid-April to mid-May)
    if (banglaDate <= 18) {
      gregorianMonth = 3 // April
      gregorianDate = banglaDate + 13
    } else {
      gregorianMonth = 4 // May
      gregorianDate = banglaDate - 18
    }
  } else if (banglaMonth === 2) {
    // Jyoishtho (mid-May to mid-June)
    if (banglaDate <= 17) {
      gregorianMonth = 4 // May
      gregorianDate = banglaDate + 14
    } else {
      gregorianMonth = 5 // June
      gregorianDate = banglaDate - 17
    }
  } else if (banglaMonth === 3) {
    // Asharh (mid-June to mid-July)
    if (banglaDate <= 16) {
      gregorianMonth = 5 // June
      gregorianDate = banglaDate + 14
    } else {
      gregorianMonth = 6 // July
      gregorianDate = banglaDate - 16
    }
  } else if (banglaMonth === 4) {
    // Shrabon (mid-July to mid-August)
    if (banglaDate <= 16) {
      gregorianMonth = 6 // July
      gregorianDate = banglaDate + 15
    } else {
      gregorianMonth = 7 // August
      gregorianDate = banglaDate - 16
    }
  } else if (banglaMonth === 5) {
    // Bhadro (mid-August to mid-September)
    if (banglaDate <= 16) {
      gregorianMonth = 7 // August
      gregorianDate = banglaDate + 15
    } else {
      gregorianMonth = 8 // September
      gregorianDate = banglaDate - 16
    }
  } else if (banglaMonth === 6) {
    // Ashwin (mid-September to mid-October)
    if (banglaDate <= 15) {
      gregorianMonth = 8 // September
      gregorianDate = banglaDate + 15
    } else {
      gregorianMonth = 9 // October
      gregorianDate = banglaDate - 15
    }
  } else if (banglaMonth === 7) {
    // Kartik (mid-October to mid-November)
    if (banglaDate <= 16) {
      gregorianMonth = 9 // October
      gregorianDate = banglaDate + 15
    } else {
      gregorianMonth = 10 // November
      gregorianDate = banglaDate - 16
    }
  } else if (banglaMonth === 8) {
    // Ogrohayon (mid-November to mid-December)
    if (banglaDate <= 15) {
      gregorianMonth = 10 // November
      gregorianDate = banglaDate + 14
    } else {
      gregorianMonth = 11 // December
      gregorianDate = banglaDate - 15
    }
  } else if (banglaMonth === 9) {
    // Poush (mid-December to mid-January)
    if (banglaDate <= 16) {
      gregorianMonth = 11 // December
      gregorianDate = banglaDate + 14
    } else {
      gregorianMonth = 0 // January
      gregorianDate = banglaDate - 16
      gregorianYear += 1
    }
  } else if (banglaMonth === 10) {
    // Magh (mid-January to mid-February)
    if (banglaDate <= 18) {
      gregorianMonth = 0 // January
      gregorianDate = banglaDate + 13
    } else {
      gregorianMonth = 1 // February
      gregorianDate = banglaDate - 18
    }
  } else if (banglaMonth === 11) {
    // Falgun (mid-February to mid-March)
    if (banglaDate <= 16) {
      gregorianMonth = 1 // February
      gregorianDate = banglaDate + 12
    } else {
      gregorianMonth = 2 // March
      gregorianDate = banglaDate - 16
    }
  } else {
    // Chaitra (mid-March to mid-April)
    if (banglaDate <= 17) {
      gregorianMonth = 2 // March
      gregorianDate = banglaDate + 14
    } else {
      gregorianMonth = 3 // April
      gregorianDate = banglaDate - 17
    }
  }

  return new Date(gregorianYear, gregorianMonth, gregorianDate)
}

/**
 * Get the Bangla weekday name for a given date
 * @param date JavaScript Date object
 * @returns Bangla weekday name
 */
export const getBanglaWeekday = (date: Date): string => {
  const dayIndex = date.getDay() // 0-6, where 0 is Sunday
  return BANGLA_WEEKDAYS[dayIndex]
}

/**
 * Get the current Bangla date
 * @returns BanglaDate object for the current date
 */
export const getCurrentBanglaDate = (): BanglaDate => {
  return convertGregorianToBangla(new Date())
}

/**
 * Format a Bangla date as a string
 * @param banglaDate BanglaDate object
 * @param format Format string (e.g., 'full', 'medium', 'short')
 * @returns Formatted Bangla date string
 */
export const formatBanglaDateString = (
  banglaDate: BanglaDate,
  format: "full" | "medium" | "short" = "medium",
): string => {
  const { date, month, year, monthName, season } = banglaDate

  // Convert numbers to Bangla numerals
  const banglaNumerals = ["০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"]
  const toBanglaNumerals = (num: number) => {
    return num
      .toString()
      .split("")
      .map((digit) => banglaNumerals[Number.parseInt(digit)])
      .join("")
  }

  const banglaDateNum = toBanglaNumerals(date)
  const banglaYear = toBanglaNumerals(year)

  if (format === "full") {
    return `${banglaDateNum} ${monthName} ${banglaYear} (${season})`
  } else if (format === "short") {
    return `${banglaDateNum}/${toBanglaNumerals(month)}/${banglaYear}`
  } else {
    // medium format
    return `${banglaDateNum} ${monthName} ${banglaYear}`
  }
}
