import {
  Sheet,
  Button,
  Paragraph,
  YStack,
  XStack,
  isWeb,
  useWindowDimensions,
  Anchor,
} from '@my/ui'
import { MoreHorizontal, Bookmark, BookmarkX } from '@tamagui/lucide-icons'
import { CardProps } from 'app/types'
import { getCardsOnTopic } from 'app/utils/catalog/getCardsOnTopic'
import { useState } from 'react'

const contentOffset = 24
const linkColor = '#06CAEB'

function CardActionButton({
  card,
  saveCardToMemberCollection,
  unsaveCardFromMemberCollection,
}: {
  card: CardProps
  saveCardToMemberCollection: Function
  unsaveCardFromMemberCollection: Function
}) {
  const [open, setOpen] = useState(false)

  const openMenuSheet = () => {
    setOpen(true)
  }

  const cardActionButtonStyle = isWeb
    ? {
        fontFamily: 'Spline+Sans',
        fontWeight: 400,
        transform: [{ scaleX: 1.03 }, { scaleY: 0.97 }],
        size: '$5',
        letterSpacing: 0.3,
      }
    : {
        fontFamily: 'SplineSansLight',
        fontWeight: 400,
        transform: [{ scaleX: 1.03 }, { scaleY: 0.97 }],
        size: '$5',
        letterSpacing: 0.3,
      }

  return (
    <>
      <Button
        icon={MoreHorizontal}
        onPress={openMenuSheet}
        size="$3"
        minWidth={0}
        padding={0}
        backgroundColor="transparent"
      />
      <Sheet modal open={open} onOpenChange={setOpen} dismissOnSnapToBottom snapPointsMode="fit">
        <Sheet.Overlay />
        <Sheet.Handle />
        <Sheet.Frame padding="$4" justifyContent="center" alignItems="center" space="$5">
          {!card.is_in_member_collection ? (
            <Button
              icon={<Bookmark size="$1.5" strokeWidth="$0.25" />}
              onPress={() => {
                saveCardToMemberCollection(card.id, card.topic_id)
              }}
              w="100%"
              jc="flex-start"
              style={cardActionButtonStyle}
            >
              Save
            </Button>
          ) : (
            <Button
              icon={BookmarkX}
              onPress={() => {
                unsaveCardFromMemberCollection(card.id, card.topic_id)
              }}
              w="100%"
              jc="flex-start"
            >
              Unsave
            </Button>
          )}
        </Sheet.Frame>
      </Sheet>
    </>
  )
}

function CardTitle({ card }: { card: CardProps }) {
  const cardTitleStyle = isWeb
    ? {
        fontFamily: 'Spline+Sans',
        fontWeight: 500,
      }
    : { fontFamily: 'SplineSansMedium' }

  return (
    <Paragraph
      style={cardTitleStyle}
      transform={[{ scaleX: 1.03 }, { scaleY: 0.97 }]}
      size="$8"
      letterSpacing={0.3}
      lineHeight={isWeb ? '$8' : '$9'}
      flex={1}
    >
      {card.topic}: {card.title}
    </Paragraph>
  )
}

