import moment from 'moment'

import { capitalize } from '../../services/HelperServiceTyped'
import styles from './header_metric_group.module.scss'
import { c } from '../../translations/LibraryTranslationService'
import { type IconColorList, type IconStringList } from '../Icons/Icon.models'

type changeObjectNewProps = {
  /** Icon color to display in determine change */
  iconColor: IconColorList
  /** Icon to display in determine change */
  icon: IconStringList
  /** This className will be added to the text */
  textClassName: string
}

/** This function determines the change and reverse logic based on the change percentage */
export const determineChangeValue = (
  changePct: number,
  reverse?: boolean,
  isNeutralColor?: boolean,
) => {
  let changeObject: changeObjectNewProps = {
    iconColor: isNeutralColor ? 'purple' : 'dark-blue',
    textClassName: isNeutralColor ? styles.fontPurple : styles.fontBlue,
    icon: 'trendEven',
  }
  if (changePct < 0) {
    changeObject = {
      textClassName: isNeutralColor
        ? styles.fontPurple
        : reverse
          ? styles.fontDarkGreen
          : styles.fontDarkRed,
      iconColor: isNeutralColor
        ? 'purple'
        : reverse
          ? 'dark-green'
          : 'dark-red',
      icon: 'trendDown',
    }
  } else if (changePct > 0) {
    changeObject = {
      textClassName: isNeutralColor
        ? styles.fontPurple
        : reverse
          ? styles.fontDarkRed
          : styles.fontDarkGreen,
      iconColor: isNeutralColor
        ? 'purple'
        : reverse
          ? 'dark-red'
          : 'dark-green',
      icon: 'trendUp',
    }
  }
  return changeObject
}

type TimeframeTypeBase = {
  timeValue: moment.DurationInputArg2
  aggregation: string
  display: string
}

type CurrentTimeframeType = TimeframeTypeBase & {
  type: 'current'
  value?: never
}

type PreviousTimeframeType = TimeframeTypeBase & {
  type: 'previous'
  value?: never
}

type HistoricalTimeframeTypeBase = TimeframeTypeBase & {
  type: 'historical' | 'trailing'
}

type CustomHistoricalTimeframeType = HistoricalTimeframeTypeBase & {
  value: 'custom'
  compareDisplay: string
}

type NumberHistoricalTimeframeType = HistoricalTimeframeTypeBase & {
  value: number
  compareDisplay?: never
}

type HistoricalTimeframeType =
  | CustomHistoricalTimeframeType
  | NumberHistoricalTimeframeType

type QuarterlyTimeframeType = TimeframeTypeBase & {
  type: 'quarterly'
  year: number
  quarter: number
  value?: never
}
type PeriodDisplaysParams = {
  // Type of Timeframe eg. current/Historical/Quarterly/Previous
  timeframe: TimeframeType
  // 1 -> current Period && 2 -> current Year
  column: 1 | 2
  // compare with Previous Period or Previous Year
  compareWith?: CompareWith
}

export type TimeframeType =
  | CurrentTimeframeType
  | HistoricalTimeframeType
  | QuarterlyTimeframeType
  | PreviousTimeframeType

export type CompareWith = 'previous_period' | 'previous_year'

