import { forwardRef, ForwardedRef, useEffect, useState } from 'react'

import { PktButton, PktIcon, PktProgressbar } from '..'
import { PktModal } from '../modal/Modal'
import { Truncate } from './Truncate'
import { TFileAndTransfer, TItemRenderer, TQueueItemOperation, TTransferItemInProgress } from './types'
import { formatFileSize } from './utils'

const CancelTransferButton = (props: { onClick: () => void; label?: string; ariaLabel?: string }) => (
  <button
    onClick={props.onClick}
    className="pkt-fileupload__queue-display__item__cancel-button"
    aria-label={props.ariaLabel || 'Avbryt opplasting'}
  >
    {props.label || 'Avbryt'}
  </button>
)

const LoadingText = () => {
  const [dotCount, setDotCount] = useState(1)

  useEffect(() => {
    const interval = setInterval(() => {
      setDotCount((prev) => (prev >= 3 ? 1 : prev + 1))
    }, 400)

    return () => clearInterval(interval)
  }, [])

  return (
    <span className="pkt-fileupload__queue-display__item__loading-text" aria-label="Laster opp fil">
      Laster opp{'.'.repeat(dotCount)}
    </span>
  )
}

export const TransferInProgress = ({
  cancelTransfer,
  transferItem,
}: {
  transferItem: TTransferItemInProgress
  cancelTransfer: () => void
}) => {
  const showProgressBar = transferItem.showProgress ?? transferItem.progress !== 0

  return (
    <>
      <PktIcon
        name="document-text"
        className="pkt-fileupload__queue-display__item__icon pkt-icon--medium"
        aria-hidden="true"
      />
      <p className="pkt-fileupload__queue-display__item__title" aria-label="Filnavn">
        <Truncate>{transferItem.attributes['targetFilename']}</Truncate>
      </p>
      <CancelTransferButton onClick={cancelTransfer} />
      {showProgressBar ? (
        <>
          <PktProgressbar
            valueCurrent={transferItem.progress * 100}
            statusType={'none'}
            valueMax={100}
            statusPlacement={'following'}
            className="pkt-fileupload__queue-display__item__progress"
          />
          <span className="pkt-fileupload__queue-display__item__filesize">
            {formatFileSize(transferItem.file.size)}
          </span>
          <span className="pkt-fileupload__queue-display__item__percentage" aria-hidden="true">
            {`${Math.round(transferItem.progress * 100)}%`}
          </span>
        </>
      ) : (
        <LoadingText />
      )}
    </>
  )
}

// Error state with progress bar (when showProgress was true during upload)
const TransferErrorWithProgress = ({
  transferItem,
  onRemove,
}: {
  transferItem: TFileAndTransfer
  onRemove: () => void
}) => {
  // Use lastProgress to show where the upload failed (default to 100% if not available)
  const progressValue = (transferItem.lastProgress ?? 1) * 100

  return (
    <>
      <PktIcon
        className="pkt-fileupload__queue-display__item__icon pkt-icon--medium"
        name="alert-error"
        aria-hidden="true"
      />
      <p className="pkt-fileupload__queue-display__item__title">
        <Truncate>{transferItem.attributes['targetFilename']}</Truncate>
      </p>
      <CancelTransferButton onClick={onRemove} label="Fjern" ariaLabel="Fjern fil som feilet under opplasting" />
      <PktProgressbar
        valueCurrent={progressValue}
        statusType={'none'}
        valueMax={100}
        statusPlacement={'following'}
        className="pkt-fileupload__queue-display__item__progress pkt-fileupload__queue-display__item__progress--error"
      />
      <span className="pkt-fileupload__queue-display__item__filesize">{formatFileSize(transferItem.file.size)}</span>
      {transferItem.errorMessage && (
        <span className="pkt-fileupload__queue-display__item__error-message">{transferItem.errorMessage}</span>
      )}
    </>
  )
}

