<script setup>
import { requestClient } from '#/api/request';
import { Button, message, Form, InputNumber, Drawer } from 'ant-design-vue';
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue';
import dayjs from 'dayjs';

import MatchCard from '../components/match_card.vue';

import { useContentsPositionStore } from '@vben/stores';
const contentsPositionStore = useContentsPositionStore();

const solutions = ref([]);
const selectedSolutions = reactive([]);
const totalProfit = ref({});

const psOptions = reactive({
  bet: 10000,
  rebate: 0,
});

const totalProfitVisible = ref(false);

const fixFloat = (number, x = 2) => {
  return parseFloat(number.toFixed(x));
}

const headerStyle = computed(() => {
  return {
    position: contentsPositionStore.position,
    top: contentsPositionStore.top,
    left: contentsPositionStore.left,
    width: contentsPositionStore.width,
    paddingLeft: contentsPositionStore.paddingLeft,
  }
});

const totalProfitValue = computed(() => {
  const { profit = {}, preSolution = {}, subSolution = {}, gamesEvents = {} } = totalProfit.value;
  const sol1 = formatSolution(preSolution, gamesEvents);
  const sol2 = formatSolution(subSolution, gamesEvents);

  const psScale = psOptions.bet / profit.ps_base ?? 10000;
  const psRebate = psOptions.bet * psOptions.rebate / 100;
  const profitInfo = {};
  Object.keys(profit).forEach(key => {
    if (key == 'win_diff') {
      return;
    }
    if (key.startsWith('gold')) {
      profitInfo[key] = fixFloat(profit[key] * psScale);
    }
    else if (key.startsWith('win_')) {
      profitInfo[key] = fixFloat(profit[key] * psScale + psRebate);
    }
  });

  const psInfo = [];
  const outPreSol = [];
  const outSubSol = [];

  const solutions = [sol1, sol2].filter(item => item);
  solutions.forEach((item, index) => {
    const { sol: { ps_index }, cpr } = item;
    const newCpr = [...cpr];
    const ps_info = newCpr.splice(ps_index, 1);
    psInfo.push({ ...ps_info[0] });
    newCpr.forEach((c, i) => {
      let side = '';
      if (ps_index == 0) {
        if (i == 0) {
          side = "B"
        }
        else {
          side = "M";
        }
      }
      else if (ps_index == 1) {
        if (i == 0) {
          side = "A";
        }
        else {
          side = "M";
        }
      }
      else {
        if (i == 0) {
          side = "A";
        }
        else {
          side = "B";
        }
      }
      if (index == 0) {
        outPreSol.push({ ...c, g: profitInfo[`gold${side}${index+1}`] });
      }
      else {
        outSubSol.push({ ...c, g: profitInfo[`gold${side}${index+1}`] });
      }
    })
  });

  return { solutions, profit: profitInfo, psInfo, outPreSol, outSubSol };
});

const solutionsList = computed(() => {
  const startTimestamp = selectedSolutions[0]?.timestamp ?? 0;
  return solutions.value.map(item => {
    const selected = selectedSolutions.findIndex(sol => sol.sid === item.sid) >= 0;
    const disabled = false && !selected && (item.info.ps.timestamp < startTimestamp + 1000 * 60 * 60 * 2);
    const currentSol = { ...item.sol };

    const psScale = psOptions.bet / currentSol.inner_base;
    const psRebate = psOptions.bet * psOptions.rebate / 100;

    Object.keys(currentSol).forEach(key => {
      if (key.startsWith('gold_')) {
        currentSol[key] = fixFloat(currentSol[key] * psScale);
      }
      else if (key.startsWith('win_')) {
        currentSol[key] = fixFloat(currentSol[key] * psScale + psRebate);
      }
    });
    return { ...item, sol: currentSol, selected, disabled };
  });
});

const getSolutions = async () => {
  try {
    const data = await requestClient.get('/pstery/get_solutions');
    return data;
  }
  catch (error) {
    console.error('Failed to fetch solutions:', error);
    message.error('获取中单方案失败');
    return [];
  }
}

const calcTotalProfit = async () => {
  const sids = selectedSolutions.map(item => item.sid);
  try {
    const totalProfit = await requestClient.post('/pstery/calc_total_profit', [...sids, psOptions.bet]);
    return totalProfit;
  }
  catch (error) {
    console.error('Failed to calc total profit:', error);
    message.error('计算综合利润失败');
    return {};
  }
}

