<template>
  <div class="dest-mass-route-container">
    <div v-if="generalError">
      <div class="destination-mass-route-info">
        <ph-warning size="18px"></ph-warning>
        The routing data is faulty. Please contact support.
        You can try to solve the problem by first deleting all destinations and then creating them again.
      </div>
    </div>
    <div v-else class="dest-mass-route-table-wrapper">
      <div class="dest-mass-route-table-header-wrapper"
           ref="headerWrapper"
           @scroll="syncScroll('header')">
        <div class="dest-mass-route-table-header">
          <div class="dest-mass-route-table-header-supplier"></div>
          <div class="dest-mass-route-table-header-dest"
               :key="`${dest.id}`"
               v-for="dest in destPool">
            <div></div>
            <div>{{ toNode(dest.destination_node, 6) }}</div>
          </div>
        </div>
      </div>

      <div class="dest-mass-route-table"
           ref="tableBody"
           @scroll="syncScroll('body')">
        <destination-mass-route-row :row="row"
                                    :key="row.id"
                                    v-for="row in rows"></destination-mass-route-row>
      </div>
    </div>
  </div>
</template>


<script>

import DestinationMassQuantityRow from "@/components/layout/edit/destination/mass/DestinationMassQuantityRow.vue";
import Checkbox from "@/components/UI/Checkbox.vue";
import IconButton from "@/components/UI/IconButton.vue";
import {mapStores} from "pinia";
import {useDestinationEditStore} from "@/store/destinationEdit.js";
import {usePremiseEditStore} from "@/store/premiseEdit.js";
import {toRaw} from "vue";
import DestinationMassRouteRow from "@/components/layout/edit/destination/mass/DestinationMassRouteRow.vue";
import Flag from "@/components/UI/Flag.vue";
import logger from "@/logger.js";

