"use client";
import { AtUri } from "@atproto/api";
import { PubIcon } from "components/ActionBar/Publications";
import { usePubTheme } from "components/ThemeManager/PublicationThemeProvider";
import { BaseThemeProvider } from "components/ThemeManager/ThemeProvider";
import { blobRefToSrc } from "src/utils/blobRefToSrc";
import type {
  NormalizedDocument,
  NormalizedPublication,
} from "src/utils/normalizeRecords";
import { hasLeafletContent } from "lexicons/src/normalize";
import type { Post } from "app/(home-pages)/reader/getReaderFeed";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { TagPopover } from "./InteractionsPreview";
import { useLocalizedDate } from "src/hooks/useLocalizedDate";
import { useSmoker } from "./Toast";
import { CommentTiny } from "./Icons/CommentTiny";
import { QuoteTiny } from "./Icons/QuoteTiny";
import { ShareTiny } from "./Icons/ShareTiny";
import { useSelectedPostListing } from "src/useSelectedPostState";
import { mergePreferences } from "src/utils/mergePreferences";
import { ExternalLinkTiny } from "./Icons/ExternalLinkTiny";
import { getDocumentURL } from "app/lish/createPub/getPublicationURL";
import { RecommendButton } from "./RecommendButton";
import { getFirstParagraph } from "src/utils/getFirstParagraph";

export const PostListing = (props: Post & { selected?: boolean }) => {
  let pubRecord = props.publication?.pubRecord as
    | NormalizedPublication
    | undefined;

  let postRecord = props.documents.data as NormalizedDocument | null;

  // Don't render anything for records that can't be normalized (e.g., site.standard records without expected fields)
  if (!postRecord) {
    return null;
  }
  let postUri = new AtUri(props.documents.uri);
  let uri = props.publication ? props.publication?.uri : props.documents.uri;

  // For standalone documents (no publication), pass isStandalone to get correct defaults
  let isStandalone = !pubRecord;
  let theme = usePubTheme(pubRecord?.theme || postRecord?.theme, isStandalone);
  let themeRecord = pubRecord?.theme || postRecord?.theme;
  let elRef = useRef<HTMLDivElement>(null);
  let [hasBackgroundImage, setHasBackgroundImage] = useState(false);

  useEffect(() => {
    if (!themeRecord?.backgroundImage?.image || !elRef.current) {
      setHasBackgroundImage(false);
      return;
    }
    let alpha = Number(
      window
        .getComputedStyle(elRef.current)
        .getPropertyValue("--bg-page-alpha"),
    );
    setHasBackgroundImage(alpha < 0.7);
  }, [themeRecord?.backgroundImage?.image]);

  let backgroundImage =
    themeRecord?.backgroundImage?.image?.ref && uri
      ? blobRefToSrc(themeRecord.backgroundImage.image.ref, new AtUri(uri).host)
      : null;

  let backgroundImageRepeat = themeRecord?.backgroundImage?.repeat;
  let backgroundImageSize = themeRecord?.backgroundImage?.width || 500;

  let showPageBackground = pubRecord
    ? pubRecord?.theme?.showPageBackground
    : postRecord.theme?.showPageBackground ?? true;

  let mergedPrefs = mergePreferences(
    postRecord?.preferences,
    pubRecord?.preferences,
  );

  let quotes =
    props.documents.mentionsCount ??
    props.documents.document_mentions_in_bsky?.[0]?.count ??
    0;
  let comments =
    mergedPrefs.showComments === false
      ? 0
      : props.documents.comments_on_documents?.[0]?.count || 0;
  let recommends = props.documents.recommends_on_documents?.[0]?.count || 0;
  let tags = (postRecord?.tags as string[] | undefined) || [];

  // For standalone posts, link directly to the document
  let postUrl = getDocumentURL(postRecord, props.documents.uri, pubRecord);

  return (
    <div className="postListing flex flex-col gap-1">
      <BaseThemeProvider {...theme} local>
        <div
          ref={elRef}
          id={`post-listing-${postUri}`}
          className={`
          relative
          flex flex-col overflow-hidden
          selected-outline  rounded-lg w-full
          ${props.selected ? "outline-2 outline-offset-1 outline-accent-contrast border-accent-contrast" : "hover:outline-accent-contrast hover:border-accent-contrast border-border-light"}
          ${showPageBackground ? "bg-bg-page " : "bg-bg-leaflet"} `}
          style={
            hasBackgroundImage
              ? {
                  backgroundImage: backgroundImage
                    ? `url(${backgroundImage})`
                    : undefined,
                  backgroundRepeat: backgroundImageRepeat
                    ? "repeat"
                    : "no-repeat",
                  backgroundSize: backgroundImageRepeat
                    ? `${backgroundImageSize}px`
                    : "cover",
                }
              : {}
          }
        >
          <Link
            className="h-full w-full absolute top-0 left-0"
            href={postUrl}
          />
          {postRecord.coverImage && (
            <div className="postListingImage">
              <img
                src={blobRefToSrc(postRecord.coverImage.ref, postUri.host)}
                alt={postRecord.title || ""}
                className="w-full h-auto aspect-video object-cover object-top-left rounded"
              />
            </div>
          )}
          <div className="postListingInfo px-3 py-2">
            {postRecord.title && (
              <h3 className="postListingTitle text-primary line-clamp-2 sm:text-lg text-base pb-0.5">
                {postRecord.title}
              </h3>
            )}
            {postRecord.description && postRecord.description !== "" && (
              <p className="postListingDescription text-secondary line-clamp-3 leading-snug sm:text-base text-sm">
                {postRecord.description || getFirstParagraph(postRecord)}
              </p>
            )}
            <div className="flex flex-col-reverse gap-2 text-sm text-tertiary items-center justify-start pt-1.5 w-full">
              {props.publication && pubRecord && (
                <PubInfo
                  href={props.publication.href}
                  pubRecord={pubRecord}
                  uri={props.publication.uri}
                  postRecord={postRecord}
                />
              )}
              <div className="flex flex-row justify-between gap-2 text-xs items-center w-full">
                <PostDate publishedAt={postRecord.publishedAt} />
                {tags.length === 0 ? null : <TagPopover tags={tags!} />}
              </div>
            </div>
          </div>
        </div>
      </BaseThemeProvider>
      <div className="text-sm flex justify-between text-tertiary">
        <Interactions
          postUrl={postUrl}
          quotesCount={quotes}
          commentsCount={comments}
          recommendsCount={recommends}
          tags={tags}
          showComments={mergedPrefs.showComments !== false}
          showMentions={mergedPrefs.showMentions !== false}
          documentUri={props.documents.uri}
          document={postRecord}
          publication={pubRecord}
        />
        <Share postUrl={postUrl} />
      </div>
    </div>
  );
};

