import {
    type Accessor,
    type Component,
    type ParentProps,
    createContext,
    createMemo,
    createResource,
    useContext,
} from "solid-js";
import { deleteImage, deleteImageFromStack, getUserImages, JustTheImageWhatAreTheseNames, reprocessImage } from "../network";

export type SearchImageStore = {
    imagesByDate: Accessor<
        Array<{ date: Date; images: JustTheImageWhatAreTheseNames }>
    >;

    lists: Accessor<Awaited<ReturnType<typeof getUserImages>>["lists"]>;

    userImages: Accessor<JustTheImageWhatAreTheseNames>;

    processingImages: Accessor<
        Awaited<ReturnType<typeof getUserImages>>["processingImages"] | undefined
    >;

    onRefetchImages: () => void;
    onDeleteImage: (imageID: string) => void;
    onDeleteImageFromStack: (stackID: string, imageID: string) => void;
    onRefreshImage: (imageID: string) => void;
};

const SearchImageContext = createContext<SearchImageStore>();
export const SearchImageContextProvider: Component<ParentProps> = (props) => {
    const [data, { refetch }] = createResource(getUserImages);

    const sortedImages = createMemo<ReturnType<SearchImageStore["imagesByDate"]>>(
        () => {
            const d = data();
            if (d == null) {
                return [];
            }

            // Sorted by day. But we could potentially add more in the future.
            const buckets: Record<string, JustTheImageWhatAreTheseNames> = {};

            for (const image of d.userImages) {
                if (image.CreatedAt == null) {
                    continue;
                }

                const date = new Date(image.CreatedAt).toDateString();
                if (!(date in buckets)) {
                    buckets[date] = [];
                }

                buckets[date].push(image);
            }

            return Object.entries(buckets)
                .map(([date, images]) => ({ date: new Date(date), images }))
                .sort((a, b) => b.date.getTime() - a.date.getTime());
        },
    );

    const processingImages = () => data()?.processingImages ?? [];

    return (
        <SearchImageContext.Provider
            value={{
                imagesByDate: sortedImages,
                lists: () => data()?.lists ?? [],
                userImages: () => data()?.userImages ?? [],
                processingImages,
                onRefetchImages: refetch,
                onDeleteImage: (imageID: string) => {
                    deleteImage(imageID).then(refetch);
                },
                onDeleteImageFromStack: (stackID: string, imageID: string) => {
                    deleteImageFromStack(stackID, imageID).then(refetch);
                },
                onRefreshImage: (imageID: string) => {
                    reprocessImage(imageID).then(refetch)
                }
            }}
        >
            {props.children}
        </SearchImageContext.Provider>
    );
};

export const useSearchImageContext = () => {
    const context = useContext(SearchImageContext);
    if (context == null) {
        throw new Error(
            "Unreachable: We should always have a mounted context and no undefined values",
        );
    }

    return context;
};