export default {
  name: "DestinationMassRoute",
  components: {Flag, DestinationMassRouteRow, IconButton, Checkbox, DestinationMassQuantityRow},
  props: {
    premiseIds: {
      type: Array,
      required: true
    },
    onLoadingChange: {
      type: Function,
      default: () => {}
    }
  },
  computed: {
    ...mapStores(useDestinationEditStore, usePremiseEditStore),
    rows() {
      return this.destinationEditStore.getRouteMatrix ?? [];
    }
  },
  data() {
    return {
      destPool: null,
      generalError: false,
      isScrollingSyncronized: false,
    }
  },
  async created() {
    this.onLoadingChange(true);
    try {
      await new Promise(resolve => setTimeout(() => {
        this.buildMatrix();
        resolve();
      }, 10));
    } finally {
      this.onLoadingChange(false);
    }
  },
  methods: {
    syncScroll(source) {
      if (this.isScrollingSyncronized) {
        this.isScrollingSyncronized = false;
        return;
      }

      this.isScrollingSyncronized = true;

      if (source === 'body') {
        this.$refs.headerWrapper.scrollLeft = this.$refs.tableBody.scrollLeft;
      } else if (source === 'header') {
        this.$refs.tableBody.scrollLeft = this.$refs.headerWrapper.scrollLeft;
      }
    },
    toNode(node, limit = 5) {
      if (!node)
        return 'N/A';

      const name = node.name;
      const mappingId = node.external_mapping_id;
      const needsShortName = name.length > limit;
      const useMappingId = ((mappingId ?? null) !== null) && ((name ?? null) === null || needsShortName);
      const shortName = name?.substring(0, limit).concat("...") ?? 'N/A';
      return `${useMappingId ? mappingId.replace("_", " ") : (needsShortName ? shortName : name)}`;

    },
    async buildMatrix() {
      const columnHeadersMap = new Map();
      const supplierToDestinationsMap = new Map();

      for (const pId of this.premiseIds) {
        const curPremise = this.premiseEditStore.getById(pId);
        const destOfCurPremise = this.destinationEditStore.getByPremiseId(pId);
        if (!destOfCurPremise) continue;

        /* supplier map collects all destinations for one supplier.
         * if there is more than one instance of a destination for one supplier
         * (more than one part number), a destination instance is chosen by the following priority list:
         * 1. instances with d2d rate
         * 2. instances with selected routes
         * 3. all other instances.
         */
        if (!supplierToDestinationsMap.has(curPremise.supplier.id)) {
          supplierToDestinationsMap.set(curPremise.supplier.id, {
            destinations: [...destOfCurPremise]
          });
        } else {
          const mapEntry = supplierToDestinationsMap.get(curPremise.supplier.id);
          const exDs = mapEntry.destinations;

          destOfCurPremise.forEach(d => {
            const exD = exDs.find(ex => ex.destination_node.id === d.destination_node.id) ?? null;

            if (!exD) {
              exDs.push(d);
            } else {

              if ((!exD.routes?.some(r => r.is_selected) && d.routes?.some(r => r.is_selected) && !exD.is_d2d) || (!exD.is_d2d && d.is_d2d)) {
                const idx = exDs.indexOf(exD);
                exDs.splice(idx, 1);
                exDs.push(d);
              }
            }
          })
        }

        /* Collects all destinations over all
         * suppliers and part numbers for the table headers
         */
        for (const d of destOfCurPremise) {
          const destId = d.destination_node.id;
          if (!columnHeadersMap.has(destId)) {
            columnHeadersMap.set(destId, {
              destination_node: {...d.destination_node},
              destinationNodeId: d.destination_node.id,
              destinationNodeName: d.destination_node.name
            });
          }
        }
      }

      this.destPool = Array.from(columnHeadersMap.values());



      const premiseMap = new Map();

      this.premiseIds.forEach(pId => {
        const curPremise = this.premiseEditStore.getById(pId);
        const destOfCurPremise = this.destinationEditStore.getByPremiseId(pId);

        if (!premiseMap.has(curPremise.supplier.id)) {
          premiseMap.set(curPremise.supplier.id, {
            ids: [],
            supplierNodeId: curPremise.supplier.id,
            supplier: curPremise.supplier,
            destinations: this.buildDestinations(columnHeadersMap, supplierToDestinationsMap.get(curPremise.supplier.id)?.destinations ?? [])
          });
        }

        const row = premiseMap.get(curPremise.supplier.id);

        if (row) {
          row.ids.push(curPremise.id);
          this.addDestinationsToRow(row.destinations, destOfCurPremise)
        }

      });

      const destMatrix = Array.from(premiseMap.values());
      this.generalError = destMatrix.some(r => !r.destinations.every(d => d.valid));

      this.destinationEditStore.setRouteMatrix(destMatrix)
      await this.$nextTick();
    },
    buildDestinations(allDestinationsMap, assignedDestinations) {
      return Array.from(allDestinationsMap.values()).map(d => {

        const assignedDest = assignedDestinations.find(dest => dest.destination_node.id === d.destinationNodeId);

        const builtRoutes = this.buildRoutes(assignedDest?.routes);
        const selectedBuildRoute = builtRoutes?.find(r => r.selected)?.routeCompareString ?? null;

        return {
          ids: [],
          disabled: true,
          valid: true,
          destinationNodeId: d.destinationNodeId,
          destinationName: d.destinationNodeName,
          routes: builtRoutes,
          isD2d: assignedDest?.is_d2d ?? false,
          rateD2d: assignedDest?.rate_d2d ?? null,
          leadTimeD2d: assignedDest?.lead_time_d2d === 0 ? null : (assignedDest?.lead_time_d2d ?? null),
          selectedRoute: selectedBuildRoute
        }
      });
    },
    addDestinationsToRow(rowDestinations, destOfPremises) {
      destOfPremises.forEach(curDestOfPremise => {

        /* rowDestinations contains all here known destinations that are shown
         *
         *
         */
        let existingDest = rowDestinations.find(rowD => rowD.destinationNodeId === curDestOfPremise.destination_node.id) ?? null;

        if (existingDest) {
          existingDest.disabled = false;

          if(existingDest.ids.includes(curDestOfPremise.id))
            logger.log("Duplicate id: ", curDestOfPremise.id);

          existingDest.ids.push(curDestOfPremise.id);

          /* add route ids to routes */
          this.verifyRoutes(existingDest, curDestOfPremise)
        }
      });
    },
    verifyRoutes(rowDest, premiseDest) {

      const premiseRoutes = premiseDest.routes;

      if (rowDest.routes.length !== premiseRoutes.length) {
        logger.log("length mismatch ", toRaw(rowDest), toRaw(premiseDest));
        rowDest.valid = false;
        return
      }

      premiseRoutes.forEach(route => {
        const routeString = JSON.stringify(route.transit_nodes.map(n => n.external_mapping_id)); //.join(" > ").replace("_", " ");

        const rowRoute = rowDest.routes.find(r => r.routeCompareString === routeString && r.type === route.type);

        if (!rowRoute) {
          logger.log("no matching route ", routeString, rowDest);
          rowDest.valid = false;
        } else {
          rowRoute.ids.push(route.id);
        }
      });
    },
    buildRoutes(routes) {

      return routes?.map(r => {
        return {
          ids: [],
          type: r.type,
          selected: r.is_selected,
          transitNodes: r.transit_nodes.map(n => n.external_mapping_id),
          routeCompareString: JSON.stringify(r.transit_nodes.map(n => n.external_mapping_id)), //.join(" > ").replace("_", " ")
          routeDisplayString: this.toRoute(r)
        }
      }) ?? [];
    },
    toRoute(route, limit = 48) {

      if (!route)
        return 'N/A';

      const nodes = route.transit_nodes?.map((node) => this.toNode(node)) ?? [];

      if (nodes.length === 0)
        return 'N/A';

      const separator = " > ";
      let fullString = nodes.join(separator);

      if (fullString.length <= limit)
        return fullString;

      const front = nodes[0].concat(separator).concat("...").concat(separator);
      let back = [];

      for (const node of nodes.slice().reverse()) {

        back.unshift(node);
        const temp = front.concat(back.join(separator));

        if (temp.length > limit) {
          return front.concat(back.slice(1).join(separator));
        }

      }
    },
  }
}
</script>


