'use client'

import { forwardRef } from 'react'

import { PktIcon } from '../icon/Icon'
import { PktInputWrapper } from '../inputwrapper/InputWrapper'
import { useTimepickerState } from './useTimepickerState'
import type { IPktTimepicker } from './types'

export type { IPktTimepicker } from './types'

export const PktTimepicker = forwardRef<HTMLDivElement, IPktTimepicker>((props, ref) => {
  const { onChange, onInput } = props
  const state = useTimepickerState(props, ref)

  const hoursLabel = state.strings.hours
  const minutesLabel = state.strings.minutes
  const hoursAriaLabel = state.label ? `${hoursLabel}, ${state.label}` : hoursLabel
  const minutesAriaLabel = state.label ? `${minutesLabel}, ${state.label}` : minutesLabel

  const renderOption = (optionValue: number, type: 'hour' | 'minute') => {
    const strVal = String(optionValue).padStart(2, '0')
    const currentVal =
      type === 'hour'
        ? state.hours !== ''
          ? parseInt(state.hours, 10)
          : NaN
        : state.minutes !== ''
          ? parseInt(state.minutes, 10)
          : NaN
    const isSelected = optionValue === currentVal
    return (
      <button
        key={`${type}-${optionValue}`}
        type="button"
        className={[
          'pkt-btn',
          'pkt-btn--tertiary',
          'pkt-btn--small',
          'pkt-btn--label-only',
          'pkt-timepicker-popup__option',
          isSelected ? 'pkt-timepicker-popup__option--selected' : '',
        ]
          .filter(Boolean)
          .join(' ')}
        role="option"
        aria-selected={isSelected ? 'true' : 'false'}
        tabIndex={isSelected ? 0 : -1}
        data-type={type}
        data-value={optionValue}
        onClick={(e) => {
          e.stopPropagation()
          state.handleOptionClick(optionValue, type)
        }}
      >
        <span className="pkt-btn__text pkt-txt-14-light">{strVal}</span>
      </button>
    )
  }

  const renderPopup = () => (
    <div
      ref={state.popupRef}
      className="pkt-timepicker-popup"
      id={state.popupId}
      hidden={!state.isOpen}
      role="group"
      aria-label={state.strings.selectTime}
      onKeyDown={state.handlePopupKeydown}
      onBlur={state.handlePopupFocusOut}
    >
      <div className="pkt-timepicker-popup__col" role="listbox" aria-label={hoursLabel} aria-orientation="vertical">
        {state.hourOptions.map((h) => renderOption(h, 'hour'))}
      </div>
      <div className="pkt-timepicker-popup__col" role="listbox" aria-label={minutesLabel} aria-orientation="vertical">
        {state.minuteOptions.map((m) => renderOption(m, 'minute'))}
      </div>
    </div>
  )

  const renderContainer = () => (
    <div
      className="pkt-input__container"
      onClick={(e) => {
        const target = e.target as HTMLElement
        if (target.closest('button, input')) return
        state.hoursInputRef.current?.focus()
      }}
    >
      {state.stepArrows && (
        <button
          type="button"
          className="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-timepicker__button pkt-timepicker__button--prev"
          aria-label={state.strings.prevTime}
          disabled={state.disabled}
          onClick={() => state.stepTimeDelta(-1)}
        >
          <PktIcon name="chevron-thin-left" />
          <span className="pkt-btn__text">{state.strings.prevTime}</span>
        </button>
      )}
      <input
        ref={state.hoursInputRef}
        type="text"
        inputMode="numeric"
        maxLength={2}
        size={2}
        className="pkt-input pkt-timepicker__input"
        id={state.hoursId}
        data-min="0"
        data-max="23"
        value={state.hours}
        placeholder="––"
        aria-label={hoursAriaLabel}
        role="spinbutton"
        aria-invalid={state.hasError || state.isInvalid || undefined}
        aria-valuemin={0}
        aria-valuemax={23}
        aria-valuenow={state.hours !== '' ? parseInt(state.hours, 10) : undefined}
        aria-valuetext={state.hours !== '' ? `${state.hours} ${hoursLabel.toLowerCase()}` : undefined}
        autoComplete="off"
        disabled={state.disabled}
        onKeyDown={state.handleHoursKeydown}
        onBlur={state.handleHoursBlur}
        onFocus={(e) => {
          e.currentTarget.select()
        }}
        onChange={() => {
          /* value is driven by keydown handlers */
        }}
        onPaste={(e) => e.preventDefault()}
      />
      <span className="pkt-timepicker__separator">:</span>
      <input
        ref={state.minutesInputRef}
        type="text"
        inputMode="numeric"
        maxLength={2}
        size={2}
        className="pkt-input pkt-timepicker__input"
        id={state.minutesId}
        data-min="0"
        data-max="59"
        value={state.minutes}
        placeholder="––"
        aria-label={minutesAriaLabel}
        role="spinbutton"
        aria-invalid={state.hasError || state.isInvalid || undefined}
        aria-valuemin={0}
        aria-valuemax={59}
        aria-valuenow={state.minutes !== '' ? parseInt(state.minutes, 10) : undefined}
        aria-valuetext={state.minutes !== '' ? `${state.minutes} ${minutesLabel.toLowerCase()}` : undefined}
        autoComplete="off"
        disabled={state.disabled}
        onKeyDown={state.handleMinutesKeydown}
        onBlur={state.handleMinutesBlur}
        onFocus={(e) => {
          e.currentTarget.select()
        }}
        onChange={() => {
          /* value is driven by keydown handlers */
        }}
        onPaste={(e) => e.preventDefault()}
      />
      {state.hidePicker && !state.stepArrows && (
        <PktIcon className="pkt-input-icon pkt-timepicker__icon" name="clock" aria-hidden={true} />
      )}
      {!state.hidePicker && !state.stepArrows && (
        <button
          ref={state.buttonRef}
          type="button"
          className="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-timepicker__button"
          aria-label={state.strings.openPicker}
          aria-haspopup="listbox"
          aria-expanded={state.isOpen}
          aria-controls={state.popupId}
          disabled={state.disabled}
          onClick={state.handleClockButtonClick}
        >
          <PktIcon name="clock" />
          <span className="pkt-btn__text">{state.strings.openPicker}</span>
        </button>
      )}
      {state.stepArrows && (
        <button
          type="button"
          className="pkt-input-icon pkt-btn pkt-btn--icon-only pkt-btn--tertiary pkt-timepicker__button pkt-timepicker__button--next"
          aria-label={state.strings.nextTime}
          disabled={state.disabled}
          onClick={() => state.stepTimeDelta(1)}
        >
          <PktIcon name="chevron-thin-right" />
          <span className="pkt-btn__text">{state.strings.nextTime}</span>
        </button>
      )}
      {/* Native constraints are reported on the hours spinbutton (setCustomValidity), not here — avoids
          "invalid form control is not focusable" for this hidden type="time" input. */}
      <input
        ref={state.changeInputRef}
        type="time"
        hidden
        name={state.name}
        id={state.hiddenInputId}
        disabled={state.disabled}
        tabIndex={-1}
        aria-hidden={true}
        onChange={onChange}
        onInput={onInput}
      />
    </div>
  )

  return (
    <div
      ref={state.containerRef}
      className={state.outerClasses}
      id={state.id || undefined}
      onFocus={state.handleFocusIn}
      onBlur={state.handleFocusOut}
    >
      <PktInputWrapper
        forId={state.hoursId}
        label={state.label}
        disabled={state.disabled}
        hasError={state.hasError}
        inline={state.inline}
        optionalTag={state.optionalTag}
        optionalText={state.optionalText}
        requiredTag={state.requiredTag}
        requiredText={state.requiredText}
        useWrapper={state.useWrapper}
        ariaDescribedby={state.ariaDescribedby}
        errorMessage={state.errorMessage}
        helptext={state.helptext}
        helptextDropdown={state.helptextDropdown}
        helptextDropdownButton={state.helptextDropdownButton}
        tagText={state.tagText}
      >
        {!state.hidePicker && !state.stepArrows ? (
          <div className="pkt-timepicker__anchor">
            {renderContainer()}
            {renderPopup()}
          </div>
        ) : (
          renderContainer()
        )}
      </PktInputWrapper>
    </div>
  )
})

PktTimepicker.displayName = 'PktTimepicker'
