import type { InertiaForm } from '@inertiajs/vue3';
import type { FlashProps } from '@/composables/useFlash';
import { isFlashSuccess } from '@/composables/useFlash';

interface ToggleAutoRenewFields {
    auto_renew: boolean;
}

export function toggleAutoRenew(
    newValue: boolean,
    form: InertiaForm<ToggleAutoRenewFields>,
): void {
    if (form.processing) {
        return;
    }

    form.auto_renew = newValue;
    form.post(window.route('subscriptions.toggle-auto-renew'), {
        preserveScroll: true,
    });
}

interface ModifySubscriptionFields {
    to_package_id: number;
    period: 'monthly' | 'annual';
    saved_card_id: number;
    has_foodics_addon: boolean;
    promo_code?: string | null;
}

export interface SubscriptionVisitResult {
    flashError: string | null
    flashSucceeded: boolean
}

function readFlashResult(flash: FlashProps | undefined | null): SubscriptionVisitResult {
    if (!flash) {
        return { flashError: null, flashSucceeded: false }
    }

    if (flash.error) {
        return { flashError: String(flash.error), flashSucceeded: false }
    }

    if (flash.success === false) {
        return {
            flashError: flash.message ? String(flash.message) : 'Request failed',
            flashSucceeded: false,
        }
    }

    return {
        flashError: null,
        flashSucceeded: isFlashSuccess(flash),
    }
}

export function modifySubscription(
    payload: ModifySubscriptionFields,
    form: InertiaForm<ModifySubscriptionFields>,
): Promise<SubscriptionVisitResult> {
    return new Promise((resolve, reject) => {
        if (form.processing) {
            reject(new Error('Form already processing'));

            return;
        }

        form.to_package_id = payload.to_package_id;
        form.period = payload.period;
        form.saved_card_id = payload.saved_card_id;
        form.has_foodics_addon = payload.has_foodics_addon;
        form.promo_code = payload.promo_code ?? null;

        let isSettled = false;
        let visitResult: SubscriptionVisitResult = { flashError: null, flashSucceeded: false };

        form.post(window.route('subscriptions.modify-subscription'), {
            preserveScroll: true,
            // onFlash runs before onSuccess in Inertia — reliable flash capture for dialog flow control.
            // Toast display remains the responsibility of global useFlash().
            onFlash: (flash) => {
                visitResult = readFlashResult(flash as FlashProps);
            },
            onSuccess: () => {
                isSettled = true;
                resolve(visitResult);
            },
            onError: (errors) => {
                isSettled = true;
                reject(errors);
            },
            onFinish: () => {
                if (!isSettled) {
                    // This means we hit a 500 or non-validation error
                    reject(new Error('Internal Server Error'));
                }
            },
        });
    });
}

interface RenewSubscriptionFields {
    saved_card_id: number;
    has_foodics_addon: boolean;
    promo_code?: string | null;
}

export function renewSubscription(
    payload: RenewSubscriptionFields,
    form: InertiaForm<RenewSubscriptionFields>,
): Promise<SubscriptionVisitResult> {
    return new Promise((resolve, reject) => {
        if (form.processing) {
            reject(new Error('Form already processing'));

            return;
        }

        form.saved_card_id = payload.saved_card_id;
        form.has_foodics_addon = payload.has_foodics_addon;
        form.promo_code = payload.promo_code ?? null;

        let isSettled = false;
        let visitResult: SubscriptionVisitResult = { flashError: null, flashSucceeded: false };

        form.post(window.route('subscriptions.renew'), {
            preserveScroll: true,
            onFlash: (flash) => {
                visitResult = readFlashResult(flash as FlashProps);
            },
            onSuccess: () => {
                isSettled = true;
                resolve(visitResult);
            },
            onError: (errors) => {
                isSettled = true;
                reject(errors);
            },
            onFinish: () => {
                if (!isSettled) {
                    reject(new Error('Internal Server Error'));
                }
            },
        });
    });
}