<style scoped>

.destination-mass-route-info {
  display: flex;
  align-items: center;
  font-size: 1.4rem;
  gap: 1.6rem;
  background-color: #BC2B72;
  color: #ffffff;
  border-radius: 0.8rem;
  padding: 1.6rem;
  margin: 1.6rem 1.6rem 0 1.6rem;
}


/* Global style für copy-mode cursor */
.dest-mass-route-container.has-selection :deep(.dest-mass-route-row__cell--copyable:hover) {
  cursor: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDEyOC41MSAxMzQuMDUiPjxkZWZzPjxzdHlsZT4uY3tmaWxsOm5vbmU7fS5jLC5ke3N0cm9rZTojMDEwMTAxO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4O30uZHtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJhIj48cGF0aCBjbGFzcz0iYyIgZD0ibTU0Ljg5LDExMi41MWgtMi4yNGMtMS4yNCwwLTIuMjQtMS0yLjI0LTIuMjR2LTIuMjQiLz48bGluZSBjbGFzcz0iYyIgeDE9IjcwLjU3IiB5MT0iNzYuNjciIHgyPSI2My44NSIgeTI9Ijc2LjY3Ii8+PGxpbmUgY2xhc3M9ImMiIHgxPSI3MC41NyIgeTE9IjExMi41MSIgeDI9IjY2LjA5IiB5Mj0iMTEyLjUxIi8+PGxpbmUgY2xhc3M9ImMiIHgxPSI4Ni4yNSIgeTE9Ijk5LjA3IiB4Mj0iODYuMjUiIHkyPSI5Mi4zNSIvPjxsaW5lIGNsYXNzPSJjIiB4MT0iNTAuNDEiIHkxPSI5Ni44MyIgeDI9IjUwLjQxIiB5Mj0iOTIuMzUiLz48cGF0aCBjbGFzcz0iYyIgZD0ibTgxLjc3LDExMi41MWgyLjI0YzEuMjQsMCwyLjI0LTEsMi4yNC0yLjI0di0yLjI0Ii8+PHBhdGggY2xhc3M9ImMiIGQ9Im04MS43Nyw3Ni42N2gyLjI0YzEuMjQsMCwyLjI0LDEsMi4yNCwyLjI0djIuMjQiLz48cGF0aCBjbGFzcz0iYyIgZD0ibTU0Ljg5LDc2LjY3aC0yLjI0Yy0xLjI0LDAtMi4yNCwxLTIuMjQsMi4yNHYyLjI0Ii8+PHBhdGggY2xhc3M9ImMiIGQ9Im04Ni4yNSw5OS4wN2gxMS4yYzEuMjQsMCwyLjI0LTEsMi4yNC0yLjI0di0zMS4zNmMwLTEuMjQtMS0yLjI0LTIuMjQtMi4yNGgtMzEuMzZjLTEuMjQsMC0yLjI0LDEtMi4yNCwyLjI0djExLjIiLz48L2c+PGcgaWQ9ImIiPjxwYXRoIGNsYXNzPSJkIiBkPSJtNDQuMDgsNDQuMDdsMzIuOTQtOS4yYzEuNjktLjUyLDIuNjQtMi4zMSwyLjEyLTQtLjMtLjk4LTEuMDUtMS43NS0yLjAxLTIuMDlMNi43MywyLjY3Yy0xLjY3LS41Ny0zLjQ5LjMzLTQuMDYsMi0uMjMuNjYtLjIzLDEuMzgsMCwyLjA1bDI2LjExLDcwLjRjLjU4LDEuNjcsMi40LDIuNTYsNC4wNywxLjk4Ljk3LS4zMywxLjcxLTEuMTEsMi4wMS0yLjA5bDkuMjItMzIuOTRaIi8+PC9nPjwvc3ZnPg==") 12 12, pointer;
  background-color: #f8fafc;
  border-radius: 0.8rem;
}