// Error state without progress bar (indeterminate upload)
const TransferErrorIndeterminate = ({
  transferItem,
  onRemove,
}: {
  transferItem: TFileAndTransfer
  onRemove: () => void
}) => (
  <>
    <PktIcon
      className="pkt-fileupload__queue-display__item__icon pkt-icon--medium"
      name="alert-error"
      aria-hidden="true"
    />
    <p className="pkt-fileupload__queue-display__item__title">
      <Truncate>{transferItem.attributes['targetFilename']}</Truncate>
    </p>
    <CancelTransferButton onClick={onRemove} label="Fjern" ariaLabel="Fjern fil som feilet under opplasting" />
    {transferItem.errorMessage && (
      <span className="pkt-fileupload__queue-display__item__error-message">{transferItem.errorMessage}</span>
    )}
  </>
)

// Main error component - chooses display based on showProgress
export const TransferError = ({ transferItem, onRemove }: { transferItem: TFileAndTransfer; onRemove: () => void }) => {
  // If showProgress was true, show error with progress bar, otherwise show indeterminate error
  if (transferItem.showProgress) {
    return <TransferErrorWithProgress transferItem={transferItem} onRemove={onRemove} />
  }
  return <TransferErrorIndeterminate transferItem={transferItem} onRemove={onRemove} />
}
export const OperationButton = ({
  operation,
  onActivate,
  transferItem,
}: {
  operation: TQueueItemOperation
  onActivate: (fileId: string, operation: TQueueItemOperation) => void
  transferItem: TFileAndTransfer
}) => {
  const title = typeof operation.title === 'function' ? operation.title(transferItem) : operation.title

  // Don't render button if title is empty (e.g., comment exists, show icons instead)
  if (!title) return null

  const onClick = () => {
    if (operation.renderInlineUI || operation.renderExtendedUI) {
      onActivate(transferItem.fileId, operation)
    }
    if (operation.onClick) {
      operation.onClick(transferItem)
    }
  }
  return (
    <button
      type="button"
      className={'pkt-fileupload__queue-display__item__operation'}
      onClick={onClick}
      aria-label={typeof operation.ariaLabel === 'function' ? operation.ariaLabel(transferItem) : operation.ariaLabel}
    >
      {title}
    </button>
  )
}
export const FilenameRenderer = ({
  transferItem,
}: {
  transferItem: TFileAndTransfer
  queueItemOperations?: Array<TQueueItemOperation>
  onPreviewClick?: () => void
}) => (
  <>
    <PktIcon
      name="document-text"
      className="pkt-fileupload__queue-display__item__icon pkt-icon--medium"
      aria-hidden="true"
    />
    <p className={'pkt-fileupload__queue-display__item__title'}>
      <Truncate>{transferItem.attributes['targetFilename']}</Truncate>
    </p>
    <span className="pkt-fileupload__queue-display__item__filesize">{formatFileSize(transferItem.file.size)}</span>
  </>
)

export const ThumbnailRenderer = ({
  transferItem,
  onPreviewClick,
}: {
  transferItem: TFileAndTransfer
  queueItemOperations?: Array<TQueueItemOperation>
  onPreviewClick?: () => void
}) => {
  const [thumbnailUrl, setThumbnailUrl] = useState<string | null>(null)
  const [thumbnailLoadFailed, setThumbnailLoadFailed] = useState(false)
  const file = transferItem.file

  useEffect(() => {
    setThumbnailLoadFailed(false)

    // Check if the file is an image
    if (file.type.startsWith('image/')) {
      // Create an object URL for the file
      const url = URL.createObjectURL(file)
      setThumbnailUrl(url)

      // Cleanup: revoke the object URL when component unmounts
      return () => {
        URL.revokeObjectURL(url)
      }
    }

    setThumbnailUrl(null)
  }, [file])

  const img = (thumbnailUrl && !thumbnailLoadFailed && (
    <img
      src={thumbnailUrl}
      alt={transferItem.attributes['targetFilename']}
      onError={() => setThumbnailLoadFailed(true)}
    />
  )) || <PktIcon name="document-text" className="pkt-fileupload__queue-display__item__icon pkt-icon--medium" />

  const showExpandButton = !!onPreviewClick
  const hasThumbnailPreview = !!thumbnailUrl && !thumbnailLoadFailed

  return (
    <div
      className={`pkt-fileupload__queue-display__item__thumbnail${
        hasThumbnailPreview ? '' : ' pkt-fileupload__queue-display__item__thumbnail--fallback'
      }`}
    >
      <PktButton
        className="pkt-fileupload__queue-display__item__thumbnail__image-wrapper"
        aria-label={`Forhåndsvis bilde ${transferItem.attributes['targetFilename']}`}
        type="button"
        skin="secondary"
        onClick={onPreviewClick}
      >
        {showExpandButton && (
          <PktIcon
            name="expand"
            className="pkt-fileupload__queue-display__item__thumbnail__expand-icon"
            aria-hidden="true"
          />
        )}
        {img}
      </PktButton>
      <Truncate className={'pkt-fileupload__queue-display__item__thumbnail__title'}>
        {transferItem.attributes['targetFilename']}
      </Truncate>
    </div>
  )
}

