import { useCallback, useState } from "react";
import { Bookmark, Heart, Link2, MessageCircle, Repeat2 } from "lucide-react";
import type { Tweet } from "../lib/fetching/types";
import { timeAgo } from "../lib/utils/time";
import { LangText } from "prosody-ui";

interface TweetCardProps {
  tweet: Tweet;
  accent: string;
  allowBookmarkRemoval?: boolean;
  onRemoveBookmark?: (tweetId: string) => void;
  onReply?: (tweetId: string, text: string) => Promise<unknown>;
  onToggleRetweet?: (tweetId: string, next: boolean) => Promise<unknown>;
  onToggleLike?: (tweetId: string, next: boolean) => Promise<unknown>;
  onToggleBookmark?: (tweetId: string, next: boolean) => Promise<unknown>;
  onOpenAuthor?: (author: Tweet["author"]) => void;
  onOpenThread?: (tweet: Tweet) => void;
  isQuote?: boolean;
}

type ActionKind = "reply" | "retweet" | "like" | "bookmark" | null;

export function TweetCard(props: TweetCardProps) {
  const {
    tweet,
    accent,
    allowBookmarkRemoval,
    onRemoveBookmark,
    onOpenAuthor,
    onOpenThread,
    isQuote,
  } = props;
  const timestamp = timeAgo(tweet.time);

  return (
    <article
      className="tweet-card"
      lang={tweet.language}
      style={{ borderColor: accent }}
    >
      {tweet.retweeted_by && (
        <p
          onClick={() => onOpenAuthor?.(tweet.retweeted_by!.author)}
          className="muted tiny retweet-banner"
        >
          Retweeted by {tweet.retweeted_by.author.name}
          <span>{timeAgo(tweet.retweeted_by.time)}</span>
        </p>
      )}
      <header>
        <div className="author">
          <img
            src={tweet.author.avatar}
            alt={tweet.author.name}
            loading="lazy"
          />
          <button
            type="button"
            className="link-button author-meta"
            onClick={() => onOpenAuthor?.(tweet.author)}
            title={`View @${tweet.author.username}`}
            disabled={!onOpenAuthor}
          >
            <strong>{tweet.author.name}</strong>
            <span className="muted">@{tweet.author.username}</span>
          </button>
        </div>
        <div className="meta">
          <button
            type="button"
            className="link-button muted"
            onClick={() => onOpenThread?.(tweet)}
            title="Open thread"
            disabled={!onOpenThread}
          >
            {timestamp}
          </button>
          {allowBookmarkRemoval && onRemoveBookmark && (
            <button
              className="ghost"
              onClick={() => onRemoveBookmark(tweet.id)}
            >
              Remove
            </button>
          )}
        </div>
      </header>
      {isQuote && tweet.replyingTo.length > 0 && (
        <div className="tweet-replying-to">
          <span>replying to</span>
          {tweet.replyingTo.map((rt) => (
            <span key={rt.username}>@{rt.username}</span>
          ))}
        </div>
      )}
      <div className="tweet-body">
        <div className="tweet-text">
          <LangText lang={tweet.language} text={tweet.text} />
          {/*renderText(tweet.text)}*/}
        </div>
        {!!tweet.media.pics.length && (
          <div
            className={`media-grid pics-${Math.min(tweet.media.pics.length, 4)}`}
          >
            {tweet.media.pics.map((pic) => (
              <img key={pic} src={pic} alt="Tweet media" loading="lazy" />
            ))}
          </div>
        )}
        {tweet.media.video.url && (
          <div className="video-wrapper">
            <video controls preload="none" poster={tweet.media.video.thumb}>
              <source src={tweet.media.video.url} />
            </video>
          </div>
        )}
        {!!tweet.urls.length && (
          <div className="link-chips">
            {tweet.urls.map((link) => (
              <a
                key={link.expandedUrl}
                href={link.expandedUrl}
                target="_blank"
                rel="noreferrer"
              >
                {link.displayUrl}
              </a>
            ))}
          </div>
          // end body
        )}
        {tweet.quoting && <Quote tweet={tweet.quoting} />}
      </div>
      {!isQuote && <Actions {...props} />}
    </article>
  );
}

type Token = { type: "text" | "mention" | "hashtag" | "url"; value: string };

