'use client'

import type { Dayjs } from 'dayjs'
import type { DatePickerProps } from '@/app/components/base/date-and-time-picker/types'
import type { I18nKeysWithPrefix } from '@/types/i18n'
import { cn } from '@langgenius/dify-ui/cn'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectItemIndicator,
  SelectItemText,
  SelectTrigger,
} from '@langgenius/dify-ui/select'
import dayjs from 'dayjs'
import { noop } from 'es-toolkit/function'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import DatePicker from '@/app/components/base/date-and-time-picker/date-picker'
import { useLocale } from '@/context/i18n'
import { formatToLocalTime } from '@/utils/format'

export type AgentMonitoringPeriod = {
  name: string
  query: {
    start: string
    end: string
  }
}

type TimeRangeKey = 'today' | 'last7days' | 'last30days'

type TimeRangeOption = {
  value: TimeRangeKey
  days: number
  nameKey: I18nKeysWithPrefix<'agentV2', 'agentDetail.monitoring.timeRanges.'>
}

type AgentMonitoringTimeRangePickerProps = {
  value: AgentMonitoringPeriod
  onChange: (period: AgentMonitoringPeriod) => void
}

const today = dayjs()
const queryDateFormat = 'YYYY-MM-DD HH:mm'

const timeRangeOptions: TimeRangeOption[] = [
  { value: 'today', days: 0, nameKey: 'agentDetail.monitoring.timeRanges.today' },
  { value: 'last7days', days: 7, nameKey: 'agentDetail.monitoring.timeRanges.last7days' },
  { value: 'last30days', days: 30, nameKey: 'agentDetail.monitoring.timeRanges.last30days' },
]

const getRangePeriod = (option: TimeRangeOption): AgentMonitoringPeriod => {
  const end = today.endOf('day')
  const start =
    option.days === 0 ? today.startOf('day') : today.subtract(option.days, 'day').startOf('day')

  return {
    name: option.value,
    query: {
      start: start.format(queryDateFormat),
      end: end.format(queryDateFormat),
    },
  }
}

function DateRangePart({
  start,
  end,
  onStartChange,
  onEndChange,
}: {
  start: Dayjs
  end: Dayjs
  onStartChange: (date?: Dayjs) => void
  onEndChange: (date?: Dayjs) => void
}) {
  const locale = useLocale()

  const renderDate: DatePickerProps['renderTrigger'] = (props, _state, { value }) => (
    <button
      {...props}
      type="button"
      className={cn(
        'flex h-7 cursor-pointer items-center rounded-lg px-1 system-sm-regular text-components-input-text-filled hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden data-popup-open:bg-state-base-hover',
        props.className,
      )}
    >
      {value ? formatToLocalTime(value, locale, 'MMM D') : ''}
    </button>
  )

  const availableStartDate = end.subtract(30, 'day')
  const isStartDateDisabled = (date: Dayjs) => {
    if (date.isAfter(today, 'date')) return true

    return !(
      (date.isAfter(availableStartDate, 'date') || date.isSame(availableStartDate, 'date')) &&
      (date.isBefore(end, 'date') || date.isSame(end, 'date'))
    )
  }

  const availableEndDate = start.add(30, 'day')
  const isEndDateDisabled = (date: Dayjs) => {
    if (date.isAfter(today, 'date')) return true

    return !(
      (date.isAfter(start, 'date') || date.isSame(start, 'date')) &&
      (date.isBefore(availableEndDate, 'date') || date.isSame(availableEndDate, 'date'))
    )
  }

  return (
    <div className="flex h-8 items-center space-x-0.5 rounded-lg bg-components-input-bg-normal px-2">
      <span aria-hidden className="i-ri-calendar-line size-3.5 text-text-tertiary" />
      <DatePicker
        value={start}
        onChange={onStartChange}
        renderTrigger={renderDate}
        needTimePicker={false}
        onClear={noop}
        noConfirm
        getIsDateDisabled={isStartDateDisabled}
      />
      <span className="system-sm-regular text-text-tertiary">-</span>
      <DatePicker
        value={end}
        onChange={onEndChange}
        renderTrigger={renderDate}
        needTimePicker={false}
        onClear={noop}
        noConfirm
        getIsDateDisabled={isEndDateDisabled}
      />
    </div>
  )
}

export function AgentMonitoringTimeRangePicker({
  value,
  onChange,
}: AgentMonitoringTimeRangePickerProps) {
  const { t } = useTranslation('agentV2')
  const locale = useLocale()
  const [selectedRange, setSelectedRange] = useState<TimeRangeKey | 'custom'>('today')
  const [start, setStart] = useState(() => dayjs(value.query.start))
  const [end, setEnd] = useState(() => dayjs(value.query.end))

  const selectedOption = timeRangeOptions.find((option) => option.value === selectedRange)

  const handleRangeChange = (nextValue: TimeRangeKey | null) => {
    if (!nextValue) return

    const option = timeRangeOptions.find((item) => item.value === nextValue)
    if (!option) return

    const nextPeriod = getRangePeriod(option)
    setSelectedRange(option.value)
    setStart(dayjs(nextPeriod.query.start))
    setEnd(dayjs(nextPeriod.query.end))
    onChange({
      ...nextPeriod,
      name: t(($) => $[option.nameKey]),
    })
  }

  const handleDateChange = (type: 'start' | 'end') => (date?: Dayjs) => {
    if (!date) return

    if (type === 'start' && date.isSame(start)) return

    if (type === 'end' && date.isSame(end)) return

    const nextStart = type === 'start' ? date : start
    const nextEnd = type === 'end' ? date : end
    const nextName = `${formatToLocalTime(nextStart, locale, 'MMM D')} - ${formatToLocalTime(nextEnd, locale, 'MMM D')}`

    setSelectedRange('custom')
    setStart(nextStart)
    setEnd(nextEnd)
    onChange({
      name: nextName,
      query: {
        start: nextStart.format(queryDateFormat),
        end: nextEnd.format(queryDateFormat),
      },
    })
  }

  return (
    <div className="flex min-w-0 items-center">
      <Select<TimeRangeKey>
        value={selectedRange === 'custom' ? null : selectedRange}
        onValueChange={handleRangeChange}
      >
        <SelectTrigger
          aria-label={t(($) => $['agentDetail.monitoring.timeRangeLabel'])}
          className="w-fit shrink-0 cursor-pointer gap-1.5 pr-2 pl-3"
        >
          {selectedRange === 'custom'
            ? t(($) => $['agentDetail.monitoring.timeRanges.custom'])
            : selectedOption
              ? t(($) => $[selectedOption.nameKey])
              : value.name}
        </SelectTrigger>
        <SelectContent className="w-50">
          {timeRangeOptions.map((option) => (
            <SelectItem key={option.value} value={option.value}>
              <SelectItemText>{t(($) => $[option.nameKey])}</SelectItemText>
              <SelectItemIndicator />
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      <span
        aria-hidden
        className="i-custom-vender-other-hourglass-shape h-3.5 w-2 text-components-input-bg-normal"
      />
      <DateRangePart
        start={start}
        end={end}
        onStartChange={handleDateChange('start')}
        onEndChange={handleDateChange('end')}
      />
    </div>
  )
}
