import { http } from '@inertiajs/vue3';
import type { QTableProps } from 'quasar';
import { reactive, ref } from 'vue';
import type { GridColumn, GridPagination } from '@/composables/useAdminGrid';
import { DEFAULT_GRID_SORT, normalizeGridSort } from '@/composables/useAdminGrid';
import type {
    AuctionGridBidRow,
    AuctionGridBuyerPaidFields,
    AuctionGridTitleFields,
} from '@/composables/useOnlineAuctionGrid';
import type { SelectOption } from '@/constants/options';
import { isCompleteDateRangeFilter, normalizeDateRangeFilter } from '@/utils/auctionDates';
import { applyAuctionGridPrefill } from '@/utils/applyAuctionGridPrefill';
import { IN_PERSON_AUCTION_GRID_PREFILL_KEY } from '@/utils/customerAuctionNavigation';

export interface InPersonAuctionGridFilters {
    search: string | null;
    category: SelectOption;
    status: SelectOption;
    date_range: { from: string; to: string } | string | null;
    buyer_paid: SelectOption;
    user_id: number | null;
}

export interface InPersonAuctionGridRow extends AuctionGridBuyerPaidFields, AuctionGridTitleFields {
    id: number;
    customer_username: string | null;
    category: string;
    category_label: string;
    image_path: string | null;
    image_label: string;
    status: string;
    status_label: string;
    status_color: string;
    reserve_price: string;
    reserve_met: boolean | null;
    current_bid: string | null;
    bidding_history: AuctionGridBidRow[];
    opened_at: string | null;
    closed_at: string | null;
    deleted_at: string | null;
    can_edit: boolean;
    view_url: string;
    edit_url: string;
    image_url: string | null;
    plate_combination: string | null;
}

export interface InPersonAuctionGridResponse {
    total: number;
    page: number;
    data: InPersonAuctionGridRow[];
}

type TableRequest = Parameters<NonNullable<QTableProps['onRequest']>>[0];

function buildGridPayload(
    pagination: GridPagination,
    filters: InPersonAuctionGridFilters,
): GridPagination & { filters: InPersonAuctionGridFilters } {
    return {
        page: pagination.page,
        rowsPerPage: pagination.rowsPerPage,
        sortBy: pagination.sortBy,
        descending: pagination.descending,
        rowsNumber: pagination.rowsNumber,
        filters: {
            search: filters.search,
            category: { ...filters.category },
            status: { ...filters.status },
            date_range: isCompleteDateRangeFilter(filters.date_range)
                ? normalizeDateRangeFilter(filters.date_range)
                : null,
            buyer_paid: { ...filters.buyer_paid },
            user_id: filters.user_id,
        },
    };
}

export function useInPersonAuctionGrid(gridUrl: string, initialGrid?: InPersonAuctionGridResponse) {
    const loading = ref(false);
    const rows = ref<InPersonAuctionGridRow[]>(initialGrid?.data ?? []);

    const filters = reactive<InPersonAuctionGridFilters>({
        search: null,
        category: { id: 'all', name: 'All' },
        status: { id: 'all', name: 'All' },
        date_range: null,
        buyer_paid: { id: 'all', name: 'All' },
        user_id: null,
    });

    const hasPrefill = applyAuctionGridPrefill(IN_PERSON_AUCTION_GRID_PREFILL_KEY, filters);

    const pagination = ref<GridPagination>({
        sortBy: DEFAULT_GRID_SORT.sortBy,
        descending: DEFAULT_GRID_SORT.descending,
        page: initialGrid?.page ?? 1,
        rowsPerPage: 10,
        rowsNumber: initialGrid?.total ?? 0,
    });

    const columns: GridColumn[] = [
        { name: 'id', label: 'ID', align: 'left', field: 'id', sortable: true },
        { name: 'category', label: 'Category', align: 'left', field: 'category_label', sortable: true },
        { name: 'image', label: 'Image', align: 'left', field: 'image_label', sortable: false },
        { name: 'display_title', label: 'Title', align: 'left', field: 'display_title', sortable: true },
        { name: 'status', label: 'Status', align: 'left', field: 'status_label', sortable: true },
        { name: 'current_bid', label: 'Current Bid', align: 'right', field: 'current_bid', sortable: false },
        { name: 'reserve_price', label: 'Reserve Price', align: 'right', field: 'reserve_price', sortable: true },
        { name: 'reserve_met', label: 'Reserve Met', align: 'left', field: 'reserve_met', sortable: false },
        { name: 'auction_dates', label: 'Auction Date / Time Range', align: 'left', field: 'opened_at', sortable: true },
        { name: 'buyer_paid', label: 'Buyer Paid', align: 'left', field: 'buyer_paid_status', sortable: false },
        { name: 'customer_username', label: 'Seller', align: 'left', field: 'customer_username', sortable: true },
        { name: 'actions', label: 'Actions', align: 'left', field: 'id' },
    ];

    async function fetchGrid(): Promise<void> {
        loading.value = true;

        try {
            const response = await http.getClient().request({
                method: 'post',
                url: gridUrl,
                data: JSON.stringify(buildGridPayload(pagination.value, filters)),
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                },
            });

            const result = JSON.parse(response.data) as InPersonAuctionGridResponse;

            rows.value = result.data;
            pagination.value.rowsNumber = result.total;
            pagination.value.page = result.page;
        } catch (error) {
            console.error('Failed to load in-person auction grid data', error);
        } finally {
            loading.value = false;
        }
    }

    function onRequest(requestProps: TableRequest): void {
        const { page, rowsPerPage, sortBy, descending } = requestProps.pagination;

        const normalizedSort = normalizeGridSort(sortBy, descending);

        pagination.value.page = page;
        pagination.value.rowsPerPage = rowsPerPage;
        pagination.value.sortBy = normalizedSort.sortBy;
        pagination.value.descending = normalizedSort.descending;

        void fetchGrid();
    }

    function onFilterChange(): void {
        pagination.value.page = 1;
        void fetchGrid();
    }

    return {
        loading,
        rows,
        filters,
        pagination,
        columns,
        hasPrefill,
        fetchGrid,
        onRequest,
        onFilterChange,
    };
}
