<template>
  <div class="report report-daily-page">
    <div class="report-header mb-4">
      <h2 class="header-report-title">Báo cáo tình hình giao dịch & thanh toán theo ngày</h2>
      <div class="select-date">
        <span class="label-date">Chọn ngày báo cáo:</span> &nbsp;
        <Datepicker v-bind="{ record: infoReport, attr: 'date-report' }" @date="select('date-report', $event)" />
      </div>
    </div>
    <div class="report-body">
      <!-- Report Product -->
      <div class="report-product">
        <div class="fixed-grid has-6-cols-desktop has-3-cols-tablet has-2-cols-mobile">
          <div class="grid">
            <div class="cell">
              <p class="cell-label">Tổng số sản phẩm</p>
              <span class="cell-value">{{ totalProduct }}</span>
            </div>

            <div
              class="cell event"
              v-for="product in saleStatusProductSummary"
              :style="{ color: product.color }"
              @click="handlerStatusProduct($event, product)"
            >
              <p class="cell-label">{{ product.name }}</p>
              <span class="cell-value">{{ product.count || 0 }}</span>
            </div>
          </div>
        </div>
        <div class="chart-report-product">
          <div class="fixed-grid has-1-cols has-3-cols-desktop">
            <div class="grid">
              <div class="cell">
                <div class="chart-status-product">
                  <client-only>
                    <highcharts-vue-chart :highcharts="Highcharts" :options="chartProductStatusOptions" />
                  </client-only>
                </div>
              </div>
              <div class="cell">
                <div class="chart-zone-product">
                  <client-only>
                    <highcharts-vue-chart :highcharts="Highcharts" :options="chartProductZoneOptions" />
                  </client-only>
                </div>
              </div>
              <div class="cell">
                <div class="chart-product-dealer">
                  <client-only>
                    <highcharts-vue-chart :highcharts="Highcharts" :options="chartProductDealerOptions" />
                  </client-only>
                </div>
              </div>
            </div>
          </div>
          <div class="chart-cart-product">
            <client-only>
              <highcharts-vue-chart :highcharts="Highcharts" :options="chartStatusProductDealerOptions" />
            </client-only>
          </div>
        </div>
      </div>
      <!-- End Report Porduct -->
    </div>
    <Modal @close="handlerCloseModal" v-bind="showModal" v-if="showModal.lock"> </Modal>
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import Highcharts from "highcharts";
import { Chart as HighchartsVueChart } from "highcharts-vue";

import Datepicker from "~/components/datepicker/Datepicker";

const { $numtoString, $findapi, $getapi, $store, $getdata, $mode } = useNuxtApp();

const dealer = $store.dealer;
const isVietnamese = computed(() => $store.lang.toLowerCase() === "vi");
const today = new Date().toISOString().split("T")[0];

let selectedChartPie = null;

const productsResponse = ref(null);
const totalProduct = ref(0);

const infoReport = ref({
  "date-report": today,
});

const showModal = ref({
  title: null,
  lock: false,
});

const dataStatusProduct = ref({
  totalProduct: 0,
  totalValue: 0,
  statusCode: null,
  statusName: null,
  totalLandArea: 0,
  totalBuildingArea: 0,
  totalFloorArea: 0,
  listProduct: [],
});

const listSaleStatus = await $getdata("salestatus");
// const listZoneType = await $getdata("zonetype");

const select = (fieldName, value) => {
  infoReport.value[fieldName] = value;
};

function buildDateRange(date) {
  if (!date) return null;
  const dateTemp = new Date(date).toISOString().split("T")[0];
  const start = new Date(`${dateTemp}T00:00:00.000Z`);
  const end = new Date(`${dateTemp}T23:59:59.999Z`);

  return {
    start: start.toISOString(),
    end: end.toISOString(),
  };
}

const groupByField = (list, { keyField, nameField, nameTransform, colorField }) => {
  if (!Array.isArray(list) || list.length === 0) return [];

  const map = new Map();

  for (const item of list) {
    const key = item[keyField];
    if (!key) continue;

    let group = map.get(key);

    if (!group) {
      group = {
        key,
        name: nameTransform ? nameTransform(item[nameField]) : nameField ? item[nameField] : key,
        color: colorField ? item[colorField] : null,
        count: 0,
        children: [],
      };
      map.set(key, group);
    }

    group.count++;
    group.children.push(item);
  }

  return [...map.values()];
};

