<template>
    <el-row>
        <el-col :span="22">
            <el-select-v2 v-model="itemName" :options="itemNameList" clearable filterable placeholder="物品名"
                          style="width: 99%"/>
        </el-col>
        <el-col :span="2">
            <el-button :disabled="!itemName" :icon="Search" :loading="listLoading"
                       @click="doGetIMarketList(itemName2IdMap[itemName])">查询
            </el-button>
        </el-col>
    </el-row>
    <el-skeleton :loading="listLoading" :rows="5" animated style="margin-top: 1em">
        <template #default>
            <el-table :data="itemOnList" empty-text="暂无数据" style="width: 100%" table-layout="auto">
                <el-table-column label="卖家">
                    <template #default="scope">
                        <el-link :href="'/bazaar.php?userId=' + scope.row.playerId" :underline="false" target="_blank"
                                 type="primary" v-text="scope.row.playerName + `[${scope.row.playerId}]`"/>
                    </template>
                </el-table-column>
                <el-table-column label="单价">
                    <template #default="scope">
                        <div style="display: flex; align-items: center"
                             v-text="'$' + toThousands(scope.row.price)"></div>
                    </template>
                </el-table-column>
                <el-table-column label="在售" prop="amount"/>
                <el-table-column label="">
                    <template #default="scope">
                        <el-input v-model="scope.row.inputAmount" style="width: 12em">
                            <template #append>
                                <el-button :icon="ShoppingCart" :loading="scope.row.onBuying" type="primary"
                                           @click="buy(scope.row)">购买
                                </el-button>
                            </template>
                        </el-input>
                    </template>
                </el-table-column>
            </el-table>
            <el-row v-if="queryTs">
                <el-col :span="2"><span><el-icon><Timer/></el-icon>{{ timePastFormat(currentTs - queryTs) }}</span>
                </el-col>
                <el-col :span="3">
                        <span :style="{ backgroundImage: 'url(/images/items/' + itemId + '/small.png)' }"
                              style="display:inline-block;width:38px;height:19px;"></span>
                </el-col>
            </el-row>
        </template>
    </el-skeleton>
</template>

<script lang="ts">
export default {
    name: "MarketHelper"
}
</script>

<script lang="ts" setup>

import { Search, ShoppingCart, Timer } from '@element-plus/icons-vue';
import { ElMessage } from "element-plus";
import { inject, onBeforeUnmount, onMounted, ref } from "vue";
import { LoggerKey } from "../ts/class/Logger";
import { ItemHelperKey } from "../ts/class/utils/ItemHelper";
import { itemNameDict } from "../ts/dictionary/translation";
import toThousands from "../ts/func/utils/toThousands";
import Sleep from "../ts/func/utils/Sleep";
import { MathUtilsKey } from "../ts/class/utils/MathUtils";

const logger = inject(LoggerKey);
const itemHelper = inject(ItemHelperKey);
const mathUtils = inject(MathUtilsKey)

let itemName2IdMap: { [p: string]: number } = null;
const itemName = ref<string>('');
const itemNameList = ref<{ value: string, label: string }[]>([]);
const itemId = ref<number>();
const queryTs = ref<number>(0);
type ItemInfo = {
    playerId: string,
    playerName: string,
    price: number,
    amount: number,
    inputAmount: number,
    onBuying: boolean,
    itemId: string,
};
const itemOnList = ref<ItemInfo[]>([]);
const listLoading = ref<boolean>(false);
const currentTs = ref<number>(Date.now());

const timePastFormat = (ts: number): string => {
    // 毫秒
    if (ts < 1000) {
        return ts + 'ms';
    }
    // 秒
    else if (ts < 60000) {
        return (ts / 1000 | 0) + 's';
    }
    // 分
    else if (ts < 3600000) {
        return (ts / 60000 | 0) + 'm';
    }
    // 时
    else {
        return (ts / 3600000 | 0) + 'h';
    }
};

