import { useHttp } from '@inertiajs/react';
import { useEffect, useState } from 'react';
import {
    client as clientAdvice,
    mine as mineAdvice,
} from '@/actions/App/Http/Controllers/GrowthScoreAdvisorController';
import type {
    AdvisorAdvice,
    GrowthAdviceStatus,
    SavedAdvisorAdvice,
} from '@/types/growth-score';

export type GrowthExternalCompany = {
    id: string;
    accountType: string;
    name: string;
};

export type GrowthAdviceState = {
    advice: AdvisorAdvice | null;
    generatedAt: string | null;
    isStale: boolean;
    loading: boolean;
    error: string | null;
    status: GrowthAdviceStatus['status'];
};

function isAdvisorAdvice(value: unknown): value is AdvisorAdvice {
    if (typeof value !== 'object' || value === null) {
        return false;
    }

    const advice = value as Record<string, unknown>;
    const plan = advice.three_month_plan;
    const projection = advice.next_grade_projection;
    const upskill = advice.upskill_recommendation;

    return (
        Array.isArray(advice.critical_must_do) &&
        Array.isArray(advice.areas_needing_focus) &&
        Array.isArray(advice.good_to_have) &&
        typeof plan === 'object' &&
        plan !== null &&
        typeof projection === 'object' &&
        projection !== null &&
        typeof upskill === 'object' &&
        upskill !== null
    );
}

export function extractAdvice(payload: unknown): AdvisorAdvice | null {
    if (!isAdvisorAdvice(payload)) {
        return null;
    }

    const legacyPlan = payload.three_month_plan;
    const legacyProjection = payload.next_grade_projection;

    return {
        critical_must_do: payload.critical_must_do,
        areas_needing_focus: payload.areas_needing_focus,
        good_to_have: payload.good_to_have,
        three_month_plan: payload.three_month_plan,
        ninety_day_plan: payload.ninety_day_plan ?? {
            days_0_30: legacyPlan.month_1,
            days_31_60: legacyPlan.month_2,
            days_61_90: legacyPlan.month_3,
        },
        next_grade_projection: {
            ...legacyProjection,
            months_12: legacyProjection.months_12 ?? legacyProjection.months_6,
        },
        upskill_recommendation: payload.upskill_recommendation,
    };
}

export function useGrowthAdvice({
    savedAdvice,
    adviceStatus,
    externalCompany,
    canGenerate,
}: {
    savedAdvice?: SavedAdvisorAdvice | null;
    adviceStatus?: GrowthAdviceStatus;
    externalCompany?: GrowthExternalCompany;
    canGenerate: boolean;
}): GrowthAdviceState {
    const externalCompanyId = externalCompany?.id;
    const externalAccountType = externalCompany?.accountType;
    const { post, setData } = useHttp<{ account_type: string }>({
        account_type: externalAccountType ?? '',
    });
    const [state, setState] = useState<GrowthAdviceState>(() => ({
        advice: savedAdvice ? extractAdvice(savedAdvice) : null,
        generatedAt: savedAdvice?.generated_at ?? null,
        isStale: savedAdvice?.is_stale ?? false,
        loading:
            adviceStatus?.status === 'pending' ||
            adviceStatus?.status === 'generating',
        error: adviceStatus?.error ?? null,
        status: adviceStatus?.status ?? 'pending',
    }));

    useEffect(() => {
        if (!canGenerate) {
            return;
        }

        let cancelled = false;
        const route = externalCompanyId
            ? clientAdvice(externalCompanyId)
            : mineAdvice();

        setData('account_type', externalAccountType ?? '');
        void post(route.url, {
            onStart: () => {
                if (!cancelled) {
                    setState((current) => ({
                        ...current,
                        loading: true,
                        status: 'generating',
                        error: null,
                    }));
                }
            },
        })
            .then((response) => {
                if (cancelled) {
                    return;
                }

                const payload = response as Record<string, unknown>;
                const status = payload.status as
                    | GrowthAdviceStatus
                    | undefined;
                const advice = extractAdvice(payload);

                setState({
                    advice,
                    generatedAt:
                        typeof payload.generated_at === 'string'
                            ? payload.generated_at
                            : null,
                    isStale: payload.is_stale === true,
                    loading:
                        status?.status === 'pending' ||
                        status?.status === 'generating',
                    error: status?.error ?? null,
                    status: status?.status ?? (advice ? 'ready' : 'pending'),
                });
            })
            .catch(() => {
                if (!cancelled) {
                    setState((current) => ({
                        ...current,
                        loading: false,
                        status: 'failed',
                        error: 'Advice could not be generated.',
                    }));
                }
            });

        return () => {
            cancelled = true;
        };
    }, [canGenerate, externalAccountType, externalCompanyId, post, setData]);

    return state;
}