const PubInfo = (props: {
  href: string;
  pubRecord: NormalizedPublication;
  uri: string;
  postRecord: NormalizedDocument;
}) => {
  let isLeaflet = hasLeafletContent(props.postRecord);
  let cleanUrl = props.pubRecord.url
    ?.replace(/^https?:\/\//, "")
    .replace(/^www\./, "");

  return (
    <div className="flex flex-col shrink-0 w-full">
      <hr className=" block border-border-light mb-1" />
      <div className="flex justify-between gap-4 w-full ">
        <Link
          href={props.href}
          className="text-accent-contrast font-bold no-underline! text-sm flex gap-[6px] items-center relative grow w-max shrink-0 min-w-0"
        >
          <PubIcon tiny record={props.pubRecord} uri={props.uri} />
          <div className="w-max min-w-0">{props.pubRecord.name}</div>
        </Link>
        {!isLeaflet && (
          <div className="text-sm flex flex-row items-center text-tertiary gap-1  min-w-0">
            <div className="truncate min-w-0">{cleanUrl}</div>
            <ExternalLinkTiny className="shrink-0" />
          </div>
        )}
      </div>
    </div>
  );
};

const PostDate = (props: { publishedAt: string | undefined }) => {
  let localizedDate = useLocalizedDate(props.publishedAt || "", {
    year: "numeric",
    month: "short",
    day: "numeric",
  });
  if (props.publishedAt) {
    return <div className="shrink-0 sm:text-sm text-xs">{localizedDate}</div>;
  } else return null;
};

const Interactions = (props: {
  quotesCount: number;
  commentsCount: number;
  recommendsCount: number;
  tags?: string[];
  postUrl: string;
  showComments: boolean;
  showMentions: boolean;
  documentUri: string;
  document: NormalizedDocument;
  publication?: NormalizedPublication;
}) => {
  let setSelectedPostListing = useSelectedPostListing(
    (s) => s.setSelectedPostListing,
  );
  let selectPostListing = (drawer: "quotes" | "comments") => {
    setSelectedPostListing({
      document_uri: props.documentUri,
      document: props.document,
      publication: props.publication,
      drawer,
    });
  };

  return (
    <div
      className={`flex gap-2 text-tertiary text-sm  items-center justify-between px-1`}
    >
      <div className="postListingsInteractions flex gap-3">
        <RecommendButton
          documentUri={props.documentUri}
          recommendsCount={props.recommendsCount}
        />
        {!props.showMentions || props.quotesCount === 0 ? null : (
          <button
            aria-label="Post quotes"
            onClick={() => selectPostListing("quotes")}
            className="relative flex flex-row gap-1 text-sm items-center hover:text-accent-contrast text-tertiary"
          >
            <QuoteTiny /> {props.quotesCount}
          </button>
        )}
        {!props.showComments || props.commentsCount === 0 ? null : (
          <button
            aria-label="Post comments"
            onClick={() => selectPostListing("comments")}
            className="relative flex flex-row gap-1 text-sm items-center hover:text-accent-contrast text-tertiary"
          >
            <CommentTiny /> {props.commentsCount}
          </button>
        )}
      </div>
    </div>
  );
};

const Share = (props: { postUrl: string }) => {
  let smoker = useSmoker();
  return (
    <button
      id={`copy-post-link-${props.postUrl}`}
      className="flex gap-1 items-center hover:text-accent-contrast relative font-bold"
      onClick={(e) => {
        e.stopPropagation();
        e.preventDefault();
        let mouseX = e.clientX;
        let mouseY = e.clientY;

        if (!props.postUrl) return;
        navigator.clipboard.writeText(
          props.postUrl.includes("http")
            ? props.postUrl
            : `leaflet.pub/${props.postUrl}`,
        );

        smoker({
          text: <strong>Copied Link!</strong>,
          position: {
            y: mouseY,
            x: mouseX,
          },
        });
      }}
    >
      Share <ShareTiny />
    </button>
  );
};
