import PrefetchLink from '@/components/PrefetchLink'
import ResponsiveMarqueeText from '@/components/ResponsiveMarqueeText'
import { cn } from '@/lib/utils'

import type { ComponentProps, CSSProperties, FC, HTMLAttributes } from 'react'

import type { Category, Tag } from '@/types'

type LightweightTag = {
    name:     string
    category: Category }

type FullCommonProps = {
    tag:        Tag
    nestLevel?: number
    truncateOnMobile?: boolean
    withWiki?:  boolean
    withCount?: boolean }

type PropsWithLink =
    & FullCommonProps
    & { linkFlg?: true }
    & Partial<ComponentProps<typeof PrefetchLink>>

type PropsWithoutLink =
    & FullCommonProps
    & { linkFlg: false }
    & Partial<HTMLAttributes<HTMLSpanElement>>

type LightweightPropsWithLink =
    & {
	tag:              LightweightTag
	nestLevel?:       number
	truncateOnMobile?: boolean
	withWiki:         false
	withCount:        false
	linkFlg?:         true }
    & Partial<ComponentProps<typeof PrefetchLink>>

type LightweightPropsWithoutLink =
    & {
	tag:              LightweightTag
	nestLevel?:       number
	truncateOnMobile?: boolean
	withWiki:         false
	withCount:        false
	linkFlg:          false }
    & Partial<HTMLAttributes<HTMLSpanElement>>

type Props =
    | PropsWithLink
    | PropsWithoutLink
    | LightweightPropsWithLink
    | LightweightPropsWithoutLink

const isFullTag = (tag: Tag | LightweightTag): tag is Tag =>
    'id' in tag


const TagLink: FC<Props> = ({ tag,
			      nestLevel = 0,
			      linkFlg   = true,
			      truncateOnMobile = false,
			      withWiki  = true,
			      withCount = true,
			      className,
			      style,
			      title,
			      ...props }) => {
  const colourStyle = {
      '--tag-link-colour': `var(--tag-colour-${ tag.category })`,
      '--tag-link-hover-colour': `var(--tag-colour-${ tag.category }-hover)`,
      ...style,
  } as CSSProperties
  const spanClass = 'tag-link-colour'
  const linkClass = 'tag-link-colour tag-link-hover-colour'
  const textClass = 'group min-w-0 max-w-full overflow-hidden align-bottom'
  const markerWrapClass = 'shrink-0 self-start md:self-auto'
  const countClass = 'shrink-0 self-end md:self-auto'
  const matchedAlias = isFullTag (tag) ? tag.matchedAlias : null
  const textTitle = title
      ?? (matchedAlias == null ? tag.name : `${ matchedAlias } → ${ tag.name }`)

  return (
      <span
	  className={cn (
	      'inline-flex min-w-0 max-w-full flex-nowrap items-stretch align-baseline',
	      'gap-x-1 md:items-baseline')}>
	{(linkFlg && withWiki && isFullTag (tag)) && (
	    <span className={markerWrapClass}>
	      {(tag.materialId != null || tag.hasWiki || tag.hasDeerjikists)
	       ? (
		  tag.materialId == null && !(tag.hasDeerjikists)
		  ? (
		      <PrefetchLink
			  to={`/wiki/${ encodeURIComponent (tag.name) }`}
			  className={linkClass}
			  style={colourStyle}>
			?
		      </PrefetchLink>)
		  : (
		      tag.materialId != null
		      ? (
			  <PrefetchLink
			      to={`/materials/${ tag.materialId }`}
			      className={linkClass}
			      style={colourStyle}>
			    ?
			  </PrefetchLink>)
		      : (
			  <PrefetchLink
			      to={`/tags/${ tag.id }/deerjikists`}
			      className={linkClass}
			      style={colourStyle}>
			    ?
			  </PrefetchLink>)))
	       : (
		  ['character', 'material'].includes (tag.category)
		  ? (
		      <PrefetchLink
			  to={`/materials/new?tag=${ encodeURIComponent (tag.name) }`}
			  className="animate-[wiki-blink_.25s_steps(2,end)_infinite]
				     dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]"
			  title={`${ tag.name } 素材情報が存在しません．`}>
			!
		      </PrefetchLink>)
		  : (
		      tag.category === 'deerjikist'
		      ? (
			  <PrefetchLink
			      to={`/tags/${ tag.id }/deerjikists`}
			      className="animate-[wiki-blink_.25s_steps(2,end)_infinite]
					 dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]"
			      title={`${ tag.name } に関する情報が存在しません．`}>
			    !
			  </PrefetchLink>)
		      : (
			  <PrefetchLink
			      to={`/wiki/${ encodeURIComponent (tag.name) }`}
			      className="animate-[wiki-blink_.25s_steps(2,end)_infinite]
					 dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]"
			      title={`${ tag.name } Wiki が存在しません．`}>
			    !
			  </PrefetchLink>)))}
	    </span>)}
	{nestLevel > 0 && (
	    <span
		className="ml-1 mr-1 shrink-0"
		style={{ paddingLeft: `${ (nestLevel - 1) }rem` }}>
	      ↳
	    </span>)}
	{matchedAlias != null && (
	    <>
	      <span
		  title={textTitle}
		  className={cn (spanClass, textClass, className)}
		  style={colourStyle}
		  {...props}>
		<ResponsiveMarqueeText
		    text={matchedAlias}
		    title={textTitle}
		    truncateOnMobile={truncateOnMobile}/>
	      </span>
	      <span className="shrink-0"> → </span>
	    </>)}
	{linkFlg
	 ? (
	    <PrefetchLink
		to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}
		title={textTitle}
		className={cn (linkClass, textClass, className)}
		style={colourStyle}
		{...props}>
	      <ResponsiveMarqueeText
		  text={tag.name}
		  title={textTitle}
		  truncateOnMobile={truncateOnMobile}/>
	    </PrefetchLink>)
	 : (
	    <span
		  title={textTitle}
		  className={cn (spanClass, textClass, className)}
		  style={colourStyle}
		  {...props}>
	      <ResponsiveMarqueeText
		  text={tag.name}
		  title={textTitle}
		  truncateOnMobile={truncateOnMobile}/>
	    </span>)}
	{(withCount && isFullTag (tag)) && (
	    <span className={countClass}>{tag.postCount}</span>)}
      </span>)
}

export default TagLink
