import {
  type CSSProperties,
  type MouseEvent,
  type TouchEvent,
  useEffect,
  useRef,
  useState,
} from "react"
import { useIntl } from "react-intl"

import { Typography } from "@scandic-hotels/design-system/Typography"

import { debounce } from "@/utils/debounce"

import styles from "./digitalTeamMemberCard.module.css"

import type { User } from "@/types/user"

interface DigitalTeamMemberCardCardProps {
  user: User
}

export default function DigitalTeamMemberCardContent({
  user,
}: DigitalTeamMemberCardCardProps) {
  const intl = useIntl()
  const cardRef = useRef<HTMLDivElement>(null)
  const [isHovering, setIsHovering] = useState(false)
  const [coords, setCoords] = useState({ x: 0, y: 0 })
  const [rect, setRect] = useState<DOMRect>({
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    height: 0,
    width: 0,
    x: 0,
    y: 0,
    toJSON() {},
  })
  let ticking = false
  let animationFrame = 0

  useEffect(() => {
    const observer = new ResizeObserver(
      debounce(() => {
        const el = cardRef.current
        if (!el) return
        const rect = el.getBoundingClientRect()
        setRect(rect)
      })
    )
    observer.observe(document.body)
    return () => {
      observer.unobserve(document.body)
    }
  }, [])

  function requestTick(
    evt: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>
  ) {
    if (!ticking) {
      animationFrame = requestAnimationFrame(update(evt))
    }
    ticking = true
  }

  function onInteractionMove(
    evt: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>
  ) {
    requestTick(evt)
  }

  function update(
    evt: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>
  ) {
    return () => {
      let x, y
      if ("touches" in evt) {
        x = evt.touches[0].clientX - rect.left
        y = evt.touches[0].clientY - rect.top
      } else {
        x = evt.clientX - rect.left
        y = evt.clientY - rect.top
      }
      setCoords({ x, y })
    }
  }

  function getShimmerStyle(): CSSProperties {
    const { x, y } = coords
    const oppositeX = 100 - (x / rect.width) * 100
    const oppositeY = 100 - (y / rect.height) * 100
    return {
      background: `radial-gradient(circle at ${oppositeX}% ${oppositeY}%, rgb(233 171 163 / 40%) 0%, rgb(255 255 255 / 0%) 50%)`,
      opacity: isHovering ? 1 : 0,
    }
  }

  function getSkewStyle(): CSSProperties {
    const { x, y } = coords
    const centerX = rect.width / 2
    const centerY = rect.height / 2
    const rotateY = ((x - centerX) / centerX) * 5 // Max 5 degrees
    const rotateX = ((centerY - y) / centerY) * 5 // Max 5 degrees

    return {
      transform: isHovering
        ? `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
        : "rotateX(0) rotateY(0)",
    }
  }

  function handleInteractionStart() {
    setIsHovering(true)
  }

  function handleInteractionEnd() {
    setIsHovering(false)
    cancelAnimationFrame(animationFrame)
  }

  return (
    <div
      className={styles.cardContainer}
      onMouseEnter={handleInteractionStart}
      onMouseMove={onInteractionMove}
      onMouseLeave={handleInteractionEnd}
      onTouchStart={handleInteractionStart}
      onTouchMove={onInteractionMove}
      onTouchEnd={handleInteractionEnd}
    >
      <div className={styles.card} ref={cardRef} style={getSkewStyle()}>
        <div className={styles.shimmer} style={getShimmerStyle()} />
        <div className={styles.content}>
          <Typography variant="Tag/sm">
            <div className={styles.top}>
              <span>
                {intl.formatMessage({ defaultMessage: "Team Member" })}
              </span>
              {/* TODO: Should display country of employment */}
              {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
              <span>SWE</span>
            </div>
          </Typography>
          <div className={styles.middle}>
            <div className={styles.employeeNumber}>
              <Typography variant="Title/sm">
                {/* TODO: Should display employee number */}
                {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
                <div>123 456</div>
              </Typography>
              <svg
                width="42"
                height="42"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
                className={styles.icon}
              >
                <path
                  d="M3.5 35V12.288C3.5 8.933 3.5 7 4.268 7c.912 0 1.569 1.156 3.17 3.978l11.374 20.044C20.413 33.844 21.041 35 21.982 35c.768 0 .768-1.933.768-5.288V7M28 22.75h10.5M29.016 8.016c1.355-1.355 7.113-1.355 8.468 0 1.355 1.355 1.355 7.113 0 8.468-1.355 1.355-7.114 1.355-8.468 0-1.355-1.355-1.355-7.113 0-8.468Z"
                  strokeWidth="2.625"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                />
              </svg>
            </div>

            <Typography variant="Title/md">
              <div>
                {user.firstName} {user.lastName}
              </div>
            </Typography>
          </div>
          <Typography variant="Tag/sm">
            <div className={styles.bottom}>
              <span>
                {/* TODO: Should display department of employment */}
                {/* eslint-disable formatjs/no-literal-string-in-jsx */}
                Haymarket by Scandic
                {/* eslint-enable */}
              </span>
              {/* TODO: Should display current state of employment */}
              {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
              <span>Employee</span>
            </div>
          </Typography>
        </div>
      </div>
    </div>
  )
}
