<script setup lang="ts">
import {computed, ref, watch} from "vue";
import {
  BarController,
  BarElement,
  CategoryScale,
  Chart as ChartJS,
  type ChartData,
  type ChartDataset,
  type ChartOptions,
  Filler,
  Legend,
  LinearScale,
  LineController,
  LineElement,
  PointElement,
  Tooltip,
} from "chart.js";
import {Chart} from "vue-chartjs";
import {useLedgerParam} from "@/ledger";
import {transactionApi} from "@/mammon";
import {useProcessedResource} from "@/activity";
import {DailyProfitResponse} from "@/generated/mammon";
import {IskLabel} from "@/market";
import {formatIsk} from "@/formaters";
import {DualRangeSlider} from "@/components";

ChartJS.register(
  CategoryScale, LinearScale,
  BarController, BarElement,
  LineController, LineElement, PointElement,
  Tooltip, Legend, Filler,
);

const {ledgerId} = useLedgerParam();

const profits = useProcessedResource<DailyProfitResponse[]>(async () => {
  if (!ledgerId.value) {
    return [];
  }

  const {data} = await transactionApi.profitPerDayInLedger(ledgerId.value);

  return data;
}, []);

const from = ref(0);
const to = ref(0);

watch(() => profits.value.length, length => {
  from.value = 0;
  to.value = Math.max(length - 1, 0);
}, {immediate: true});

const maxIndex = computed(() => Math.max(profits.value.length - 1, 0));

const range = computed(() => profits.value.slice(from.value, to.value + 1));

const total = computed(() => range.value.reduce((sum, p) => sum + p.profit, 0));

const cumulativeProfit = computed(() => {
  let running = 0;

  return range.value.map(p => (running += p.profit));
});

const chartData = computed<ChartData<'bar' | 'line'>>(() => {
  const cumulative: ChartDataset<'line'> = {
    type: 'line',
    label: 'Cumulative profit',
    data: cumulativeProfit.value,
    borderColor: '#38bdf8',
    backgroundColor: 'rgba(56, 189, 248, 0.15)',
    pointBackgroundColor: '#38bdf8',
    fill: true,
    tension: 0.2,
    yAxisID: 'y',
    order: 0,
  };

  const iskIn: ChartDataset<'bar'> = {
    type: 'bar',
    label: 'ISK in',
    data: range.value.map(p => p.iskIn),
    backgroundColor: 'rgba(16, 185, 129, 0.7)',
    yAxisID: 'y',
    order: 1,
  };

  const iskOut: ChartDataset<'bar'> = {
    type: 'bar',
    label: 'ISK out',
    data: range.value.map(p => -p.iskOut),
    backgroundColor: 'rgba(180, 83, 9, 0.7)',
    yAxisID: 'y',
    order: 1,
  };

  return {
    labels: range.value.map(p => p.date),
    datasets: [cumulative, iskIn, iskOut],
  };
});

const chartOptions = computed<ChartOptions<'bar' | 'line'>>(() => ({
  responsive: true,
  maintainAspectRatio: false,
  interaction: {mode: 'index', intersect: false},
  plugins: {
    legend: {display: true},
    tooltip: {
      callbacks: {
        label: ctx => `${ctx.dataset.label}: ${formatIsk(Math.abs(ctx.parsed.y ?? 0))}`,
      },
    },
  },
  scales: {
    x: {
      stacked: true,
    },
    y: {
      position: 'left',
      stacked: true,
      ticks: {
        callback: value => formatIsk(Math.abs(Number(value))),
      },
    }
  },
}));
</script>

<template>
  <div class="mt-4">
    <div class="flex justify-end mb-4">
      <span class="mr-2">Total profit:</span>
      <IskLabel :amount="total" />
    </div>

    <p v-if="profits.length === 0" class="text-center text-gray-400 mt-8">
      No trade profit recorded for this ledger
    </p>
    <template v-else>
      <div class="h-96">
        <Chart type="bar" :data="chartData" :options="chartOptions" />
      </div>

      <div class="flex items-center gap-3 mt-4">
        <span class="text-sm w-24 text-gray-400">{{ profits[from]?.date }}</span>
        <DualRangeSlider class="grow" :min="0" :max="maxIndex" v-model:from="from" v-model:to="to" />
        <span class="text-sm w-24 text-right text-gray-400">{{ profits[to]?.date }}</span>
      </div>
    </template>
  </div>
</template>