const parseIorKey = (iorKey) => {
  const [, type, accept, side, , ratioString] = iorKey.match(/^ior_(r|ou|m|wm|ot)(a?)(h|c|n)?(_(\d+))?$/);
  const ratio = ratioString ? `${ratioString[0]}.${ratioString.slice(1)}` * (accept ? 1 : -1) : 0;
  return { type, side, ratio };
}

const PS_IOR_KEYS = [
  ['0', 'ior_mh', 'ior_mn', 'ior_mc'],
  // ['0', 'ior_rh_05', 'ior_mn', 'ior_rc_05'],
  ['-1', 'ior_rh_15', 'ior_wmh_1', 'ior_rac_05'],
  ['-2', 'ior_rh_25', 'ior_wmh_2', 'ior_rac_15'],
  ['+1', 'ior_rah_05', 'ior_wmc_1', 'ior_rc_15'],
  ['+2', 'ior_rah_15', 'ior_wmc_2', 'ior_rc_25'],
  ['2-3', 'ior_ot_2', 'ior_os_2-3', 'ior_ot_3'],
];

const formatPsEvents = (events) => {
  return PS_IOR_KEYS.map(([label, ...keys]) => {
    const match = keys.map(key => ({
      key,
      value: events[key] ?? 0
    }));
    return {
      label,
      match
    };
  })
  // .filter(item => item.match.every(entry => entry.value !== 0))
  .map(({label, match}) => [label, ...match]);
}

// const rivalIor = (ior) => {
//   const map = {
//     "ior_rh": "ior_rac",
//     "ior_rc": "ior_rah",
//     "ior_rac": "ior_rh",
//     "ior_rah": "ior_rc",
//     "ior_wmh": "ior_wmc",
//     "ior_wmc": "ior_wmh",
//     "ior_wmh_2": "ior_wmc_2",
//     "ior_wmc_2": "ior_wmh_2"
//   };
//   const iorInfos = ior.split('_');
//   const iorStart = iorInfos.slice(0, 2).join('_');
//   if (!map[iorStart]) {
//     return ior;
//   }
//   return `${map[iorStart]}_${iorInfos[2]}`;
// }

const formatEvents = (events, cprKeys) => {
  const eventsMap = {};
  Object.keys(events).forEach(key => {
    const { type, side, ratio } = parseIorKey(key);
    let ratioKey, index;
    if (type === 'r') {
      if (side === 'h') {
        ratioKey = ratio;
        index = 0;
      }
      else if (side === 'c') {
        ratioKey = -ratio;
        index = 2;
      }
    }
    else if (type === 'm') {
      ratioKey = 'm';
      if (side == 'h') {
        index = 0;
      }
      else if (side == 'c') {
        index = 2;
      }
      else {
        index = 1;
      }
    }
    else if (type === 'wm') {
      ratioKey = `wm_${Math.abs(ratio)}`;
      if (side === 'h') {
        index = 0;
      }
      else if (side === 'c') {
        index = 2;
      }
    }
    else if (type === 'ou') {
      ratioKey = `ou_${Math.abs(ratio)}`;
      if (side === 'c') {
        index = 0;
      }
      else if (side === 'h') {
        index = 2;
      }
    }
    if (typeof (ratioKey) == 'number') {
      if (ratioKey > 0) {
        ratioKey = `+${ratioKey}`;
      }
      // else if (ratioKey === 0) {
      //   ratioKey = '-0';
      // }
      else {
        ratioKey = `${ratioKey}`;
      }
    }

    if (!ratioKey) {
      return;
    }

    if (!eventsMap[ratioKey]) {
      eventsMap[ratioKey] = new Array(3).fill(undefined);
    }

    const value = events[key] ?? 0;
    eventsMap[ratioKey][index] = { key, value };
  });

  return Object.keys(eventsMap).sort((a, b) => a.localeCompare(b)).map(key => {
    return [key, ...eventsMap[key]];
  });
}

const formatSolution = (solution, eventsList) => {
  const { cpr, info } = solution;
  if (!cpr || !info) {
    return null;
  }

  const cprKeys = cpr.map(item => item.k);

  const psEvents = eventsList.ps?.[info.ps.eventId] ?? {};
  const obEvents = eventsList.ob?.[info.ob.eventId] ?? {};
  const hgEvents = eventsList.hg?.[info.hg.eventId] ?? {};

  info.ps.events = formatPsEvents(psEvents);
  info.ob.events = formatEvents(obEvents, cprKeys);
  info.hg.events = formatEvents(hgEvents, cprKeys);

  info.ps.dateTime = dayjs(info.ps.timestamp).format('YYYY-MM-DD HH:mm:ss');
  info.ob.dateTime = dayjs(info.ob.timestamp).format('YYYY-MM-DD HH:mm:ss');
  info.hg.dateTime = dayjs(info.hg.timestamp).format('YYYY-MM-DD HH:mm:ss');

  cpr.forEach(item => {
    const { k, p } = item;
    if (!info[p]['selected']) {
      info[p]['selected'] = [];
    }
    info[p]['selected'].push(k);
  });

  return solution;
}

