'use client'

import classNames from 'classnames'
import { forwardRef, HTMLAttributes, type JSX, ReactNode, Ref } from 'react'
import type { TCardSkin, TLayout, TTagSkin } from 'shared-types'

import { PktTag } from '../tag/Tag'

export type { TCardSkin, TLayout }
type TCardPadding = 'none' | 'default'
type TCardImageShape = 'square' | 'round'
type TCardTagPosition = 'top' | 'bottom'
type THeadingLevel = 1 | 2 | 3 | 4 | 5 | 6

interface ICardTag {
  skin?: TTagSkin
  iconName?: string
  ariaLabel?: string
  text: string
}

export interface IPktCard extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
  ariaLabel?: string
  metaLead?: string | null
  borderOnHover?: boolean
  metaTrail?: string | null
  layout?: TLayout
  heading?: string
  headingLevel?: THeadingLevel
  image?: { src: string; alt: string }
  imageShape?: TCardImageShape
  clickCardLink?: string | null
  padding?: TCardPadding
  openLinkInNewTab?: boolean
  skin?: TCardSkin
  subheading?: string
  tagPosition?: TCardTagPosition
  tags?: ICardTag[]
  children?: ReactNode
  ref?: Ref<HTMLDivElement>
}

export const PktCard = forwardRef<HTMLDivElement, IPktCard>(
  (
    {
      children,
      className,
      ariaLabel,
      metaLead,
      borderOnHover = true,
      metaTrail,
      layout = 'vertical',
      heading = '',
      headingLevel = 3,
      image,
      imageShape = 'square',
      clickCardLink,
      padding = 'default',
      openLinkInNewTab = false,
      skin = 'outlined',
      subheading = '',
      tagPosition = 'top',
      tags = [],
      ...props
    },
    ref,
  ) => {
    const classes = classNames({
      'pkt-card': true,
      [`pkt-card--${skin}`]: skin,
      [`pkt-card--${layout}`]: layout,
      [`pkt-card--padding-${padding}`]: padding,
      'pkt-card--border-on-hover': borderOnHover,
    })

    const ariaLabelLenke = ariaLabel?.trim() || (heading ? `${heading} lenkekort` : 'lenkekort')
    const ariaLabelVanlig = ariaLabel?.trim() || (heading ? heading : 'kort')

    const HeadingTag = `h${headingLevel}` as keyof JSX.IntrinsicElements

    const renderImage = () => {
      if (!image?.src) return null
      return (
        <div className={classNames('pkt-card__image', `pkt-card__image-${imageShape}`)}>
          <img src={image.src} alt={image.alt || ''} />
        </div>
      )
    }

    const renderTags = () => {
      if (tags.length === 0) return null
      return (
        <div
          className={classNames('pkt-card__tags', `pkt-card__tags-${tagPosition}`)}
          role="list"
          aria-label={tags.length > 1 ? 'merkelapper' : 'merkelapp'}
        >
          {tags.map((tag, index) => (
            <PktTag
              key={index}
              role="listitem"
              textStyle="normal-text"
              size="medium"
              skin={tag.skin}
              iconName={tag.iconName}
            >
              <span>{tag.text}</span>
            </PktTag>
          ))}
        </div>
      )
    }

    const renderHeading = () => {
      if (!heading || clickCardLink) return null
      return (
        <HeadingTag className="pkt-heading pkt-heading--medium pkt-heading--fw-regular pkt-card__heading">
          {heading}
        </HeadingTag>
      )
    }

    const renderLinkHeading = () => {
      if (!clickCardLink) return null
      return (
        <HeadingTag className="pkt-heading pkt-heading--medium pkt-heading--fw-regular pkt-card__link-heading pkt-card__heading">
          <a
            className="pkt-card__link"
            href={clickCardLink}
            target={openLinkInNewTab ? '_blank' : '_self'}
            rel={openLinkInNewTab ? 'noopener noreferrer' : undefined}
          >
            {heading}
          </a>
        </HeadingTag>
      )
    }

    const renderSubheading = () => {
      if (!subheading) return null
      return <p className="pkt-card__subheading">{subheading}</p>
    }

    const renderHeader = () => {
      if (!heading && !subheading) return null
      return (
        <header className="pkt-card__header">
          {renderHeading()}
          {renderLinkHeading()}
          {renderSubheading()}
        </header>
      )
    }

    const renderMetadata = () => {
      if (!metaLead && !metaTrail) return null
      return (
        <footer className="pkt-card__metadata">
          {metaLead && <span className="pkt-card__metadata-lead">{metaLead}</span>}
          {metaTrail && <span className="pkt-card__metadata-trail">{metaTrail}</span>}
        </footer>
      )
    }

    return (
      <div ref={ref} className={classNames('pkt-card-root', className)} style={{ display: 'block', width: '100%' }}>
        <article {...props} className={classes} aria-label={clickCardLink ? ariaLabelLenke : ariaLabelVanlig}>
          {renderImage()}
          <div className="pkt-card__wrapper">
            {tagPosition === 'top' && renderTags()}
            {renderHeader()}
            <section className="pkt-card__content">{children}</section>
            {tagPosition === 'bottom' && renderTags()}
            {renderMetadata()}
          </div>
        </article>
      </div>
    )
  },
)

PktCard.displayName = 'PktCard'
