<script setup lang="ts">
import {SortableHeader, useSort, VirtualScrollTable} from '@/components/table';
import {MarketTypeLabel} from '@/market/type';
import {computed} from 'vue';
import {MarketLocation} from '../location';
import IskLabel from '../IskLabel.vue';
import {ComparedItem} from './compare';

interface Props {
    result?: ComparedItem[];
    locations?: MarketLocation[];
}

const props = withDefaults(defineProps<Props>(), {
    result: () => [],
    locations: () => []
});

const buyKey = (id: number): `buy:${number}` => `buy:${id}`;
const sellKey = (id: number): `sell:${number}` => `sell:${id}`;

type SortableItem = ComparedItem & Record<`buy:${number}` | `sell:${number}`, number>;

const rows = computed<SortableItem[]>(() => props.result.map(item => {
    const sortable = {...item} as SortableItem;

    props.locations.forEach(l => {
        const price = item.prices[l.id];
        sortable[buyKey(l.id)] = price?.buy ?? 0;
        sortable[sellKey(l.id)] = price?.sell ?? 0;
    });

    return sortable;
}));

const {sortedArray, headerProps} = useSort(rows, {
    defaultSortKey: 'name',
    defaultSortDirection: 'asc'
});

const bestBuy = (row: ComparedItem): number | undefined => {
    let best: number | undefined;
    let bestValue = -Infinity;
    props.locations.forEach(l => {
        const cell = row.prices[l.id];
        if (cell && cell.buy > bestValue) {
            bestValue = cell.buy;
            best = l.id;
        }
    });
    return bestValue > 0 ? best : undefined;
};

const bestSell = (row: ComparedItem): number | undefined => {
    let best: number | undefined;
    let bestValue = -Infinity;
    props.locations.forEach(l => {
        const cell = row.prices[l.id];
        if (cell && cell.sell > bestValue) {
            bestValue = cell.sell;
            best = l.id;
        }
    });
    return bestValue > 0 ? best : undefined;
};

const totals = computed(() => new Map(props.locations.map(l => [l.id, props.result.reduce((acc, row) => {
    const cell = row.prices[l.id];
    return {
        buy: acc.buy + (cell?.buy ?? 0),
        sell: acc.sell + (cell?.sell ?? 0),
    };
}, {buy: 0, sell: 0})])));
</script>

<template>
    <VirtualScrollTable :list="sortedArray" :itemHeight="33" :headerHeight="66" :footerHeight="33" bottom="1rem">
        <template #default="{ list }">
            <thead>
                <tr>
                    <SortableHeader v-bind="headerProps" sortKey="name" rowspan="2">Item</SortableHeader>
                    <SortableHeader v-bind="headerProps" sortKey="quantity" rowspan="2">Qty</SortableHeader>
                    <th v-for="location in locations" :key="location.id" colspan="2" class="text-center border-l border-slate-500" :title="location.name">
                        {{ location.systemName }}
                    </th>
                </tr>
                <tr>
                    <template v-for="location in locations" :key="location.id">
                        <SortableHeader v-bind="headerProps" :sortKey="buyKey(location.id)" class="border-l border-slate-500">Buy</SortableHeader>
                        <SortableHeader v-bind="headerProps" :sortKey="sellKey(location.id)">Sell</SortableHeader>
                    </template>
                </tr>
            </thead>
            <tbody>
                <tr v-for="r in list" :key="r.data.typeId">
                    <td>
                        <MarketTypeLabel :id="r.data.typeId" :name="r.data.name" />
                    </td>
                    <td class="text-right">{{ r.data.quantity.toLocaleString() }}</td>
                    <template v-for="location in locations" :key="location.id">
                        <td class="text-right border-l border-slate-500" :class="r.data.prices[location.id] ? (bestBuy(r.data) === location.id ? 'bg-emerald-500' : 'bg-amber-900') : ''">
                            <IskLabel v-if="r.data.prices[location.id]" :amount="r.data.prices[location.id].buy" :colored="false" />
                            <span v-else>-</span>
                        </td>
                        <td class="text-right" :class="r.data.prices[location.id] ? (bestSell(r.data) === location.id ? 'bg-emerald-500' : 'bg-amber-900') : ''">
                            <IskLabel v-if="r.data.prices[location.id]" :amount="r.data.prices[location.id].sell" :colored="false" />
                            <span v-else>-</span>
                        </td>
                    </template>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="2" class="font-semibold">Total</td>
                    <template v-for="location in locations" :key="location.id">
                        <td class="text-right border-l border-slate-500"><IskLabel :amount="totals.get(location.id)?.buy ?? 0" :colored="false" /></td>
                        <td class="text-right"><IskLabel :amount="totals.get(location.id)?.sell ?? 0" :colored="false" /></td>
                    </template>
                </tr>
            </tfoot>
        </template>
        <template #empty>
            <div class="text-center mt-4">
                <span>No items found</span>
            </div>
        </template>
    </VirtualScrollTable>
</template>