export const getPeriodDisplays = ({
  timeframe,
  column,
  compareWith,
}: PeriodDisplaysParams) => {
  // This logic is seperated to not impact if compareWith global filter param is not used
  if (compareWith === 'previous_year' && column === 2) {
    switch (timeframe?.type) {
      case 'current':
      case 'previous':
        return timeframe?.timeValue === 'day'
          ? c('sameDayPreviousYear')
          : timeframe.timeValue === 'year'
            ? c('previousYear')
            : c('sameTimeframeDisplayLastYear', {
                timeframeDisplay: timeframe?.display,
              })
      case 'historical':
      case 'trailing':
        if (timeframe?.timeValue === 'day' && timeframe?.value === 1) {
          return c('sameDayLastYear')
        } else if (timeframe?.value === 'custom') {
          return c('comparisonPeriod')
        } else {
          return timeframe.timeValue === 'year'
            ? c('precedingOneYear')
            : c('sameTimeframeDisplayLastYear', {
                timeframeDisplay: `${
                  timeframe?.timeValue === 'month' ||
                  timeframe?.timeValue === 'hours' ||
                  timeframe?.value === 30 ||
                  timeframe?.value === 7
                    ? timeframe?.value
                    : ''
                } ${capitalize(timeframe?.timeValue)}${
                  timeframe?.timeValue !== 'hours' &&
                  (timeframe?.timeValue === 'month' ||
                    timeframe?.value === 30 ||
                    timeframe?.value === 7)
                    ? c('sForPlural')
                    : ''
                }`,
              })
        }
    }
  }

  switch (timeframe?.type) {
    case 'current':
      if (timeframe?.timeValue === 'day')
        return column === 1 ? c('today') : c('yesterday')
      else
        return column === 1
          ? c('thisTimeframe', {
              timeframeDisplay: timeframe?.display,
            })
          : c('lastTimeframe', {
              timeframeDisplay: timeframe?.display,
            })
    case 'previous':
      if (timeframe?.timeValue === 'day')
        return column === 1 ? c('yesterday') : c('previousDay')
      else
        return column === 1
          ? c('lastTimeframe', {
              timeframeDisplay: timeframe?.display,
            })
          : c('previousTimeframe', {
              timeframeDisplay: timeframe?.display,
            })

    case 'historical':
    case 'trailing':
      if (timeframe?.timeValue === 'day' && timeframe?.value === 1)
        return `${column === 1 ? c('yesterday') : c('previousDay')}`
      else if (timeframe?.value === 'custom')
        return column === 1 ? c('selectedPeriod') : c('comparisonPeriod')
      else
        return column === 1
          ? c('lastTimeframe', {
              timeframeDisplay: `${
                timeframe?.timeValue === 'month' ||
                timeframe?.timeValue === 'hours' ||
                timeframe?.value === 30 ||
                timeframe?.value === 7
                  ? timeframe?.value
                  : ''
              } ${capitalize(timeframe?.timeValue)}${
                timeframe?.timeValue !== 'hours' &&
                (timeframe?.timeValue === 'month' ||
                  timeframe?.value === 30 ||
                  timeframe?.value === 7)
                  ? c('sForPlural')
                  : ''
              }`,
            })
          : c('previousTimeframe', {
              timeframeDisplay: `${
                timeframe?.timeValue === 'month' ||
                timeframe?.timeValue === 'hours' ||
                timeframe?.value === 30 ||
                timeframe?.value === 7
                  ? timeframe?.value
                  : ''
              } ${capitalize(timeframe?.timeValue)}${
                timeframe?.timeValue !== 'hours' &&
                (timeframe?.timeValue === 'month' ||
                  timeframe?.value === 30 ||
                  timeframe?.value === 7)
                  ? c('sForPlural')
                  : ''
              }`,
            })

    case 'quarterly':
      if (compareWith === 'previous_period' && column === 2) {
        if (timeframe.timeValue === 'year') {
          return `${moment(timeframe?.year, 'YYYY').subtract(1, 'year').format('YYYY')}`
        }
        const previousQuarter =
          timeframe?.quarter === 1 ? 4 : timeframe?.quarter - 1
        const year =
          timeframe?.quarter === 1 ? timeframe?.year - 1 : timeframe?.year
        return c('yearAndQuarter', {
          year: year,
          quarter: previousQuarter,
        })
      } else if (timeframe?.timeValue === 'quarter') {
        const quarter = moment(timeframe?.year, 'YYYY')
          .quarter(timeframe?.quarter)
          .subtract(4, 'Q')
        return column === 1
          ? `${timeframe?.display}`
          : c('yearAndQuarter', {
              year: quarter.format('YYYY'),
              quarter: quarter.format('Q'),
            })
      } else {
        return column === 1
          ? `${timeframe?.display}`
          : `${moment(timeframe?.year, 'YYYY').subtract(1, 'year').format('YYYY')}`
      }
  }
}

