import { Badge } from "@/components/ui/badge"
import type { RecurrenceRule } from "@/lib/rfc5545-types"

interface RRuleDisplayProps {
  rrule: string | RecurrenceRule
  className?: string
}

export function RRuleDisplay({ rrule, className }: RRuleDisplayProps) {
  const parsedRule = typeof rrule === 'string' ? parseRRuleString(rrule) : rrule
  const humanText = formatRRuleToHuman(parsedRule)
  
  return (
    <div className={className}>
      <span className="text-sm text-muted-foreground">{humanText}</span>
    </div>
  )
}

interface RRuleDisplayDetailedProps {
  rrule: string | RecurrenceRule
  className?: string
  showBadges?: boolean
}

export function RRuleDisplayDetailed({ rrule, className, showBadges = true }: RRuleDisplayDetailedProps) {
  const parsedRule = typeof rrule === 'string' ? parseRRuleString(rrule) : rrule
  const humanText = formatRRuleToHuman(parsedRule)
  const details = getRRuleDetails(parsedRule)
  
  return (
    <div className={className}>
      <div className="space-y-2">
        <div className="text-sm font-medium">{humanText}</div>
        
        {showBadges && details.length > 0 && (
          <div className="flex flex-wrap gap-1">
            {details.map((detail, index) => (
              <Badge key={index} variant="outline" className="text-xs">
                {detail}
              </Badge>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}

function parseRRuleString(rruleString: string): RecurrenceRule {
  const parts = Object.fromEntries(rruleString.split(";").map(p => p.split("=")))
  
  return {
    freq: parts.FREQ as RecurrenceRule['freq'],
    until: parts.UNTIL ? new Date(parts.UNTIL.replace(/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z?/, '$1-$2-$3T$4:$5:$6Z')).toISOString() : undefined,
    count: parts.COUNT ? parseInt(parts.COUNT, 10) : undefined,
    interval: parts.INTERVAL ? parseInt(parts.INTERVAL, 10) : undefined,
    bySecond: parts.BYSECOND ? parts.BYSECOND.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byMinute: parts.BYMINUTE ? parts.BYMINUTE.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byHour: parts.BYHOUR ? parts.BYHOUR.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byDay: parts.BYDAY ? parts.BYDAY.split(",") : undefined,
    byMonthDay: parts.BYMONTHDAY ? parts.BYMONTHDAY.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byYearDay: parts.BYYEARDAY ? parts.BYYEARDAY.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byWeekNo: parts.BYWEEKNO ? parts.BYWEEKNO.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    byMonth: parts.BYMONTH ? parts.BYMONTH.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    bySetPos: parts.BYSETPOS ? parts.BYSETPOS.split(",").map((n: string) => parseInt(n, 10)) : undefined,
    wkst: parts.WKST as RecurrenceRule['wkst'],
  }
}

function formatRRuleToHuman(rule: RecurrenceRule): string {
  const { freq, interval = 1, count, until, byDay, byMonthDay, byMonth, byHour, byMinute, bySecond } = rule
  
  let text = ""
  
  // Base frequency
  switch (freq) {
    case 'SECONDLY':
      text = interval === 1 ? "Every second" : `Every ${interval} seconds`
      break
    case 'MINUTELY':
      text = interval === 1 ? "Every minute" : `Every ${interval} minutes`
      break
    case 'HOURLY':
      text = interval === 1 ? "Every hour" : `Every ${interval} hours`
      break
    case 'DAILY':
      text = interval === 1 ? "Daily" : `Every ${interval} days`
      break
    case 'WEEKLY':
      text = interval === 1 ? "Weekly" : `Every ${interval} weeks`
      break
    case 'MONTHLY':
      text = interval === 1 ? "Monthly" : `Every ${interval} months`
      break
    case 'YEARLY':
      text = interval === 1 ? "Yearly" : `Every ${interval} years`
      break
  }
  
  // Add day specifications
  if (byDay?.length) {
    const dayNames = {
      'SU': 'Sunday', 'MO': 'Monday', 'TU': 'Tuesday', 'WE': 'Wednesday',
      'TH': 'Thursday', 'FR': 'Friday', 'SA': 'Saturday'
    }
    
    const days = byDay.map(day => {
      // Handle numbered days like "2TU" (second Tuesday)
      const match = day.match(/^(-?\d+)?([A-Z]{2})$/)
      if (match) {
        const [, num, dayCode] = match
        const dayName = dayNames[dayCode as keyof typeof dayNames]
        if (num) {
          const ordinal = getOrdinal(parseInt(num))
          return `${ordinal} ${dayName}`
        }
        return dayName
      }
      return day
    })
    
    if (freq === 'WEEKLY') {
      text += ` on ${formatList(days)}`
    } else {
      text += ` on ${formatList(days)}`
    }
  }
  
  // Add month day specifications
  if (byMonthDay?.length) {
    const days = byMonthDay.map(day => {
      if (day < 0) {
        return `${getOrdinal(Math.abs(day))} to last day`
      }
      return getOrdinal(day)
    })
    text += ` on the ${formatList(days)}`
  }
  
  // Add month specifications
  if (byMonth?.length) {
    const monthNames = [
      'January', 'February', 'March', 'April', 'May', 'June',
      'July', 'August', 'September', 'October', 'November', 'December'
    ]
    const months = byMonth.map(month => monthNames[month - 1])
    text += ` in ${formatList(months)}`
  }
  
  // Add time specifications
  if (byHour?.length || byMinute?.length || bySecond?.length) {
    const timeSpecs = []
    if (byHour?.length) {
      const hours = byHour.map(h => `${h.toString().padStart(2, '0')}:00`)
      timeSpecs.push(`at ${formatList(hours)}`)
    }
    if (byMinute?.length && !byHour?.length) {
      timeSpecs.push(`at minute ${formatList(byMinute.map(String))}`)
    }
    if (bySecond?.length && !byHour?.length && !byMinute?.length) {
      timeSpecs.push(`at second ${formatList(bySecond.map(String))}`)
    }
    if (timeSpecs.length) {
      text += ` ${timeSpecs.join(' ')}`
    }
  }
  
  // Add end conditions
  if (count) {
    text += `, ${count} time${count === 1 ? '' : 's'}`
  } else if (until) {
    const date = new Date(until)
    text += `, until ${date.toLocaleDateString()}`
  }
  
  return text
}

function getRRuleDetails(rule: RecurrenceRule): string[] {
  const details: string[] = []
  
  if (rule.wkst && rule.wkst !== 'MO') {
    const dayNames = {
      'SU': 'Sunday', 'MO': 'Monday', 'TU': 'Tuesday', 'WE': 'Wednesday',
      'TH': 'Thursday', 'FR': 'Friday', 'SA': 'Saturday'
    }
    details.push(`Week starts ${dayNames[rule.wkst]}`)
  }
  
  if (rule.byWeekNo?.length) {
    details.push(`Week ${formatList(rule.byWeekNo.map(String))}`)
  }
  
  if (rule.byYearDay?.length) {
    details.push(`Day ${formatList(rule.byYearDay.map(String))} of year`)
  }
  
  if (rule.bySetPos?.length) {
    const positions = rule.bySetPos.map(pos => {
      if (pos < 0) {
        return `${getOrdinal(Math.abs(pos))} to last`
      }
      return getOrdinal(pos)
    })
    details.push(`Position ${formatList(positions)}`)
  }
  
  return details
}

function getOrdinal(num: number): string {
  const suffix = ['th', 'st', 'nd', 'rd']
  const v = num % 100
  return num + (suffix[(v - 20) % 10] || suffix[v] || suffix[0])
}

function formatList(items: string[]): string {
  if (items.length === 0) return ''
  if (items.length === 1) return items[0]
  if (items.length === 2) return `${items[0]} and ${items[1]}`
  return `${items.slice(0, -1).join(', ')}, and ${items[items.length - 1]}`
}

// Hook for easy usage in components
export function useRRuleDisplay(rrule?: string) {
  if (!rrule) return null
  
  try {
    const parsedRule = parseRRuleString(rrule)
    return {
      humanText: formatRRuleToHuman(parsedRule),
      details: getRRuleDetails(parsedRule),
      parsedRule
    }
  } catch (error) {
    return {
      humanText: "Invalid recurrence rule",
      details: [],
      parsedRule: null,
      error: error instanceof Error ? error.message : String(error)
    }
  }
}
