import { useState, useCallback, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import type {
    BookingProduct,
    BookingProductFilterState,
    BookingProductStatusCount,
    BookingProductSummary,
    BookingProductMonthOption,
    SubscriptionRemaining,
} from '../types';

interface UseBookingProductsReturn {
    data: BookingProduct[];
    isLoading: boolean;
    totalItems: number;
    totalPages: number;
    statusCounts: BookingProductStatusCount[];
    instockCount: number;
    outstockCount: number;
    lowStockThreshold: number;
    monthOptions: BookingProductMonthOption[];
    subscriptionRemaining: SubscriptionRemaining | null;
    fetchProducts: () => void;
    fetchStatusCounts: () => void;
    deleteProduct: ( productId: number ) => Promise< void >;
    deleteProducts: ( productIds: number[] ) => Promise< void >;
}

export const useBookingProducts = (
    filterArgs: BookingProductFilterState
): UseBookingProductsReturn => {
    const [ data, setData ] = useState< BookingProduct[] >( [] );
    const [ isLoading, setIsLoading ] = useState( true );
    const [ totalItems, setTotalItems ] = useState( 0 );
    const [ totalPages, setTotalPages ] = useState( 0 );
    const [ instockCount, setInstockCount ] = useState( 0 );
    const [ outstockCount, setOutstockCount ] = useState( 0 );
    const [ lowStockThreshold, setLowStockThreshold ] = useState( 2 );
    const [ subscriptionRemaining, setSubscriptionRemaining ] =
        useState< SubscriptionRemaining | null >( null );
    const [ monthOptions, setMonthOptions ] = useState< BookingProductMonthOption[] >( [] );

    const [ statusCounts, setStatusCounts ] = useState< BookingProductStatusCount[] >( [
        {
            value: 'all',
            label: __( 'All', 'dokan' ),
            count: 0,
        },
        {
            value: 'publish',
            label: __( 'Published', 'dokan' ),
            count: 0,
        },
        {
            value: 'draft',
            label: __( 'Draft', 'dokan' ),
            count: 0,
        },
        {
            value: 'pending',
            label: __( 'Pending Review', 'dokan' ),
            count: 0,
        },
        {
            value: 'reject',
            label: __( 'Rejected', 'dokan' ),
            count: 0,
        },
    ] );

    const fetchProducts = useCallback( async () => {
        setIsLoading( true );
        try {
            const queryArgs: Record< string, any > = {
                per_page: filterArgs.per_page,
                page: filterArgs.page,
            };

            if ( filterArgs.status && filterArgs.status !== 'all' ) {
                queryArgs.status = filterArgs.status;
            }

            if ( filterArgs.search ) {
                queryArgs.search = filterArgs.search;
            }

            if ( filterArgs.category ) {
                queryArgs.category = filterArgs.category;
            }

            if ( filterArgs.year_month ) {
                queryArgs.year_month = filterArgs.year_month;
            }

            if ( filterArgs.in_stock !== undefined ) {
                queryArgs.in_stock = filterArgs.in_stock;
            }

            if ( filterArgs.product_brand ) {
                queryArgs.product_brand = filterArgs.product_brand;
            }

            if ( filterArgs.filter_by_other ) {
                queryArgs.filter_by_other = filterArgs.filter_by_other;
            }

            const response = ( await apiFetch( {
                path: addQueryArgs( '/dokan/v1/booking/products', queryArgs ),
                parse: false,
            } ) ) as Response;

            const responseData: BookingProduct[] = await response.json();
            const responseTotalItems = response.headers.get( 'X-WP-Total' );
            const responseTotalPages = response.headers.get( 'X-WP-TotalPages' );

            setData( responseData );
            setTotalItems( parseInt( responseTotalItems ?? '0', 10 ) );
            setTotalPages( parseInt( responseTotalPages ?? '0', 10 ) );
        } catch ( error ) {
            console.error( 'Error fetching booking products:', error );
            setData( [] );
        } finally {
            setIsLoading( false );
        }
    }, [
        filterArgs.page,
        filterArgs.per_page,
        filterArgs.status,
        filterArgs.search,
        filterArgs.category,
        filterArgs.year_month,
        filterArgs.in_stock,
        filterArgs.product_brand,
        filterArgs.filter_by_other,
    ] );

    const fetchStatusCounts = useCallback( async () => {
        try {
            const response = ( await apiFetch( {
                path: '/dokan/v1/booking/products/summary',
            } ) ) as BookingProductSummary;

            const counts = response.post_counts ?? {};
            const allCount =
                ( counts.publish ?? 0 ) +
                ( counts.draft ?? 0 ) +
                ( counts.pending ?? 0 ) +
                ( counts.reject ?? 0 );

            setStatusCounts( [
                {
                    value: 'all',
                    label: __( 'All', 'dokan' ),
                    count: allCount,
                },
                {
                    value: 'publish',
                    label: __( 'Published', 'dokan' ),
                    count: counts.publish ?? 0,
                },
                {
                    value: 'draft',
                    label: __( 'Draft', 'dokan' ),
                    count: counts.draft ?? 0,
                },
                {
                    value: 'pending',
                    label: __( 'Pending Review', 'dokan' ),
                    count: counts.pending ?? 0,
                },
                {
                    value: 'reject',
                    label: __( 'Rejected', 'dokan' ),
                    count: counts.reject ?? 0,
                },
            ] );

            setInstockCount( response.instock_count ?? 0 );
            setOutstockCount( response.outofstock_count ?? 0 );
            setLowStockThreshold( response.low_stock_threshold ?? 2 );
            setMonthOptions( response.months ?? [] );
            setSubscriptionRemaining( response.subscription_remaining ?? null );
        } catch ( error ) {
            console.error( 'Error fetching booking product summary:', error );
        }
    }, [] );

    const deleteProduct = useCallback( async ( productId: number ) => {
        await apiFetch( {
            path: `/dokan/v1/products/${ productId }`,
            method: 'DELETE',
            data: { force: true },
        } );
    }, [] );

    const deleteProducts = useCallback( async ( productIds: number[] ) => {
        await Promise.all(
            productIds.map( ( id ) =>
                apiFetch( {
                    path: `/dokan/v1/products/${ id }`,
                    method: 'DELETE',
                    data: { force: true },
                } )
            )
        );
    }, [] );

    useEffect( () => {
        void fetchProducts();
    }, [ fetchProducts ] );

    useEffect( () => {
        void fetchStatusCounts();
    }, [ fetchStatusCounts ] );

    return {
        data,
        isLoading,
        totalItems,
        totalPages,
        statusCounts,
        instockCount,
        outstockCount,
        lowStockThreshold,
        monthOptions,
        subscriptionRemaining,
        fetchProducts,
        fetchStatusCounts,
        deleteProduct,
        deleteProducts,
    };
};