/* Global style für filter-mode cursor */
.dest-mass-route-container.add-all :deep(.dest-mass-route-row__cell--filterable:hover) {
  cursor: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDEyOC41MSAxMzQuMDUiPjxkZWZzPjxzdHlsZT4uY3tmaWxsOm5vbmU7fS5jLC5ke3N0cm9rZTojMDEwMTAxO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4O30uZHtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjxnIGlkPSJhIj48bGluZSBjbGFzcz0iYyIgeDE9IjczLjAzIiB5MT0iNzUuNTUiIHgyPSI2Ni4zOCIgeTI9Ijc1LjU1Ii8+PGxpbmUgY2xhc3M9ImMiIHgxPSI2Ni4zOCIgeTE9IjExMi4xNiIgeDI9IjczLjAzIiB5Mj0iMTEyLjE2Ii8+PHBhdGggY2xhc3M9ImMiIGQ9Im04MS4zNSw3NS41NWg0Ljk5Yy45MiwwLDEuNjYuNzUsMS42NiwxLjY2djQuOTkiLz48bGluZSBjbGFzcz0iYyIgeDE9Ijg4LjAxIiB5MT0iOTcuMTgiIHgyPSI4OC4wMSIgeTI9IjkwLjUzIi8+PHBhdGggY2xhc3M9ImMiIGQ9Im04MS4zNSwxMTIuMTZoNC45OWMuOTIsMCwxLjY2LS43NSwxLjY2LTEuNjZ2LTQuOTkiLz48bGluZSBjbGFzcz0iYyIgeDE9IjUxLjQiIHkxPSI5MC41MyIgeDI9IjUxLjQiIHkyPSI5Ny4xOCIvPjxwYXRoIGNsYXNzPSJjIiBkPSJtNTguMDUsMTEyLjE2aC00Ljk5Yy0uOTIsMC0xLjY2LS43NS0xLjY2LTEuNjZ2LTQuOTkiLz48cGF0aCBjbGFzcz0iYyIgZD0ibTU4LjA1LDc1LjU1aC00Ljk5Yy0uOTIsMC0xLjY2Ljc1LTEuNjYsMS42NnY0Ljk5Ii8+PC9nPjxnIGlkPSJiIj48cGF0aCBjbGFzcz0iZCIgZD0ibTQ0LjA4LDQ0LjA3bDMyLjk0LTkuMmMxLjY5LS41MiwyLjY0LTIuMzEsMi4xMi00LS4zLS45OC0xLjA1LTEuNzUtMi4wMS0yLjA5TDYuNzMsMi42N2MtMS42Ny0uNTctMy40OS4zMy00LjA2LDItLjIzLjY2LS4yMywxLjM4LDAsMi4wNWwyNi4xMSw3MC40Yy41OCwxLjY3LDIuNCwyLjU2LDQuMDcsMS45OC45Ny0uMzMsMS43MS0xLjExLDIuMDEtMi4wOWw5LjIyLTMyLjk0WiIvPjwvZz48L3N2Zz4=") 12 12, pointer;
  background-color: #f8fafc;
  border-radius: 0.8rem;
}