function tokenize(text: string): Token[] {
  const tokens: Token[] = [];
  const regex = /(https?:\/\/\S+|@[A-Za-z0-9_]+|#[A-Za-z0-9_]+)/g;
  let lastIndex = 0;
  for (const match of text.matchAll(regex)) {
    const value = match[0];
    const index = match.index ?? 0;
    if (index > lastIndex) {
      tokens.push({ type: "text", value: text.slice(lastIndex, index) });
    }
    if (value.startsWith("http")) {
      tokens.push({ type: "url", value });
    } else if (value.startsWith("@")) {
      tokens.push({ type: "mention", value });
    } else if (value.startsWith("#")) {
      tokens.push({ type: "hashtag", value });
    }
    lastIndex = index + value.length;
  }
  if (lastIndex < text.length) {
    tokens.push({ type: "text", value: text.slice(lastIndex) });
  }
  return tokens;
}

function renderText(text: string) {
  return tokenize(text).map((token, index) => {
    if (token.type === "text") {
      return token.value.split("\n").map((segment, segmentIndex, arr) => (
        <span key={`${index}-${segmentIndex}`}>
          {segment}
          {segmentIndex < arr.length - 1 ? <br /> : null}
        </span>
      ));
    }
    if (token.type === "url") {
      return (
        <a key={index} href={token.value} target="_blank" rel="noreferrer">
          {token.value}
        </a>
      );
    }
    if (token.type === "mention") {
      return (
        <span key={index} className="mention">
          {token.value}
        </span>
      );
    }
    return (
      <span key={index} className="hashtag">
        {token.value}
      </span>
    );
  });
}

function Actions(props: TweetCardProps) {
  const { tweet, onReply, onToggleRetweet, onToggleLike, onToggleBookmark } =
    props;

  const tweetUrl = `https://x.com/${tweet.author.username}/status/${tweet.id}`;
  const [copied, setCopied] = useState(false);
  const [pendingAction, setPendingAction] = useState<ActionKind>(null);

  const copyLink = useCallback(async () => {
    try {
      if (navigator?.clipboard?.writeText) {
        await navigator.clipboard.writeText(tweetUrl);
      } else if (typeof document !== "undefined") {
        const textarea = document.createElement("textarea");
        textarea.value = tweetUrl;
        textarea.style.position = "fixed";
        textarea.style.opacity = "0";
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand("copy");
        document.body.removeChild(textarea);
      }
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    } catch (error) {
      console.warn("Failed to copy tweet link", error);
    }
  }, [tweetUrl]);

  const executeAction = useCallback(
    async (kind: ActionKind, fn?: () => Promise<unknown>) => {
      if (!fn) return;
      setPendingAction(kind);
      try {
        await fn();
      } catch (error) {
        console.error(`Failed to perform ${kind ?? "action"}`, error);
      } finally {
        setPendingAction(null);
      }
    },
    [],
  );

  const handleReply = useCallback(() => {
    if (!onReply || typeof window === "undefined") return;
    const prefill = `@${tweet.author.username} `;
    const text = window.prompt("Reply", prefill);
    if (!text || !text.trim()) return;
    executeAction("reply", () => onReply(tweet.id, text.trim()));
  }, [executeAction, onReply, tweet.author.username, tweet.id]);

  const handleRetweet = useCallback(() => {
    if (!onToggleRetweet) return;
    const next = !tweet.rted;
    executeAction("retweet", () => onToggleRetweet(tweet.id, next));
  }, [executeAction, onToggleRetweet, tweet.id, tweet.rted]);

  const handleLike = useCallback(() => {
    if (!onToggleLike) return;
    const next = !tweet.liked;
    executeAction("like", () => onToggleLike(tweet.id, next));
  }, [executeAction, onToggleLike, tweet.id, tweet.liked]);

  const handleBookmark = useCallback(() => {
    if (!onToggleBookmark) return;
    const next = !tweet.bookmarked;
    executeAction("bookmark", () => onToggleBookmark(tweet.id, next));
  }, [executeAction, onToggleBookmark, tweet.bookmarked, tweet.id]);

  return (
    <footer className="tweet-actions">
      <button
        type="button"
        className={`action ${pendingAction === "reply" ? "in-flight" : ""}`}
        aria-label="Reply"
        title="Reply"
        disabled={pendingAction === "reply"}
        onClick={handleReply}
      >
        <MessageCircle />
        <span className="sr-only">Reply</span>
      </button>
      <button
        type="button"
        className={`action retweet ${tweet.rted ? "active" : ""} ${pendingAction === "retweet" ? "in-flight" : ""}`}
        aria-label={tweet.rted ? "Undo Retweet" : "Retweet"}
        aria-pressed={tweet.rted}
        title={tweet.rted ? "Undo Retweet" : "Retweet"}
        disabled={pendingAction === "retweet"}
        onClick={handleRetweet}
      >
        <Repeat2 />
        <span className="sr-only">Retweet</span>
      </button>
      <button
        type="button"
        className={`action like ${tweet.liked ? "active" : ""} ${pendingAction === "like" ? "in-flight" : ""}`}
        aria-label={tweet.liked ? "Undo like" : "Like"}
        aria-pressed={tweet.liked}
        title={tweet.liked ? "Undo like" : "Like"}
        disabled={pendingAction === "like"}
        onClick={handleLike}
      >
        <Heart />
        <span className="sr-only">Like</span>
      </button>
      <button
        type="button"
        className={`action bookmark ${tweet.bookmarked ? "active" : ""} ${pendingAction === "bookmark" ? "in-flight" : ""}`}
        aria-label={tweet.bookmarked ? "Remove bookmark" : "Bookmark"}
        aria-pressed={tweet.bookmarked}
        title={tweet.bookmarked ? "Remove bookmark" : "Bookmark"}
        disabled={pendingAction === "bookmark"}
        onClick={handleBookmark}
      >
        <Bookmark />
        <span className="sr-only">Bookmark</span>
      </button>
      <button
        type="button"
        className={`action ${copied ? "copied" : ""}`}
        aria-label="Copy link"
        title="Copy link"
        onClick={copyLink}
      >
        <Link2 />
        <span className="sr-only">Copy link</span>
      </button>
    </footer>
  );
}

function Quote({ tweet }: { tweet: Tweet }) {
  return (
    <div className="tweet-quote">
      <TweetCard tweet={tweet} accent="" isQuote={true} />
    </div>
  );
}