const doGetIMarketList = async (id: number) => {
    itemOnList.value = [];
    listLoading.value = true;
    queryTs.value = 0;
    itemId.value = id;
    const queryItemListHtml = await (await fetch(window.addRFC("https://www.torn.com/imarket.php"), {
        "headers": {
            "accept": "*/*",
            "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
            "sec-ch-ua-mobile": "?0",
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-origin",
            "x-requested-with": "XMLHttpRequest"
        },
        "referrer": "https://www.torn.com/imarket.php",
        "referrerPolicy": "strict-origin-when-cross-origin",
        "body": "step=getShopList1&itemID=" + id,
        "method": "POST",
        "mode": "cors",
        "credentials": "include"
    })).text();
    queryTs.value = Date.now();
    let resError = '';
    try {
        const res = JSON.parse(queryItemListHtml);
        if (!res.success) {
            resError = res.error || res.text;
            ElMessage.error(resError);
        }
    } catch (e) {
    }
    listLoading.value = false;

    // 无法获取bazaar html内容
    if (resError) {
        throw new Error(resError);
    }
    let container = document.createElement('div');
    container.innerHTML = queryItemListHtml;
    const list = container.querySelectorAll('ul.items li.private-bazaar');
    logger.info({ list });
    list.forEach((li, index) => {
        let item = {
            playerId: null,
            playerName: null,
            price: null,
            amount: null,
            inputAmount: null,
            index,
            onBuying: false,
            itemId: null,
        };
        item.playerId = li.querySelector("a.user.name").getAttribute('href').trim().split('XID=')[1];
        item.playerName = li.querySelector("a.user.name span").innerText.trim();
        item.price = Number(li.querySelector("span.cost-price").innerText.trim().replace('$', '').replaceAll(',', ''));
        item.amount = Number(li.querySelector("span.cost-amount").innerText.trim().split(' ')[0].replace('(', "").replaceAll(',', ''));
        item.inputAmount = item.amount;
        item.itemId = id;
        itemOnList.value.push(item);
    });
    container = null;
};
const buy = async (itemInfo: ItemInfo) => {
    itemInfo.onBuying = true;
    try {
        // 获取玩家id bazaar信息
        let bazaarId: string;
        const bazaarItemList: { list: { bazaarID: string, itemID: string }[] } = await (await fetch(
            `https://www.torn.com/bazaar.php?sid=bazaarData&step=getBazaarItems&start=0&ID=${ itemInfo.playerId }&order=default&by=asc&categorised=0&limit=1000&searchname=`,
            {
                "headers": {
                    "accept": "*/*",
                    "sec-ch-ua-mobile": "?0",
                    "sec-fetch-dest": "empty",
                    "sec-fetch-mode": "cors",
                    "sec-fetch-site": "same-origin",
                    "x-requested-with": "XMLHttpRequest"
                },
                "referrer": "https://www.torn.com/bazaar.php?userId=" + itemInfo.playerId,
                "referrerPolicy": "strict-origin-when-cross-origin",
                "body": null,
                "method": "GET",
                "mode": "cors",
                "credentials": "include"
            })).json();
        for (let i = 0; i < bazaarItemList.list.length; i++) {
            if (bazaarItemList.list[i].itemID === itemInfo.itemId.toString()) {
                bazaarId = bazaarItemList.list[i].bazaarID;
                break;
            }
        }
        if (!bazaarId) {
            ElMessage.error('上架商品未找到');
            logger.error('物品id未找到对应bazaar项目', bazaarItemList, itemInfo.itemId);
            (() => {
                throw new Error('bazaarId为空')
            })();
        }
      await Sleep(mathUtils.getRandomInt(100, 110))
        // 从baz买货
        let buyResponse = await (await fetch("https://www.torn.com/bazaar.php?sid=bazaarData&step=buyItem", {
            "headers": {
                "accept": "*/*",
                "sec-ch-ua-mobile": "?0",
                "sec-fetch-dest": "empty",
                "sec-fetch-mode": "cors",
                "sec-fetch-site": "same-origin",
                "x-requested-with": "XMLHttpRequest"
            },
            "referrer": "https://www.torn.com/bazaar.php?userId=" + itemInfo.playerId,
            "referrerPolicy": "strict-origin-when-cross-origin",
            "body": (() => {
                const data = new FormData();
                data.append('userID', itemInfo.playerId);
                data.append('id', bazaarId);
                data.append('itemID', itemInfo.itemId.toString());
                data.append('amount', itemInfo.inputAmount.toString());
                data.append('price', itemInfo.price.toString());
                data.append('beforeval', (itemInfo.price * itemInfo.inputAmount).toString());
                return data;
            })(),
            "method": "POST",
            "mode": "cors",
            "credentials": "include"
        })).json();
        if (!buyResponse.success) {
            ElMessage.error('购买失败 ' + buyResponse.text);
        }
    } catch (e) {
        logger.error(e.stack);
        ElMessage.error('出错了 ' + e.message);
    }
    itemInfo.onBuying = false;
};

let intervalId = 0;
onMounted(async () => {
    intervalId = window.setInterval(() => currentTs.value = Date.now(), 100);
    let map = itemHelper.getItemNameMap();
    if (map.data) {
        itemName2IdMap = map.data;
    } else {
        itemName2IdMap = await map.promise;
    }
    Object.keys(itemName2IdMap).forEach(itemName => {
        itemNameList.value.push({
            value: itemName,
            label: itemNameDict[itemName] ? itemName + ` (${ itemNameDict[itemName] })` : itemName,
        })
    });
});

onBeforeUnmount(() => window.clearInterval(intervalId));
</script>

<style scoped></style>