function buildGroupMap(list = []) {
  if (!Array.isArray(list)) return new Map();

  return new Map(list.filter((item) => item?.key != null).map((item) => [item.key, item]));
}

function mergeMasterWithGroup(masterList = [], groupMap) {
  if (!Array.isArray(masterList)) return [];

  return masterList.map((item) => {
    const found = groupMap.get(item.code);

    return {
      ...item,
      count: found?.count ?? 0,
      children: found?.children ?? [],
    };
  });
}

const formatVniDate = (date) => {
  const dateTemp = date ? new Date(date) : new Date();
  const d = String(dateTemp.getDate()).padStart(2, "0");
  const m = String(dateTemp.getMonth() + 1).padStart(2, "0");
  const y = dateTemp.getFullYear();
  return `${d}/${m}/${y}`;
};

function formatVND(amount, decimals = 2) {
  if (!amount || isNaN(amount)) return "0 đ";

  if (amount >= 1_000_000_000) return `${(amount / 1_000_000_000).toFixed(decimals)} tỷ`;

  if (amount >= 1_000_000) return `${(amount / 1_000_000).toFixed(decimals)} triệu`;

  return `${amount.toLocaleString("vi-VN")} đ`;
}

function colorStatus(value) {
  if (value > 100) {
    return "#006400";
  }

  if (value >= 90 && value <= 100) {
    return "#2ECC71";
  }

  if (value >= 75 && value < 90) {
    return "#F1C40F";
  }

  if (value >= 60 && value < 75) {
    return "#E67E22";
  }

  if (value < 60) {
    return "#E74C3C";
  }

  return "#BDC3C7";
}

function calcPercentage(part, whole, decimals = 1) {
  const numerator = Number(part) || 0;
  const denominator = Number(whole) || 0;

  if (denominator === 0) return 0;

  return Number(((numerator / denominator) * 100).toFixed(decimals));
}

function buildChartSeriesByStatus(statusList = [], parents = [], keyGroup = "status") {
  const parentStatusMaps = parents.map(
    (parent) => new Map((parent[keyGroup] ?? []).map((st) => [st.key ?? st.code, st.count ?? 0]))
  );

  return statusList.map((status) => ({
    name: status.name?.split(". ")[1] ?? status.name,
    color: status.color || undefined,
    data: parentStatusMaps.map((map) => ({
      y: map.get(status.code) ?? 0,
      key: status.code,
    })),
  }));
}

let scrollPosition = 0;

const toggleBodyScroll = (isActive) => {
  if (isActive) {
    scrollPosition = window.scrollY || document.documentElement.scrollTop;
    document.body.classList.add("popup-open");
    document.body.style.top = `-${scrollPosition}px`;
  } else {
    document.body.classList.remove("popup-open");
    document.body.style.top = "";
    window.scrollTo(0, scrollPosition);
  }
};

// <====== Fetch product list ======>
let foundProduct = $findapi("product");
foundProduct.params.values =
  "id,code,trade_code,zone_code,type__code,type__name,zone_type__code,zone_type__code,zone_type__name,direction__code,direction__name,land_lot_size,lot_area,building_area,number_of_floors,cart__code,cart__name,cart__dealer__code,cart__dealer__name,origin_price,txnprd__sale_price,status__code,status__name,status__color,status__sale_status__code,status__sale_status__name,status__sale_status__color";
if (dealer?.code) {
  foundProduct.params.filter = { cart__dealer__code: dealer?.code };
  foundProduct.params.exclude = { status__sale_status__code: "not-sold" };
}

async function fetchProducts() {
  try {
    const [productRes] = await $getapi([foundProduct]);
    productsResponse.value = productRes?.data?.rows ?? [];
    totalProduct.value = productsResponse.value?.length;
  } catch (error) {
    if ($mode === "dev") {
      console.error("Call api product error", error);
    }
    productsResponse.value = [];
    totalProduct.value = 0;
  }
}
fetchProducts();
// <====== End fetch product list ======>

// <====== Group status product ======>
const productGroupStatus = computed(() =>
  groupByField(productsResponse.value, {
    keyField: "status__sale_status__code",
    nameField: "status__sale_status__name",
    nameTransform: (name) => name?.split(". ")[1] ?? name,
    colorField: "status__sale_status__color",
  })
);

