"use client";

import { Check, Copy } from "lucide-react";
import React, { useEffect, useRef, useState } from "react";
import { cn } from "../../lib/utils";

type TSnippetType = "success" | "warning" | "error";

interface SnippetProps {
  text: string | string[];
  width?: string;
  onCopy?: () => void;
  prompt?: boolean;
  dark?: boolean;
  type?: TSnippetType;
}

const variant = {
  default: {
    background: "bg-background-100",
    text: "text-gray-1000",
    fill: "text-gray-1000",
  },
  inverted: {
    background: "bg-gray-100",
    text: "text-gray-100",
    fill: "text-gray-100",
  },
  success: {
    background: "bg-blue-100",
    text: "text-blue-900",
    fill: "text-blue-900",
  },
  warning: {
    background: "bg-amber-100",
    text: "text-amber-900",
    fill: "text-amber-900",
  },
  error: {
    background: "bg-red-100",
    text: "text-red-900",
    fill: "text-red-900",
  },
};

const getVariant = (inverted: boolean, type: TSnippetType | undefined) => {
  if (inverted) {
    return variant.inverted;
  }

  switch (type) {
    case "success":
      return variant.success;
    case "warning":
      return variant.warning;
    case "error":
      return variant.error;
    default:
      return variant.default;
  }
};

export function Snippet({
  text,
  width = "100%",
  onCopy,
  prompt = true,
  dark = false,
  type,
}: SnippetProps) {
  const [animation, setAnimation] = useState(false);
  const animationTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
  const values = typeof text === "string" ? [text] : text;
  const colors = getVariant(dark, type);

  useEffect(() => {
    return () => {
      if (animationTimeout.current) {
        clearTimeout(animationTimeout.current);
      }
    };
  }, []);

  const onClick = async () => {
    if (animationTimeout.current) {
      clearTimeout(animationTimeout.current);
    }

    setAnimation(true);
    animationTimeout.current = setTimeout(() => setAnimation(false), 800);

    const payload = values.join("\n");
    await navigator.clipboard.writeText(payload);

    onCopy?.();
  };

  return (
    <button
      className={cn(
        "flex rounded-md border border-gray-alpha-400 px-3 py-2.5 cursor-pointer",
        colors.background,
      )}
      style={{ width }}
      type="button"
      aria-label="Copy snippet"
      onClick={onClick}
    >
      <div className="mr-3">
        {values.map((item, index) => (
          <div
            key={`${item}-${index}`}
            className={cn(
              "font-mono text-[13px] select-none",
              prompt ? "before:content-['$_']" : "",
              colors.text,
            )}
          >
            {item}
          </div>
        ))}
      </div>
      <div className="relative ml-auto w-4 cursor-pointer flex items-center justify-center flex-col h-full">
        <div className="relative flex items-center justify-center h-4 w-4">
          <Copy
            size={16}
            className={cn(
              "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10",
              colors.fill,
              animation ? "animate-fade-out" : "",
            )}
          />
          <Check
            size={20}
            className={cn(
              "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2  text-purple-500",
              animation ? "animate-fade-in opacity-100" : "opacity-0",
            )}
          />
        </div>
      </div>
    </button>
  );
}