// Image Preview Modal Component
// TODO: When we get an actual PktLightBox component, we can remove this component and use that instead.
interface IImagePreviewModal {
  isOpen: boolean
  images: TFileAndTransfer[]
  currentIndex: number
  onClose: () => void
  onNavigate: (direction: 'prev' | 'next') => void
}

export const ImagePreviewModal = forwardRef(
  ({ isOpen, images, currentIndex, onClose, onNavigate }: IImagePreviewModal, ref: ForwardedRef<HTMLDialogElement>) => {
    const [imageUrl, setImageUrl] = useState<string | null>(null)
    const [imageLoadFailed, setImageLoadFailed] = useState(false)
    const currentImage = images[currentIndex]
    const hasMultipleImages = images.length > 1

    useEffect(() => {
      setImageLoadFailed(false)

      if (currentImage && currentImage.file.type.startsWith('image/')) {
        const url = URL.createObjectURL(currentImage.file)
        setImageUrl(url)
        return () => URL.revokeObjectURL(url)
      }
      setImageUrl(null)
    }, [currentImage])

    // Keyboard navigation
    useEffect(() => {
      if (!isOpen) return

      const handleKeyDown = (e: KeyboardEvent) => {
        switch (e.key) {
          case 'ArrowLeft':
            e.preventDefault()
            onNavigate('prev')
            break
          case 'ArrowRight':
            e.preventDefault()
            onNavigate('next')
            break
          case 'Escape':
            e.preventDefault()
            onClose()
            break
        }
      }

      window.addEventListener('keydown', handleKeyDown)
      return () => window.removeEventListener('keydown', handleKeyDown)
    }, [isOpen, onNavigate, onClose])

    if (!currentImage) return null

    return (
      <PktModal
        ref={ref}
        headingText={currentImage.attributes['targetFilename']}
        closeOnBackdropClick
        className="pkt-fileupload__image-preview-modal"
      >
        <div className="pkt-fileupload__image-preview">
          {hasMultipleImages && (
            <PktButton
              variant="icon-only"
              iconName="chevron-thin-left"
              skin="secondary"
              size="small"
              className="pkt-fileupload__image-preview__nav pkt-fileupload__image-preview__nav--prev"
              onClick={() => onNavigate('prev')}
              aria-label={`Forrige bilde ${currentIndex} / ${images.length}`}
            />
          )}

          <div className="pkt-fileupload__image-preview__content">
            {imageUrl && !imageLoadFailed ? (
              <img
                src={imageUrl}
                alt={`${currentImage.attributes['targetFilename']} - ${currentIndex + 1} av ${images.length}`}
                className="pkt-fileupload__image-preview__image"
                onError={() => setImageLoadFailed(true)}
              />
            ) : (
              <PktIcon name="picture" className="pkt-fileupload__queue-display__item__icon pkt-icon--medium" />
            )}
          </div>

          {hasMultipleImages && (
            <span className="pkt-fileupload__image-preview__counter">
              {currentIndex + 1} / {images.length}
            </span>
          )}

          {hasMultipleImages && (
            <PktButton
              variant="icon-only"
              iconName="chevron-thin-right"
              skin="secondary"
              size="small"
              className="pkt-fileupload__image-preview__nav pkt-fileupload__image-preview__nav--next"
              onClick={() => onNavigate('next')}
              aria-label={`Neste bilde ${currentIndex + 2} / ${images.length}`}
            />
          )}
        </div>
      </PktModal>
    )
  },
)

ImagePreviewModal.displayName = 'ImagePreviewModal'
