import { PostMedia, PostReaction } from '../posts/posts.ts'
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { PostInfo } from '../posts/usePostViewModel.ts'
import { useUserStore } from '../../user/user.ts'

interface PostItemProps {
  post: PostInfo
  reactions: PostReaction[]
  addReaction: (emoji: string) => void
  clearReaction: (emoji: string) => void
  hideViewButton?: boolean
}

export default function PostItem({
  post,
  reactions,
  addReaction,
  clearReaction,
  hideViewButton = false,
}: PostItemProps) {
  const formattedDate = post.createdAt.toLocaleString('en-US', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })

  const [visible, setVisible] = useState(false)

  useEffect(() => {
    const timeout = setTimeout(() => setVisible(true))
    return () => {
      clearTimeout(timeout)
    }
  }, [])

  const opacity = visible ? 'opacity-100' : 'opacity-0'

  return (
    <article className={`w-full p-4 ${opacity} transition-opacity duration-500`} key={post.postId}>
      <div className="text-sm text-gray-500 mb-3">
        <span className="text-gray-400 mr-2">@{post.authorName}</span>• {formattedDate}
        {!hideViewButton && (
          <>
            {' • '}
            <Link to={`/p/${post.postId}`} className="ml-2 text-primary-400 hover:underline">
              View
            </Link>
          </>
        )}
      </div>

      <div className="text-gray-800 mb-4 whitespace-pre-wrap">{post.content}</div>

      {post.media.length > 0 && (
        <div className="grid gap-4 grid-cols-1">
          {post.media.map((media) => (
            <PostMediaItem key={media.url.toString()} media={media} />
          ))}
        </div>
      )}

      <PostReactions
        post={post}
        reactions={reactions}
        addReaction={addReaction}
        clearReaction={clearReaction}
      />
    </article>
  )
}

interface PostReactionsProps {
  post: PostInfo
  reactions: PostReaction[]
  addReaction: (emoji: string) => void
  clearReaction: (emoji: string) => void
}

function PostReactions({ post, reactions, addReaction, clearReaction }: PostReactionsProps) {
  const username = useUserStore((state) => state.user?.username)
  return (
    <div className="flex flex-wrap gap-2 mt-3 justify-end">
      {post.possibleReactions.map((emoji) => {
        const count = reactions.filter((r) => r.emoji === emoji).length
        const didReact = reactions.some((r) => r.emoji == emoji && r.authorName == username)
        const onClick = () => {
          if (didReact) {
            clearReaction(emoji)
          } else {
            addReaction(emoji)
          }
        }

        return (
          <PostReactionButton
            key={emoji}
            emoji={emoji}
            didReact={didReact}
            count={count}
            onClick={onClick}
          />
        )
      })}
    </div>
  )
}

interface PostReactionButtonProps {
  emoji: string
  didReact: boolean
  count: number
  onClick: () => void
}

function PostReactionButton({ emoji, didReact, onClick, count }: PostReactionButtonProps) {
  const formattedCount = count < 100 ? count.toString() : `99+`

  return (
    <button
      key={emoji}
      onClick={onClick}
      className={`flex items-center px-2 py-1 rounded-full border cursor-pointer ${
        didReact ? 'bg-gray-100 border-gray-400' : 'bg-white border-gray-200'
      } hover:bg-gray-100 transition-colors`}
    >
      <span className="mr-1">{emoji}</span>
      <span className="text-xs text-gray-600">{formattedCount}</span>
    </button>
  )
}

interface PostMediaProps {
  media: PostMedia
}

function PostMediaItem({ media }: PostMediaProps) {
  const url = new URL(media.url.toString())

  if (location.protocol === 'https:' && url.protocol !== 'https:') {
    url.protocol = 'https:'
  }

  const width = media.width ?? undefined
  const height = media.height ?? undefined
  return (
    <img
      width={width}
      height={height}
      src={url.toString()}
      className="w-full h-auto"
      loading="lazy"
    />
  )
}
