import { Check, Copy } from "lucide-react";
import { useMemo } from "react";
import { Button } from "../../button";
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger,
} from "../../hover-card";
import { useCopyToClipboard } from "../hooks/use-copy-to-clipboard";
import { SourceData } from "../index";
import PdfDialog from "../widgets/PdfDialog";
import { useClientConfig } from "../hooks/use-config";

const SCORE_THRESHOLD = 0.3;

function truncateNumber(num: number | undefined, precision: number): number {
  if (num == undefined || num == 0) return 0;
  const factor = Math.pow(10, precision);
  return Math.trunc(num * factor) / factor;
}

function SourceNumberButton({ index, score }: { index: number, score: number | undefined }) {
  return (
    <div className="text-xs w-45 h-45 rounded-full bg-gray-100 mb-2 flex items-center justify-center hover:text-white hover:bg-primary hover:cursor-pointer">
      {truncateNumber(score, 2)}
    </div>
  );
}

type NodeInfo = {
  id: string;
  score?: number;
  text: string;
  url?: string;
};

export function ChatSources({ data }: { data: SourceData }) {
  const { backend } = useClientConfig();
  const sources: NodeInfo[] = useMemo(() => {
    // aggregate nodes by url or file_path (get the highest one by score)
    const nodesByPath: { [path: string]: NodeInfo } = {};

    data.nodes
      .filter((node) => (node.score ?? 1) > SCORE_THRESHOLD)
      .sort((a, b) => (b.score ?? 1) - (a.score ?? 1))
      .forEach((node) => {
        const nodeInfo = {
          id: node.id,
          score: node.score,
          text: node.text,
          url: node.url,
        };
        const key = nodeInfo.url ?? nodeInfo.id; // use id as key for UNKNOWN type
        if (!nodesByPath[key]) {
          nodesByPath[key] = nodeInfo;
        }
      });

    return Object.values(nodesByPath);
  }, [data.nodes]);

  if (sources.length === 0) return null;

  return (
    <div className="space-x-2 text-sm">
      <span className="font-semibold">来源:</span>
      <div className="inline-flex gap-1 items-center">
        {sources.map((nodeInfo: NodeInfo, index: number) => {
          if (nodeInfo.url?.endsWith(".pdf")) {
            return (
              <PdfDialog
                key={nodeInfo.id}
                documentId={nodeInfo.id}
                url={backend+nodeInfo.url}
                trigger={<SourceNumberButton index={index} score={nodeInfo.score} />}
              />
            );
          }
          return (
            <div key={nodeInfo.id}>
              <HoverCard>
                <HoverCardTrigger>
                  <SourceNumberButton index={index} score={nodeInfo.score}/>
                </HoverCardTrigger>
                <HoverCardContent className="w-[450px]">
                  <NodeInfo nodeInfo={nodeInfo} />
                </HoverCardContent>
              </HoverCard>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function NodeInfo({ nodeInfo }: { nodeInfo: NodeInfo }) {
  const { backend } = useClientConfig();
  const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 1000 });

  if (nodeInfo.url) {
    // this is a node generated by the web loader or file loader,
    // add a link to view its URL and a button to copy the URL to the clipboard
    return (
      <div className="flex items-center my-2">
        <a
          className="hover:text-blue-900 truncate"
          href={backend+nodeInfo.url}
          target="_blank"
        >
          <span>{nodeInfo.text}</span>
        </a>
        <Button
          onClick={() => copyToClipboard(nodeInfo.url!)}
          size="icon"
          variant="ghost"
          className="h-12 w-12 shrink-0"
        >
          {isCopied ? (
            <Check className="h-4 w-4" />
          ) : (
            <Copy className="h-4 w-4" />
          )}
        </Button>
      </div>
    );
  }

  // node generated by unknown loader, implement renderer by analyzing logged out metadata
  // return (
  //   <p>
  //     对不起, 未知文件类型. 无法打开当前的来源文件。
  //   </p>
  // );
  return (
    <div className="flex items-center my-2">
        <span>{nodeInfo.text}</span>
      <Button
        onClick={() => copyToClipboard(nodeInfo.url!)}
        size="icon"
        variant="ghost"
        className="h-12 w-12 shrink-0"
      >
        {isCopied ? (
          <Check className="h-4 w-4" />
        ) : (
          <Copy className="h-4 w-4" />
        )}
      </Button>
    </div>
  );
}
