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 { SelectOption } from '@/constants/options';
import { isCompleteDateRangeFilter, normalizeDateRangeFilter } from '@/utils/auctionDates';

export interface AuctionReportGridFilters {
    search: string | null;
    format: SelectOption;
    status: SelectOption;
    date_range: { from: string; to: string } | string | null;
    sold_date_range: { from: string; to: string } | string | null;
    reserve_met: SelectOption;
    buyer_paid: SelectOption;
}

export interface AuctionReportGridRow {
    id: number;
    format: string;
    format_label: string;
    title: string;
    display_title: string;
    title_full: string | null;
    category: string;
    image_path: string | null;
    image_url: string | null;
    image_label: string;
    plate_combination: string | null;
    views_count: number;
    seller_name: string | null;
    buyer_name: string | null;
    status: string;
    status_label: string;
    status_color: string;
    reserve_price: string;
    sold_price: string | null;
    reserve_met: boolean | null;
    show_outcome_columns: boolean;
    start_date_time: string | null;
    end_date_time: string | null;
    opened_at: string | null;
    closed_at: string | null;
    sold_at: string | null;
    buyer_paid_status: 'yes' | 'due' | 'no' | 'na';
    buyer_paid_label: string;
    buyer_paid_days_remaining: number | null;
    view_url: string;
}

export interface AuctionReportGridResponse {
    total: number;
    page: number;
    data: AuctionReportGridRow[];
}

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

function normalizeFilterDateRange(
    dateRange: AuctionReportGridFilters['date_range'],
): AuctionReportGridFilters['date_range'] {
    return isCompleteDateRangeFilter(dateRange) ? normalizeDateRangeFilter(dateRange) : null;
}

function buildGridPayload(
    pagination: GridPagination,
    filters: AuctionReportGridFilters,
): GridPagination & { filters: AuctionReportGridFilters } {
    return {
        page: pagination.page,
        rowsPerPage: pagination.rowsPerPage,
        sortBy: pagination.sortBy,
        descending: pagination.descending,
        rowsNumber: pagination.rowsNumber,
        filters: {
            search: filters.search,
            format: { ...filters.format },
            status: { ...filters.status },
            date_range: normalizeFilterDateRange(filters.date_range),
            sold_date_range: normalizeFilterDateRange(filters.sold_date_range),
            reserve_met: { ...filters.reserve_met },
            buyer_paid: { ...filters.buyer_paid },
        },
    };
}

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

    const filters = reactive<AuctionReportGridFilters>({
        search: null,
        format: { id: 'all', name: 'All' },
        status: { id: 'all', name: 'All' },
        date_range: null,
        sold_date_range: null,
        reserve_met: { id: 'all', name: 'All' },
        buyer_paid: { id: 'all', name: 'All' },
    });

    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: 'type', label: 'Type', align: 'left', field: 'format_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: 'auction_dates',
            label: 'Auction Date / Time Range',
            align: 'left',
            field: 'start_date_time',
            sortable: true,
        },
        { 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: true },
        { name: 'sold_price', label: 'Sold Price', align: 'right', field: 'sold_price', sortable: true },
        { name: 'sold_at', label: 'Sold Date Time', align: 'left', field: 'sold_at', sortable: true },
        { name: 'buyer_paid', label: 'Buyer Paid', align: 'left', field: 'buyer_paid', sortable: true },
        { name: 'seller_name', label: 'Seller', align: 'left', field: 'seller_name', sortable: true },
        { name: 'buyer_name', label: 'Buyer', align: 'left', field: 'buyer_name', sortable: true },
        { name: 'views_count', label: 'Views', align: 'right', field: 'views_count', sortable: true },
    ];

    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 AuctionReportGridResponse;

            rows.value = result.data;
            pagination.value.rowsNumber = result.total;
            pagination.value.page = result.page;
        } catch (error) {
            console.error('Failed to load auction report 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,
        fetchGrid,
        onRequest,
        onFilterChange,
    };
}