const productGroupStatusMap = computed(() => buildGroupMap(productGroupStatus.value));

const saleStatusProductSummary = computed(() => {
  const merged = mergeMasterWithGroup(listSaleStatus || [], productGroupStatusMap.value);

  return merged.map((item) => {
    const name = item.name?.split(". ")[1] ?? item.name;
    return {
      ...item,
      name,
    };
  });
});

const handlerStatusProduct = (e, data) => {
  e.preventDefault();
  e.stopPropagation();

  updateProductStatusSummary(data);
  showModal.value = {
    component: "report/TableReportProduct",
    lock: true,
    title: `Danh sách sản phẩm - Trạng thái: ${data.name} (${formatVniDate(infoReport["date-date-report"])})`,
    width: "80%",
    height: "80%",
    vbind: { data: dataStatusProduct.value },
  };
  handlerOpenModal();
};

function updateProductStatusSummary(statusData = {}) {
  const listProduct = (statusData.children || []).map((item) => {
    const buildingArea = Number(item.building_area ?? 0);
    const floors = Number(item.number_of_floors ?? 0);
    const totalBuildingArea = buildingArea * floors;
    const total_built_area = $numtoString(totalBuildingArea);
    item.txnprd__sale_price = item.txnprd__sale_price ?? item.origin_price;
    return {
      ...item,
      total_built_area,
    };
  });

  const totals = listProduct.reduce(
    (acc, product) => {
      const salePrice = Number(product.txnprd__sale_price ?? 0);
      const landArea = Number(product.lot_area ?? 0);
      const buildingArea = Number(product.building_area ?? 0);
      const floors = Number(product.number_of_floors ?? 0);

      acc.totalValue += salePrice;
      acc.totalLandArea += landArea;
      acc.totalBuildingArea += buildingArea;
      acc.totalFloorArea += buildingArea * floors;

      return acc;
    },
    {
      totalValue: 0,
      totalLandArea: 0,
      totalBuildingArea: 0,
      totalFloorArea: 0,
    }
  );

  dataStatusProduct.value = {
    statusCode: statusData.code || statusData.key,
    statusName: statusData.name ?? null,
    totalProduct: statusData.count ?? 0,
    totalValue: totals.totalValue,
    totalLandArea: $numtoString(totals.totalLandArea),
    totalBuildingArea: $numtoString(totals.totalBuildingArea),
    totalFloorArea: $numtoString(totals.totalFloorArea),
    listProduct: listProduct,
  };
}

// Options chart status product
const chartSelectedStatusProductHandler = () => ({
  select() {
    selectedChartPie = this;
    const item = productGroupStatus.value.find((i) => i.key === this.options.key);
    updateProductStatusSummary(item);

    showModal.value = {
      component: "report/TableReportProduct",
      lock: true,
      title: `Danh sách sản phẩm - Trạng thái: ${this.options.name} (${formatVniDate(infoReport["date-date-report"])})`,
      width: "80%",
      height: "80%",
      vbind: { data: dataStatusProduct.value },
    };
    handlerOpenModal();
  },

  unselect() {
    if (selectedChartPie !== this) return;
    selectedChartPie = null;
    updateProductStatusSummary();
  },
});

const chartProductStatusOptions = computed(() => {
  return {
    chart: {
      type: "pie",
      zooming: {
        type: "xy",
      },
      panning: {
        enabled: true,
        type: "xy",
      },
    },
    title: {
      text: isVietnamese ? "Trạng thái sản phẩm" : "Product status",
    },
    subtitle: {
      text: `Dữ liệu ngày: ${formatVniDate(infoReport.value["date-report"])} - ${totalProduct.value} ${
        isVietnamese ? "Sản phẩm" : "Products"
      }`,
    },
    plotOptions: {
      pie: {
        allowPointSelect: true,
        cursor: "pointer",
        dataLabels: [
          {
            enabled: true,
            distance: 20,
            format: "{point.name}: {point.y:,.0f}", // GIÁ TRỊ
          },
          {
            enabled: true,
            distance: -40,
            format: "({point.percentage:.1f}%)", // GIÁ TRỊ
            style: {
              fontSize: "0.75em",
              textOutline: "none",
              opacity: 0.7,
            },
            filter: {
              operator: ">",
              property: "percentage",
              value: 10,
            },
          },
        ],
        point: {
          events: chartSelectedStatusProductHandler(),
        },
      },
    },
    series: [
      {
        name: isVietnamese ? "Số lượng" : "Quantity",
        colorByPoint: true,
        data: productGroupStatus.value.map((item) => {
          return {
            name: item.name,
            y: item.count,
            key: item.key,
            color: item.color,
          };
        }),
      },
    ],
  };
});