export const getPreviousPeriodRange = (
  timeframe: TimeframeType,
  startDate: string,
  endDate: string,
  compareWith?: string,
): string | null => {
  if (!timeframe || !startDate || !endDate) return null

  const start = moment(startDate)
  const end = moment(endDate)

  if (!start.isValid() || !end.isValid()) return null

  const now = moment()
  const currentYear = now.year()
  const currentQuarter = now.quarter()

  let compareStart: moment.Moment
  let compareEnd: moment.Moment

  // --- TYPE: CURRENT ---
  if (timeframe.type === 'current' && timeframe.timeValue) {
    if (compareWith === 'previous_period') {
      switch (timeframe.timeValue) {
        case 'week':
        case 'month':
        case 'year':
          compareStart = start
            .clone()
            .subtract(1, timeframe.timeValue)
            .startOf(timeframe.timeValue)
          compareEnd = compareStart.clone().endOf(timeframe.timeValue)
          break
        default:
          return null
      }
    } else if (compareWith === 'previous_year') {
      switch (timeframe.timeValue) {
        case 'week':
          compareStart = start.clone().subtract(1, 'year')
          compareEnd = compareStart.clone().add(6, 'days') // full week
          break
        case 'month':
          compareStart = start.clone().subtract(1, 'year').startOf('month')
          compareEnd = compareStart.clone().endOf('month')
          break
        case 'year':
          compareStart = start.clone().subtract(1, 'year').startOf('year')
          compareEnd = compareStart.clone().endOf('year')
          break
        default:
          return null
      }
    } else {
      return null
    }

    return `${compareStart.format('MM/DD/YYYY')} - ${compareEnd.format('MM/DD/YYYY')}`
  }

  // --- TYPE: QUARTERLY ---
  if (timeframe.type === 'quarterly' && timeframe.year) {
    const year = Number(timeframe.year)
    const quarter = Number(timeframe.quarter)

    const isCurrentQuarter = year === currentYear && quarter === currentQuarter
    const isCurrentYearOnly =
      year === currentYear && timeframe.timeValue === 'year'

    if (!(isCurrentQuarter || isCurrentYearOnly)) return null

    if (compareWith === 'previous_period') {
      if (isCurrentYearOnly) {
        compareStart = moment()
          .year(year - 1)
          .startOf('year')
        compareEnd = moment()
          .year(year - 1)
          .endOf('year')
      } else if (isCurrentQuarter && quarter) {
        const reference = moment().year(year).quarter(quarter)
        const prevQuarter = reference.clone().subtract(1, 'quarter')
        compareStart = prevQuarter.clone().startOf('quarter')
        compareEnd = prevQuarter.clone().endOf('quarter')
      } else {
        return null
      }
    } else if (compareWith === 'previous_year') {
      if (quarter && timeframe.timeValue === 'quarter') {
        const reference = moment()
          .year(year - 1)
          .quarter(quarter)
        compareStart = reference.clone().startOf('quarter')
        compareEnd = reference.clone().endOf('quarter')
      } else {
        compareStart = moment()
          .year(year - 1)
          .startOf('year')
        compareEnd = moment()
          .year(year - 1)
          .endOf('year')
      }
    } else {
      return null
    }

    return `${compareStart.format('MM/DD/YYYY')} - ${compareEnd.format('MM/DD/YYYY')}`
  }

  return null
}

export type DateType = {
  startDate: string
  endDate: string
}

export const formatDates = (
  currentPeriodDates: DateType,
  comparisonPeriodDates: DateType | undefined,
) => {
  const currentPeriodStartDate = moment(currentPeriodDates.startDate)
  const currentPeriodEndDate = moment(currentPeriodDates.endDate)
  const comparisonPeriodStartDate = moment(comparisonPeriodDates?.startDate)
  const comparisonPeriodEndDate = moment(comparisonPeriodDates?.endDate)

  if (
    currentPeriodStartDate.format('MM/DD/YYYY') ===
      currentPeriodEndDate.format('MM/DD/YYYY') &&
    comparisonPeriodStartDate.format('MM/DD/YYYY') ===
      comparisonPeriodEndDate.format('MM/DD/YYYY')
  ) {
    return c('currentDateVsComparisonDate', {
      currentDate: currentPeriodStartDate.format('MM/DD/YYYY'),
      comparisonDate: comparisonPeriodStartDate.format('MM/DD/YYYY'),
    })
  }

  return c('currentDateVsComparisonDateRange', {
    currentPeriodStartDate: currentPeriodStartDate.format('MM/DD/YYYY'),
    currentPeriodEndDate: currentPeriodEndDate.format('MM/DD/YYYY'),
    comparisonPeriodStartDate: comparisonPeriodStartDate.format('MM/DD/YYYY'),
    comparisonPeriodEndDate: comparisonPeriodEndDate.format('MM/DD/YYYY'),
  })
}

export const getPartialPeriodDates = (
  currentPeriodDates: DateType,
  comparisonPeriodDates?: DateType,
) => {
  const format = 'MM/DD/YYYY'

  const currentStart = moment(currentPeriodDates.startDate).format(format)
  const currentEnd = moment(currentPeriodDates.endDate).format(format)
  const comparisonStart = moment(comparisonPeriodDates?.startDate).format(
    format,
  )
  const comparisonEnd = moment(comparisonPeriodDates?.endDate).format(format)

  const isSingleDate =
    currentStart === currentEnd && comparisonStart === comparisonEnd

  const currentDate = isSingleDate
    ? currentStart
    : `${currentStart} - ${currentEnd}`

  const comparisonDate = isSingleDate
    ? comparisonStart
    : `${comparisonStart} - ${comparisonEnd}`

  return { currentDate, comparisonDate }
}