/* Global style für filter-mode cursor */
.dest-mass-route-container.apply-filter :deep(.dest-mass-route-row__cell--filterable:hover) {
  cursor: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDEyOC41MSAxMzQuMDUiPjxkZWZzPjxzdHlsZT4uZHtzdHJva2U6IzAwMDt9LmQsLmV7ZmlsbDpub25lO30uZCwuZSwuZntzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjVweDt9LmUsLmZ7c3Ryb2tlOiMwMTAxMDE7fS5me2ZpbGw6I2ZmZjt9PC9zdHlsZT48L2RlZnM+PGcgaWQ9ImEiPjxsaW5lIGNsYXNzPSJlIiB4MT0iNzMuMDMiIHkxPSI3NS41NSIgeDI9IjY2LjM4IiB5Mj0iNzUuNTUiLz48bGluZSBjbGFzcz0iZSIgeDE9IjY2LjM4IiB5MT0iMTEyLjE2IiB4Mj0iNzMuMDMiIHkyPSIxMTIuMTYiLz48cGF0aCBjbGFzcz0iZSIgZD0ibTgxLjM1LDc1LjU1aDQuOTljLjkyLDAsMS42Ni43NSwxLjY2LDEuNjZ2NC45OSIvPjxsaW5lIGNsYXNzPSJlIiB4MT0iODguMDEiIHkxPSI5Ny4xOCIgeDI9Ijg4LjAxIiB5Mj0iOTAuNTMiLz48cGF0aCBjbGFzcz0iZSIgZD0ibTgxLjM1LDExMi4xNmg0Ljk5Yy45MiwwLDEuNjYtLjc1LDEuNjYtMS42NnYtNC45OSIvPjxsaW5lIGNsYXNzPSJlIiB4MT0iNTEuNCIgeTE9IjkwLjUzIiB4Mj0iNTEuNCIgeTI9Ijk3LjE4Ii8+PHBhdGggY2xhc3M9ImUiIGQ9Im01OC4wNSwxMTIuMTZoLTQuOTljLS45MiwwLTEuNjYtLjc1LTEuNjYtMS42NnYtNC45OSIvPjxwYXRoIGNsYXNzPSJlIiBkPSJtNTguMDUsNzUuNTVoLTQuOTljLS45MiwwLTEuNjYuNzUtMS42NiwxLjY2djQuOTkiLz48L2c+PGcgaWQ9ImIiPjxwYXRoIGNsYXNzPSJmIiBkPSJtNDQuMDgsNDQuMDdsMzIuOTQtOS4yYzEuNjktLjUyLDIuNjQtMi4zMSwyLjEyLTQtLjMtLjk4LTEuMDUtMS43NS0yLjAxLTIuMDlMNi43MywyLjY3Yy0xLjY3LS41Ny0zLjQ5LjMzLTQuMDYsMi0uMjMuNjYtLjIzLDEuMzgsMCwyLjA1bDI2LjExLDcwLjRjLjU4LDEuNjcsMi40LDIuNTYsNC4wNywxLjk4Ljk3LS4zMywxLjcxLTEuMTEsMi4wMS0yLjA5bDkuMjItMzIuOTRaIi8+PC9nPjxnIGlkPSJjIj48bGluZSBjbGFzcz0iZCIgeDE9Ijk5LjM4IiB5MT0iOTQuMTkiIHgyPSIxMjYuMDEiIHkyPSI5NC4xOSIvPjxsaW5lIGNsYXNzPSJkIiB4MT0iMTEyLjY5IiB5MT0iODAuODciIHgyPSIxMTIuNjkiIHkyPSIxMDcuNTEiLz48L2c+PC9zdmc+") 12 12, pointer;
  background-color: #f8fafc;
  border-radius: 0.8rem;
}

.text-container.disabled {
  background-color: #f3f4f6;
  cursor: not-allowed;
  border-color: #f3f4f6;
}

.text-container.disabled input {
  cursor: not-allowed;
}


.text-container:hover:not(.disabled) {
  background: #EEF4FF;
  border: 0.2rem solid #8DB3FE;
  transform: scale(1.01);

}


.input-field {
  border: none;
  outline: none;
  background: none;
  resize: none;
  font-family: inherit;
  font-size: 1.4rem;
  color: #002F54;

  max-width: 6rem;
}

.text-container {
  display: flex;
  align-items: center;
  background: white;
  border-radius: 0.4rem;
  padding: 0.6rem 1.2rem;
  /* box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);*/
  border: 0.2rem solid #E3EDFF;
  transition: all 0.1s ease;
  flex: 1 0 auto;

  max-width: 8rem;

}

.dest-mass-route-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

.dest-mass-route-table-wrapper {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex: 1;
  min-height: 0;
}

.dest-mass-route-table-header-wrapper {
  overflow-x: auto;
  overflow-y: hidden;
  flex-shrink: 0;

  /* Scrollbar verstecken aber Funktionalität behalten */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE/Edge */
}

.dest-mass-route-table-header-wrapper::-webkit-scrollbar {
  display: none; /* Chrome/Safari/Opera */
}



.dest-mass-route-table {
  flex: 1;
  overflow-y: auto;
  overflow-x: auto;
  min-height: 0;
  margin: 0;
  padding-bottom: 2.4rem;
}

.dest-mass-route-table-header {
  display: flex;
  flex-direction: row;
  gap: 1.6rem;
  padding: 1.6rem 2.4rem;
  justify-content: flex-start;

  background-color: #ffffff;
  border-bottom: 1px solid rgba(107, 134, 156, 0.2);
  font-weight: 500;
  font-size: 1.4rem;
  color: #6B869C;
  text-transform: uppercase;
  letter-spacing: 0.08rem;

  min-width: fit-content;
}

.dest-mass-route-table-header-supplier {
  width: 24rem;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}



.dest-mass-route-table-header-dest {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  width: 35rem;
  gap: 0.8rem;
  flex-shrink: 0;
}
</style>