// <====== End group status product ======>

// <====== Group zone product ======>
const productGroupZone = computed(() =>
  groupByField(productsResponse.value, {
    keyField: "zone_type__code",
    nameField: "zone_type__name",
  })
);

// Options chart zone product
const chartProductZoneOptions = computed(() => {
  return {
    chart: {
      type: "pie",
      zooming: {
        type: "xy",
      },
      panning: {
        enabled: true,
        type: "xy",
      },
    },
    title: {
      text: isVietnamese ? "Sản phẩm theo phân khu" : "Products by category",
    },
    subtitle: {
      text: `Dữ liệu ngày: ${formatVniDate(infoReport.value["date-report"])} - ${productGroupZone.value.length} ${
        isVietnamese ? "Phân khu" : "Category"
      }`,
    },
    plotOptions: {
      pie: {
        cursor: "default",
        dataLabels: [
          {
            enabled: true,
            distance: 20,
            format: "{point.name}: {point.y:,.0f}", // GIÁ TRỊ
          },
          {
            enabled: true,
            distance: -40,
            format: "({point.percentage:.1f}%)", // GIÁ TRỊ
            style: {
              fontSize: "0.75em",
              textOutline: "none",
              opacity: 0.7,
            },
            filter: {
              operator: ">",
              property: "percentage",
              value: 10,
            },
          },
        ],
      },
    },
    series: [
      {
        name: isVietnamese ? "Số lượng" : "Quantity",
        colorByPoint: true,
        data: productGroupZone.value.map((item) => {
          return {
            name: item.name,
            y: item.count,
            key: item.key,
            color: item.color,
          };
        }),
      },
    ],
  };
});

// <====== End group zone product ======>

// <====== Group dealer product ======>
const productGroupDealer = computed(() =>
  groupByField(productsResponse.value, {
    keyField: "cart__dealer__code",
    nameField: "cart__dealer__name",
  })
);
// Options chart product dealer
const chartProductDealerOptions = computed(() => {
  return {
    chart: {
      type: "pie",
      zooming: {
        type: "xy",
      },
      panning: {
        enabled: true,
        type: "xy",
      },
    },
    title: {
      text: isVietnamese ? "Sản phẩm theo đại lý" : "Products by distributor",
    },
    subtitle: {
      text: `Dữ liệu ngày: ${formatVniDate(infoReport.value["date-report"])} - ${productGroupDealer.value?.length} ${
        isVietnamese ? "Đại lý" : "Dealer"
      }`,
    },
    plotOptions: {
      pie: {
        cursor: "default",
        dataLabels: [
          {
            enabled: true,
            distance: 20,
            format: "{point.name}: {point.y:,.0f}", // GIÁ TRỊ
          },
          {
            enabled: true,
            distance: -40,
            format: "({point.percentage:.1f}%)", // GIÁ TRỊ
            style: {
              fontSize: "0.75em",
              textOutline: "none",
              opacity: 0.7,
            },
            filter: {
              operator: ">",
              property: "percentage",
              value: 10,
            },
          },
        ],
      },
    },
    series: [
      {
        name: isVietnamese ? "Số lượng" : "Quantity",
        colorByPoint: true,
        data:
          productGroupDealer.value?.map((item) => {
            return {
              name: item.key,
              y: item.count,
              key: item.key,
              color: item.color ?? null,
            };
          }) || [],
      },
    ],
  };
});

//Options chart status product dealer
const dealerProductSaleSummary = computed(() =>
  (productGroupDealer.value ?? []).map((dealer) => {
    const productSaleByStatus = groupByField(dealer.children ?? [], {
      keyField: "status__sale_status__code",
      nameField: "status__sale_status__name",
      nameTransform: (name) => name?.split(". ")[1] ?? name,
      colorField: "status__sale_status__color",
    });

    return {
      ...dealer,
      productSaleByStatus,
    };
  })
);

