import { Check, Copy } from "lucide-react";
import React, {
    DetailedHTMLProps,
    HTMLAttributes,
    PropsWithChildren,
} from "react";
import { twMerge } from "tailwind-merge";
import Stack from "../layout/Stack";
import Row from "../layout/Row";
import Button from "../layout/Button";
import Divider from "../layout/Divider";

export const TWUIPrismLanguages = ["shell", "javascript"] as const;

type Props = PropsWithChildren &
    DetailedHTMLProps<HTMLAttributes<HTMLPreElement>, HTMLPreElement> & {
        wrapperProps?: DetailedHTMLProps<
            HTMLAttributes<HTMLDivElement>,
            HTMLDivElement
        >;
        "data-title"?: string;
        backgroundColor?: string;
        singleBlock?: boolean;
        language?: (typeof TWUIPrismLanguages)[number];
    };

/**
 * # CodeBlock
 *
 * @className `twui-code-block-wrapper`
 * @className `twui-code-pre-wrapper`
 * @className `twui-code-block-pre`
 * @className `twui-code-block-header`
 */
export default function CodeBlock({
    children,
    wrapperProps,
    backgroundColor,
    singleBlock,
    language,
    ...props
}: Props) {
    const codeRef = React.useRef<HTMLDivElement>(null);

    const [copied, setCopied] = React.useState(false);

    const title = props?.["data-title"];

    const finalBackgroundColor = backgroundColor || "#28272b";

    return (
        <div
            {...wrapperProps}
            className={twMerge(
                "outline-[1px] outline-slate-200 dark:outline-white/10",
                `rounded w-full transition-all items-start`,
                "relative max-w-[80vw] sm:max-w-[85vw] xl:max-w-[880px]",
                "twui-code-block-wrapper",
                wrapperProps?.className
            )}
            style={{
                boxShadow: copied
                    ? "0 0 10px 10px rgba(18, 139, 99, 0.2)"
                    : undefined,
                backgroundColor: finalBackgroundColor,
                ...props.style,
            }}
        >
            <Stack
                className={twMerge(
                    "gap-0 w-full overflow-x-auto relative",
                    "max-h-[600px] overflow-y-auto"
                )}
            >
                <Row
                    className={twMerge(
                        "w-full px-1 h-10 sticky top-0 py-2",
                        singleBlock ? "absolute !bg-transparent" : "",
                        "twui-code-block-header"
                    )}
                    style={{
                        backgroundColor: finalBackgroundColor,
                    }}
                >
                    {title && <span className="text-white/70">{title}</span>}
                    <div className="ml-auto">
                        {copied ? (
                            <Row>
                                <span className="text-white text-xs twui-code-block-copied-text">
                                    Copied!
                                </span>
                                <div className="w-5 h-5 rounded-full bg-emerald-600 text-white flex items-center justify-center">
                                    <Check size={15} />
                                </div>
                            </Row>
                        ) : (
                            <Button
                                variant="ghost"
                                color="gray"
                                beforeIcon={<Copy size={17} color="white" />}
                                className="!p-1 !bg-transparent opacity-50"
                                onClick={() => {
                                    const content =
                                        codeRef.current?.textContent;
                                    if (!content) {
                                        window.alert("No Content to copy");
                                        return;
                                    }

                                    window.navigator.clipboard
                                        .writeText(content)
                                        .then(() => {
                                            setCopied(true);
                                            setTimeout(() => {
                                                setCopied(false);
                                            }, 3000);
                                        });
                                }}
                                title="Copy Code Snippet"
                            />
                        )}
                    </div>
                </Row>
                {!singleBlock && (
                    <Divider className="!border-white/10 sticky top-10" />
                )}
                <div
                    className={twMerge(
                        `p-1 w-full [&_pre]:!bg-transparent`,
                        singleBlock ? "" : "-mt-1",
                        "twui-code-pre-wrapper"
                    )}
                    ref={codeRef as any}
                >
                    <pre
                        {...props}
                        className={twMerge(
                            "!my-0 whitespace-pre-wrap",
                            language ? `language-${language}` : "",
                            "twui-code-block-pre",
                            props.className
                        )}
                    >
                        {children}
                    </pre>
                </div>
            </Stack>
        </div>
    );
}
