import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api } from "./api";
import { config } from "./config";

export type StarterKey = "policy" | "booking" | "menu" | "about" | "contact";

export interface StarterPage {
    key: StarterKey;
    id: number;
    title: string;
    link: string;
    edit_link: string;
    status: string;
    /** Saved since it was made: Remove keeps it unless told otherwise. */
    edited: boolean;
}

export interface FloorCounts {
    areas: number;
    tables: number;
    shifts: number;
}

/** StarterContent::status(). */
export interface StarterStatus {
    created: boolean;
    created_at: number | null;
    pages: StarterPage[];
    /** The sample areas, tables and shifts still there. */
    floor: FloorCounts;
    front_page: boolean;
    menu: boolean;
    can: {
        /** The floor is empty, so a sample one can be made. */
        floor: boolean;
        /** A classic theme with a free menu location. */
        menu: boolean;
    };
    /** What the site needs before a guest can book, sample or not. */
    checklist: { tables: boolean; shifts: boolean; booking_page: boolean };
    booking_url: string;
}

export interface StarterOptions {
    floor: boolean;
    front_page: boolean;
    menu: boolean;
}

export type KeptReason = "edited" | "fxtr_table_booked" | "fxtr_area_has_tables" | "fxtr_shift_booked" | "failed";

export interface KeptItem {
    type: "page" | "table" | "area" | "shift";
    id: number;
    name: string;
    reason: KeptReason;
}

export interface RemoveResult {
    removed: { pages: number } & FloorCounts;
    kept: KeptItem[];
    status: StarterStatus;
}

export type OnboardingStatus = "pending" | "in_progress" | "completed" | "dismissed";

export interface OnboardingState {
    status: OnboardingStatus;
    started_at: number | null;
    completed_at: number | null;
    dismissed_at: number | null;
}

export const starterKey = ["fxtr-starter"] as const;
export const onboardingKey = ["fxtr-onboarding"] as const;

export const getStarter = () => api.get<StarterStatus>("starter");

export const createStarter = (options: StarterOptions) => api.post<StarterStatus>("starter", options);

/** The front page goes back to what it was before; the pages stay. */
export const releaseFront = () => api.post<StarterStatus>("starter/release-front", {});

export const removeStarter = (includeEdited: boolean) => api.post<RemoveResult>("starter/remove", { include_edited: includeEdited });

export const postOnboarding = (status: OnboardingStatus) => api.post<OnboardingState>("onboarding", { status });

/** Missing state never shows the welcome: a returning owner is not trapped behind it. */
export function initialOnboarding(): OnboardingState {
    return (
        config().onboarding ?? {
            status: "completed",
            started_at: null,
            completed_at: null,
            dismissed_at: null,
        }
    );
}

/** The checklist is done: the site takes bookings. */
export function ready(status: StarterStatus): boolean {
    return status.checklist.tables && status.checklist.shifts && status.checklist.booking_page;
}

export function useOnboarding() {
    return useQuery({ queryKey: onboardingKey, queryFn: () => api.get<OnboardingState>("onboarding"), initialData: initialOnboarding, staleTime: Infinity });
}

/** Optimistic: the status is a small enum, so the screen moves at once and steps back on an error. */
export function useOnboardingStatus() {
    const client = useQueryClient();

    return useMutation({
        mutationFn: postOnboarding,
        onMutate: async (status) => {
            await client.cancelQueries({ queryKey: onboardingKey });
            const before = client.getQueryData<OnboardingState>(onboardingKey);
            if (before) {
                client.setQueryData<OnboardingState>(onboardingKey, { ...before, status });
            }

            return { before };
        },
        onError: (_err, _status, context) => {
            if (context?.before) {
                client.setQueryData(onboardingKey, context.before);
            }
        },
        onSuccess: (state) => client.setQueryData(onboardingKey, state),
    });
}