const dataChartTransactionPolicy = computed(() => {
  const listSaleStatusDealer = listSaleStatus.filter((status) => status.code !== "not-sold");
  return buildChartSeriesByStatus(listSaleStatusDealer, dealerProductSaleSummary.value, "productSaleByStatus");
});

const createDealerStatusClickHandler = () => ({
  click() {
    const dealerCode = this.category?.split(" - ")?.[0] ?? null;
    const saleStatusCode = this.options?.key ?? null;

    if (!dealerCode || !saleStatusCode) return;

    const dealerSummary = dealerProductSaleSummary.value?.find((dealer) => dealer.key === dealerCode);

    const productsByStatus = dealerSummary?.productSaleByStatus?.find((status) => status.key === saleStatusCode);

    updateProductStatusSummary(productsByStatus);
    showModal.value = {
      component: "report/TableReportProduct",
      lock: true,
      title: `Danh sách sản phẩm - Đại lý: ${dealerSummary.key || dealerSummary.code} - Trạng thái: ${
        productsByStatus.name
      } (${formatVniDate(infoReport["date-date-report"])})`,
      width: "80%",
      height: "80%",
      vbind: { data: dataStatusProduct.value },
    };
    handlerOpenModal();
  },
});

const chartStatusProductDealerOptions = computed(() => {
  return {
    chart: {
      type: "column",
    },
    title: {
      text: isVietnamese ? "Trạng thái sản phẩm theo từng đại lý" : "Product status by dealer",
    },
    subtitle: {
      text: ` Dữ liệu ngày: ${formatVniDate(infoReport.value["date-report"])} `,
    },
    xAxis: {
      categories: dealerProductSaleSummary.value?.map((dealer) => `${dealer.key} - ${dealer.count} SP`),
      crosshair: true,
      accessibility: {
        description: "Countries",
      },
    },
    yAxis: {
      min: 0,
      title: {
        text: "Số lượng",
      },
    },
    tooltip: {
      headerFormat: "<b>{category}</b><br/>",
      pointFormat: "{series.name}: {point.y} Sản phẩm",
    },
    plotOptions: {
      column: {
        cursor: "pointer",
        pointPadding: 0.2,
        borderWidth: 0,
        dataLabels: {
          enabled: true,
          format: "{point.y}",
        },
        point: {
          events: createDealerStatusClickHandler(),
        },
      },
    },
    series: dataChartTransactionPolicy.value,
  };
});

// <====== End group dealer product ======>

const handleUnSelectChart = () => {
  const chart = Highcharts.charts.find((c) => c);
  if (chart) {
    chart.series[0]?.points.forEach((p) => {
      if (p.selected) p.select(false, false);
    });
  }
};

const handlerOpenModal = () => {
  toggleBodyScroll(true);
};

const handlerCloseModal = () => {
  toggleBodyScroll(false);
  showModal.value = {
    lock: false,
  };
  handleUnSelectChart();
};

// Reload data change
watch(
  infoReport,
  (newVal) => {
    // foundCustomer.params.filter.create_time__lte = buildDateRange(infoReport.value["date-report"])?.end;
    // foundCustomerTransaction.params.filter.txncust__create_time__lte = buildDateRange(
    //   infoReport.value["date-report"]
    // )?.end;
    // fetchCustomer();
  },
  { deep: true }
);
</script>

<style>
body.popup-open {
  position: fixed;
  width: 100%;
  overflow: hidden;
}

.report-daily-page .report-header {
  display: flex;
  justify-content: space-between;
}
.report-daily-page .report-header .header-report-title {
  font-size: 1.25rem;
  font-weight: bolder;
}

.report-daily-page .report-header .select-date {
  background-color: #204853;
  padding: 10px;
  border-radius: 16px;
}

.report-daily-page .report-header .select-date .label-date {
  color: #fff;
  margin-bottom: 10px;
  display: inline-block;
}
.report-daily-page .cell.event {
  padding: 10px;
  border-radius: 16px;
  cursor: pointer;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.report-daily-page .cell.event:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.report-daily-page .cell .cell-label {
  font-size: 13px;
  font-weight: 500;
}
.report-daily-page .cell .cell-value {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.2;
}

.report-daily-page .modal-card {
  overflow-y: hidden;
}

@media only screen and (max-width: 767px) {
  .report-daily-page .report-header {
    flex-direction: column;
    gap: 10px;
  }
}
</style>
