'use client'

import classNames from 'classnames'
import {
  ForwardedRef,
  forwardRef,
  HTMLAttributes,
  MutableRefObject,
  ReactNode,
  Ref,
  useCallback,
  useEffect,
  useRef,
} from 'react'

import { createScrollLockToken, setScrollLock } from 'shared-utils/scroll-lock'

import { PktButton } from '../button/Button'

export interface IPktModal
  extends Omit<HTMLAttributes<HTMLDialogElement>, 'onClose' | 'open'> {
  open?: boolean
  headingText?: string
  hideCloseButton?: boolean
  closeOnBackdropClick?: boolean
  size?: 'small' | 'medium' | 'large' | 'fit-content'
  removePadding?: boolean
  closeButtonSkin?: 'blue' | 'yellow-filled'
  variant?: 'dialog' | 'drawer'
  drawerPosition?: 'left' | 'right'
  transparentBackdrop?: boolean
  onClose?: () => void
  children?: ReactNode
  ref?: Ref<HTMLDialogElement>
}

export const PktModal = forwardRef(
  (
    {
      children,
      className,
      open = false,
      headingText = '',
      hideCloseButton = false,
      closeOnBackdropClick = false,
      size = 'medium',
      removePadding = false,
      closeButtonSkin = 'blue',
      variant = 'dialog',
      drawerPosition = 'right',
      transparentBackdrop = false,
      onClose,
      ...props
    }: IPktModal,
    ref: ForwardedRef<HTMLDialogElement>,
  ) => {
    const internalRef = useRef<HTMLDialogElement | null>(null)
    const scrollLockToken = useRef(createScrollLockToken())

    // Merge consumer ref + internal ref so we always have a working DOM handle
    // for our own logic, regardless of whether the consumer passes a callback ref
    // or an object ref (or nothing).
    const setDialogRef = useCallback(
      (node: HTMLDialogElement | null) => {
        internalRef.current = node
        if (typeof ref === 'function') ref(node)
        else if (ref) (ref as MutableRefObject<HTMLDialogElement | null>).current = node
      },
      [ref],
    )

    const close = useCallback(() => {
      if (!internalRef.current?.open) return
      internalRef.current.close()
      setScrollLock(scrollLockToken.current, false)
      onClose?.()
    }, [onClose])

    // Deklarativ åpne/lukke via open-prop
    useEffect(() => {
      if (open) {
        if (!internalRef.current?.open) {
          internalRef.current?.showModal()
        }
        setScrollLock(scrollLockToken.current, true)
      } else {
        if (internalRef.current?.open) {
          internalRef.current.close()
        }
        setScrollLock(scrollLockToken.current, false)
      }
    }, [open])

    // Rydd opp scroll-lock hvis modalen avmonteres mens den er åpen
    useEffect(() => {
      const token = scrollLockToken.current
      return () => {
        setScrollLock(token, false)
      }
    }, [])

    const handleBackdropClick = useCallback(
      (event: React.MouseEvent<HTMLDialogElement>) => {
        if (closeOnBackdropClick && event.target === internalRef.current) {
          close()
        }
      },
      [closeOnBackdropClick, close],
    )

    const handleNativeClose = useCallback(() => {
      setScrollLock(scrollLockToken.current, false)
      onClose?.()
    }, [onClose])

    const isCloseButtonSkinDefault = closeButtonSkin === 'blue'

    const classes = classNames(
      {
        'pkt-modal': true,
        'pkt-modal--removePadding': removePadding,
        'pkt-modal--noHeadingText': !headingText,
        'pkt-modal--noShadow': closeButtonSkin === 'yellow-filled',
        'pkt-modal--transparentBackdrop': transparentBackdrop,
        [`pkt-modal--${size}`]: size,
        [`pkt-modal__${variant}`]: variant,
        [`pkt-modal__drawer--${drawerPosition}`]: variant === 'drawer',
      },
      className,
    )

    return (
      <dialog
        {...props}
        className={classes}
        ref={setDialogRef}
        aria-labelledby={headingText ? 'pkt-modal__headingText' : undefined}
        aria-describedby="pkt-modal__content"
        onClick={handleBackdropClick}
        onClose={handleNativeClose}
      >
        <div className="pkt-modal__wrapper">
          {(headingText || !hideCloseButton) && (
            <div className="pkt-modal__header">
              <div className="pkt-modal__header-background" />
              {headingText ? (
                <h1 id="pkt-modal__headingText" className="pkt-modal__headingText pkt-txt-24">
                  {headingText}
                </h1>
              ) : (
                <div className="pkt-modal__headingText" />
              )}
              {!hideCloseButton ? (
                <div
                  className={classNames('pkt-modal__closeButton', {
                    [`pkt-modal__closeButton--${closeButtonSkin}`]: true,
                  })}
                >
                  <PktButton
                    onClick={close}
                    aria-label="close"
                    iconName="close"
                    variant="icon-only"
                    size="medium"
                    skin={isCloseButtonSkinDefault ? 'tertiary' : 'primary'}
                  >
                    Lukk
                  </PktButton>
                </div>
              ) : (
                <div className="pkt-modal__noCloseButton" />
              )}
            </div>
          )}
          <div className="pkt-modal__container">
            <div id="pkt-modal__content" className="pkt-modal__content pkt-txt-18-light">
              {children}
            </div>
          </div>
        </div>
      </dialog>
    )
  },
)

PktModal.displayName = 'PktModal'