const updateSolutions = async () => {
  const { solutions: solutionsList, gamesEvents: eventsList } = await getSolutions();
  solutions.value = solutionsList?.map(solution => formatSolution(solution, eventsList)) ?? [];
}

const showTotalProfit = async () => {
  totalProfit.value = await calcTotalProfit();
  totalProfitVisible.value = true;
};

const closeTotalProfit = () => {
  totalProfitVisible.value = false;
  selectedSolutions.length = 0;
  totalProfit.value = {};
};

const toggleSolution = (sid, timestamp) => {
  const findIndex = selectedSolutions.findIndex(item => item.sid === sid);
  if (findIndex >= 0) {
    selectedSolutions.splice(findIndex, 1);
  }
  else if (selectedSolutions.length < 2) {
    selectedSolutions.push({ sid, timestamp });
  }
  else {
    selectedSolutions.splice(1, 1, { sid, timestamp });
  }
  if (selectedSolutions.length == 2) {
    showTotalProfit();
  }
}

let updateTimer = null;

onMounted(() => {
  updateSolutions();
  updateTimer = setInterval(() => {
    updateSolutions();
  }, 1000 * 10);
});

onUnmounted(() => {
  clearInterval(updateTimer);
});


</script>

<template>
  <div class="solution-container">

    <div class="contents-header transition-all duration-200" :style="headerStyle">
      <div class="solution-options">
        <Form layout="inline">
          <Form.Item label="PS 投注">
            <InputNumber size="small" placeholder="PS投注" min="1000" v-model:value="psOptions.bet" />
          </Form.Item>
          <!-- <Form.Item label="PS 返点">
            <InputNumber size="small" placeholder="PS返点" min="0" v-model:value="psOptions.rebate" />
          </Form.Item> -->
        </Form>
      </div>
      <div class="solution-header">
        <span>PS</span>
        <span>OB</span>
        <span>HG</span>
        <em>利润</em>
      </div>
    </div>

    <div class="solution-list">
      <div class="solution-item"
        v-for="{ sid, sol: { win_average, cross_type }, info: { ps, ob, hg }, selected, disabled } in solutionsList" :key="sid"
        :class="{ 'selected': selected, 'disabled': disabled }">
        <MatchCard platform="ps" :eventId="ps.eventId" :leagueName="ps.leagueName" :teamHomeName="ps.teamHomeName"
          :teamAwayName="ps.teamAwayName" :dateTime="ps.dateTime" :eventInfo="ps.eventInfo" :events="ps.events ?? []"
          :matchNumStr="ps.matchNumStr" :selected="ps.selected ?? []" />

        <MatchCard platform="ob" :eventId="ob.eventId" :leagueName="ob.leagueName" :teamHomeName="ob.teamHomeName"
          :teamAwayName="ob.teamAwayName" :dateTime="ob.dateTime" :events="ob.events ?? []"
          :selected="ob.selected ?? []" />

        <MatchCard platform="hg" :eventId="hg.eventId" :leagueName="hg.leagueName" :teamHomeName="hg.teamHomeName"
          :teamAwayName="hg.teamAwayName" :dateTime="hg.dateTime" :events="hg.events ?? []"
          :selected="hg.selected ?? []" />

        <div class="solution-profit" @click="!disabled && toggleSolution(sid, ps.timestamp)">
          <p>{{ win_average }}</p>
          <p>{{ cross_type }}</p>
        </div>
      </div>
    </div>
    <div class="list-empty" v-if="!solutionsList.length">暂无数据</div>

    <!-- <Drawer
      title="综合利润方案"
      placement="bottom"
      height="600"
      :visible="totalProfitVisible"
      @close="closeTotalProfit"
    >
      <div class="solution-total-profit" v-if="totalProfitValue.solutions.length">
        <div class="solution-item"
          v-for="{ sid, info: { ps, ob, hg } } in totalProfitValue.solutions" :key="sid">
          <MatchCard platform="ps" :eventId="ps.eventId" :leagueName="ps.leagueName" :teamHomeName="ps.teamHomeName"
            :teamAwayName="ps.teamAwayName" :dateTime="ps.dateTime" :eventInfo="ps.eventInfo" :events="ps.events ?? []"
            :matchNumStr="ps.matchNumStr" :selected="ps.selected ?? []" />

          <MatchCard platform="ob" :eventId="ob.eventId" :leagueName="ob.leagueName" :teamHomeName="ob.teamHomeName"
            :teamAwayName="ob.teamAwayName" :dateTime="ob.dateTime" :events="ob.events ?? []"
            :selected="ob.selected ?? []" />

          <MatchCard platform="hg" :eventId="hg.eventId" :leagueName="hg.leagueName" :teamHomeName="hg.teamHomeName"
            :teamAwayName="hg.teamAwayName" :dateTime="hg.dateTime" :events="hg.events ?? []"
            :selected="hg.selected ?? []" />
        </div>
      </div>
      <div class="profit-info">
        <table>
          <tr>
            <th></th>
            <td>PS</td>
            <td colspan="2">第一场</td>
            <td colspan="2">第二场</td>
          </tr>
          <tr>
            <th>赔率</th>
            <td>{{ totalProfitValue.psInfo[0]?.v }}: {{ totalProfitValue.psInfo[1]?.v }}</td>
            <td>{{ totalProfitValue.outPreSol[0]?.p }}: {{ totalProfitValue.outPreSol[0]?.v }}</td>
            <td>{{ totalProfitValue.outPreSol[1]?.p }}: {{ totalProfitValue.outPreSol[1]?.v }}</td>
            <td>{{ totalProfitValue.outSubSol[0]?.p }}: {{ totalProfitValue.outSubSol[0]?.v }}</td>
            <td>{{ totalProfitValue.outSubSol[1]?.p }}: {{ totalProfitValue.outSubSol[1]?.v }}</td>
          </tr>
          <tr>
            <th>下注</th>
            <td>{{ psOptions.bet }}</td>
            <td>{{ totalProfitValue.outPreSol[0]?.g }}</td>
            <td>{{ totalProfitValue.outPreSol[1]?.g }}</td>
            <td>{{ totalProfitValue.outSubSol[0]?.g }}</td>
            <td>{{ totalProfitValue.outSubSol[1]?.g }}</td>
          </tr>
          <tr>
            <th>利润</th>
            <td>{{ totalProfitValue.profit.win_ps }}</td>
            <td colspan="2">{{ totalProfitValue.profit.win_target }}</td>
            <td colspan="2">{{ totalProfitValue.profit.win_target }}</td>
          </tr>
        </table>
      </div>
    </Drawer> -->

  </div>
