'use client';

import { fetchFileSource } from "@/app/api/(client)/client";
import { base64Decode } from "@/lib/utils";
import { useQuery } from "@tanstack/react-query";
import { CodePreview, CodePreviewFile } from "./codePreview";
import { SearchResultFile } from "@/lib/types";
import { useDomain } from "@/hooks/useDomain";
import { SymbolIcon } from "@radix-ui/react-icons";
interface CodePreviewPanelProps {
    fileMatch?: SearchResultFile;
    onClose: () => void;
    selectedMatchIndex: number;
    onSelectedMatchIndexChange: (index: number) => void;
    repoUrlTemplates: Record<string, string>;
}

export const CodePreviewPanel = ({
    fileMatch,
    onClose,
    selectedMatchIndex,
    onSelectedMatchIndexChange,
    repoUrlTemplates,
}: CodePreviewPanelProps) => {
    const domain = useDomain();

    const { data: file, isLoading } = useQuery({
        queryKey: ["source", fileMatch?.FileName, fileMatch?.Repository, fileMatch?.Branches],
        queryFn: async (): Promise<CodePreviewFile | undefined> => {
            if (!fileMatch) {
                return undefined;
            }

            // If there are multiple branches pointing to the same revision of this file, it doesn't
            // matter which branch we use here, so use the first one.
            const branch = fileMatch.Branches && fileMatch.Branches.length > 0 ? fileMatch.Branches[0] : undefined;

            return fetchFileSource({
                fileName: fileMatch.FileName,
                repository: fileMatch.Repository,
                branch,
            }, domain)
                .then(({ source }) => {
                    const link = (() => {
                        const template = repoUrlTemplates[fileMatch.Repository];

                        // This is a hacky parser for templates generated by
                        // the go text/template package. Example template:
                        // {{URLJoinPath "https://github.com/sourcebot-dev/sourcebot" "blob" .Version .Path}}
                        // @see: https://pkg.go.dev/text/template
                        if (!template || !template.match(/^{{URLJoinPath\s.*}}(\?.+)?$/)) {
                            return undefined;
                        }

                        const url =
                            template.substring("{{URLJoinPath ".length,template.indexOf("}}"))
                            .replace(".Version", branch ?? "HEAD")
                            .replace(".Path", fileMatch.FileName)
                            .split(" ")
                            .map((part) => {
                                // remove wrapping quotes
                                if (part.startsWith("\"")) part = part.substring(1);
                                if (part.endsWith("\"")) part = part.substring(0, part.length - 1);
                                return part;
                            })
                            .join("/");

                        const optionalQueryParams = 
                            template.substring(template.indexOf("}}") + 2)
                            .replace("{{.Version}}", branch ?? "HEAD")
                            .replace("{{.Path}}", fileMatch.FileName);

                        return url + optionalQueryParams;
                    })();

                    const decodedSource = base64Decode(source);

                    // Filter out filename matches
                    const filteredMatches = fileMatch.ChunkMatches.filter((match) => {
                        return !match.FileName;
                    });

                    return {
                        content: decodedSource,
                        filepath: fileMatch.FileName,
                        matches: filteredMatches,
                        link: link,
                        language: fileMatch.Language,
                        revision: branch ?? "HEAD",
                    };
                });
        },
        enabled: fileMatch !== undefined,
    });

    if (isLoading) {
        return <div className="flex flex-col items-center justify-center h-full">
            <SymbolIcon className="h-6 w-6 animate-spin" />
            <p className="font-semibold text-center">Loading...</p>
        </div>
    }

    return (
        <CodePreview
            file={file}
            repoName={fileMatch?.Repository}
            onClose={onClose}
            selectedMatchIndex={selectedMatchIndex}
            onSelectedMatchIndexChange={onSelectedMatchIndexChange}
        />
    )
}