function CardContent({
  card,
  database,
  insertDataAfterIndex,
  indexInList,
}: {
  card: CardProps
  database: any
  insertDataAfterIndex: Function
  indexInList: number
}) {
  const cardContentStyle = isWeb
    ? {
        fontFamily: 'Spline+Sans',
        fontWeight: 300,
      }
    : { fontFamily: 'SplineSansLight' }

  const insertCardsOnTopic = async (topic) => {
    const cards = await getCardsOnTopic(database, topic)
    insertDataAfterIndex(cards, indexInList)
  }

  const renderLinks = (content) => {
    const regex = /(\{\{(.*?)\|(.*?)\}\}|\[\[(.*?)\|(.*?)\]\])/g
    const parts: (string | JSX.Element)[] = []
    let lastIndex = 0

    content.replace(
      regex,
      (
        match,
        _,
        display_text_ext,
        destination_link,
        display_text_int,
        destination_topic,
        index
      ) => {
        parts.push(content.slice(lastIndex, index))
        lastIndex = index + match.length
        if (match.startsWith('{{')) {
          parts.push(
            <Anchor
              href={destination_link}
              style={{ color: linkColor, ...cardContentStyle }}
              transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
              fontSize="$5"
              letterSpacing={0.3}
              lineHeight={isWeb ? '$6' : '$8'}
              textDecorationLine="none"
            >
              {display_text_ext}
            </Anchor>
          )
        } else if (match.startsWith('[[')) {
          parts.push(
            <Paragraph
              style={{ color: linkColor, ...cardContentStyle }}
              transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
              size="$5"
              letterSpacing={0.3}
              lineHeight={isWeb ? '$6' : '$8'}
              userSelect="none"
              onPress={() => insertCardsOnTopic(destination_topic)}
            >
              {display_text_int}
            </Paragraph>
          )
        }
        return match
      }
    )

    parts.push(content.slice(lastIndex))
    return parts
  }

  return (
    <YStack gap="$2">
      {card.edited_contents.map((content, indexInList) => (
        <Paragraph
          key={indexInList}
          style={cardContentStyle}
          transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
          size="$5"
          letterSpacing={0.3}
          lineHeight={isWeb ? '$6' : '$8'}
        >
          {typeof content === 'string' ? renderLinks(content) : content}
        </Paragraph>
      ))}
      {card.showElaborateOption && (
        <ElaborateOnTopic
          card={card}
          database={database}
          insertDataAfterIndex={insertDataAfterIndex}
          indexInList={indexInList}
          insertCardsOnTopic={insertCardsOnTopic}
        />
      )}
    </YStack>
  )
}

function ElaborateOnTopic({
  card,
  database,
  insertDataAfterIndex,
  indexInList,
  insertCardsOnTopic,
}: {
  card: CardProps
  database: any
  insertDataAfterIndex: Function
  indexInList: number
  insertCardsOnTopic: Function
}) {
  if (!card.showElaborateOption) return null

  const cardContentStyle = isWeb
    ? {
        fontFamily: 'Spline+Sans',
        fontWeight: 300,
      }
    : { fontFamily: 'SplineSansLight' }

  return (
    <Paragraph
      style={cardContentStyle}
      transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
      size="$5"
      letterSpacing={0.3}
      lineHeight={isWeb ? '$6' : '$8'}
    >
      Elaborate on{' '}
      <Paragraph
        style={{ color: linkColor, ...cardContentStyle }}
        transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
        size="$5"
        letterSpacing={0.3}
        lineHeight={isWeb ? '$6' : '$8'}
        userSelect="none"
        onPress={() => insertCardsOnTopic(card.topic)}
      >
        {card.topic}
      </Paragraph>
      .
    </Paragraph>
  )
}

export function Card({
  card,
  database,
  insertDataAfterIndex,
  indexInList,
  saveCardToMemberCollection,
  unsaveCardFromMemberCollection,
}: {
  card: CardProps
  database: any
  insertDataAfterIndex: Function
  indexInList: number
  saveCardToMemberCollection: Function
  unsaveCardFromMemberCollection: Function
}) {
  const dimensions = useWindowDimensions()

  return (
    <YStack
      width={dimensions.width - 2 * contentOffset}
      maxWidth={500}
      ml={contentOffset}
      mr={contentOffset}
      gap="$3"
    >
      <XStack jc="space-between" ai="flex-start" gap="$3">
        <CardTitle card={card} />
        {!card.hideActionButton && (
          <CardActionButton
            card={card}
            saveCardToMemberCollection={saveCardToMemberCollection}
            unsaveCardFromMemberCollection={unsaveCardFromMemberCollection}
          />
        )}
      </XStack>
      <CardContent
        card={card}
        database={database}
        insertDataAfterIndex={insertDataAfterIndex}
        indexInList={indexInList}
      />
    </YStack>
  )
}