</template>

<style lang="scss" scoped>
.contents-header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 201;
  width: 100%;
  border-bottom: 1px solid hsl(var(--border));
  background-color: hsl(var(--background));
}
.solution-options {
  position: relative;
  display: flex;
  align-items: center;
  padding: 5px 20px;
  border-bottom: 1px solid hsl(var(--border));
}
.solution-header {
  position: relative;
  display: flex;
  align-items: center;
  height: 30px;
  padding: 0 20px;
  span,
  em {
    display: block;
    text-align: center;
  }

  span {
    flex: 1;
  }

  em {
    width: 80px;
    font-style: normal;
  }
}

.solution-container {
  padding-top: 74px;
}

.solution-item {
  display: flex;
  .match-card {
    flex: 1;
  }
}

.solution-list {
  padding: 20px;
  overflow: hidden;

  .solution-item {
    border-radius: 10px;
    background-color: hsl(var(--card));

    &.selected {
      background-color: hsl(var(--primary) / 0.15);
    }

    &.disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }

    &:not(:last-child) {
      margin-bottom: 20px;
    }

    .match-card {
      border-right: 1px solid hsl(var(--border));
    }

    .solution-profit {
      display: flex;
      flex-direction: column;
      width: 80px;
      align-items: center;
      justify-content: center;
    }
  }
}

.profit-info {
  table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    table-layout: fixed;
    th, td {
      height: 30px;
      border: 1px solid hsl(var(--border));
      text-align: center;
    }
    th {
      width: 64px;
      font-weight: normal;
    }
  }
}

.list-empty {
  text-align: center;
  padding: 10px;
  font-size: 18px;
  color: hsl(var(--foreground) / 0.7);
}
</style>
