<template>
  <div v-if="renderComponent" class="q-pa-sm" style="height: 700px; padding-left: 24px;padding-right: 16px;padding-top: 12px;">
    <BsGrid title="Full Table" :rows="rows_grid" :columns="columns_grid" :row-selection="selection"
      :group-hide-open-parents="true" :group-default-expanded="-1" :row-class-rules="rowClassRules"
      :auto-group-column-def="autoGroupColumnDef" :group-display-type="'groupRows'" :defaultColDef="{ minWidth: 120, resizable: true }" :enable-cell-text-selection="true" :suppress-row-click-selection="true">
      <template #searchBoxLegend>
        <div class="search-box-legend">
          <i class="dku-icon-star-fill-16" style="margin-right: 7px;"></i> <b style="font-size: 16px" font-style:
            normal>Primary
            dataset</b>
        </div>
      </template>
    </BsGrid>
  </div>
</template>

<script>
// Pinia
import { mapState, mapActions } from 'pinia';
import { useTableStore } from '../stores/tableStore';

// Local Components
import DropDownComponent from './DropDownComponent.vue';
import { API } from "@/Api"; // Kept for API.postCellValueChange

/**
 * Displays the full dataset in a single grid.
 * Connects to Pinia for all data, metadata, and update actions.
 */
export default {
  props: ['render'],
  components: {
    DropDownComponent
  },
  emits: [], 
  
  data() {
    return {
      // Local state for grid UI
      selection: "multiple",
      autoGroupColumnDef: true,
      rowClassRules: {
        "first-row-in-group": (params) =>
          params.node.rowIndex !== 0 && params.node.firstChild
      },
      renderComponent: true,
      columns_grid: [],
      rows_grid: [],
      loading: false,
    };
  },

  computed: {
    // Map all required state from the store
    ...mapState(useTableStore, {
      fullTable: 'fullTableData',
      primary_id_name: 'primaryIdName',
      secondary_id_name: 'secondaryIdName',
      primary_keys: 'primaryTableKeys',
      secondary_keys: 'secondaryTableKeys',
    }),
    
    /** List of all column names from the store's data. */
    all_columns() {
      return Object.keys(this.fullTable);
    }
  },

  /** Process data if it's already available on component mount. */
  mounted: function () {
      if (this.primary_keys && this.primary_keys.length > 0 && this.fullTable && Object.keys(this.fullTable).length > 0) {
        this.processTableData();
      }
  },
  
  watch: {
    /** Watches the `render` prop to manually force a re-render. */
    render(n, v) {
      this.forceRerendering();
    },

    /** Handles the INITIAL load once metadata is ready. */
    primary_keys(newKeys) {
      if (newKeys && newKeys.length > 0 && this.fullTable && Object.keys(this.fullTable).length > 0) {
        this.processTableData();
      }
    },

    /** Handles SUBSEQUENT updates (e.g., after an updateCell call). */
    fullTable(newTableData) {
      // Guard clause prevents race condition on initial load
      if (this.primary_keys && this.primary_keys.length > 0) {
        this.processTableData();
      }
    }
  },

  methods: {
    ...mapActions(useTableStore, ['updateCell']),

    /** Forces the component to re-render. */
    forceRerendering() {
      this.renderComponent = false;
      this.$nextTick(() => {
        this.renderComponent = true;
      });
    },

/**
     * Core method. Reads store data/metadata to build column definitions
     * and row data for the grid.
     */
    async processTableData() {
        this.loading = true;
        try {
          this.columns_grid = this.all_columns.map((col, index) => {
            const cleanedFieldName = col;
            const headerName = cleanedFieldName.charAt(0).toLowerCase() + cleanedFieldName.slice(1);
            
            const isPrimaryKey = this.primary_keys.includes(cleanedFieldName);
            const isSecondaryKey = this.secondary_keys.includes(cleanedFieldName);

            // Specific column definitions must come before general ones
            
            if (cleanedFieldName === "Match") {
              return { field: cleanedFieldName, minWidth: 150, resizable: true, cellEditor: "agRichSelectCellEditor", cellRenderer: "DropDownComponent", cellClass: "match-column", cellEditorParams: { values: ["Pending", "Approved", "Rejected"], cellRenderer: (params) => `<span style="font-size: 14px;">${params.value}</span>` }, editable: true, onCellValueChanged: async (event) => {
                const { newValue, oldValue, data } = event;
                const payload = { oldvalue: oldValue, newvalue: newValue, celltype: "dropdown", primary_id: data[this.primary_id_name], secondary_id: data[this.secondary_id_name] };
                try {
                    // Optimistic update: Update store first for instant UI change.
                    this.updateCell({
                        primaryId: data[this.primary_id_name],
                        primaryIdColumn: this.primary_id_name,
                        secondaryId: data[this.secondary_id_name],
                        secondaryIdColumn: this.secondary_id_name,
                        field: 'Match',
                        newValue: newValue,
                    });
                    // Send API call in the background.
                    await API.postCellValueChange(payload);
                } catch (error) {
                    console.error("Error posting cell value change:", error);
                }
              }};
            }

            if (cleanedFieldName === "Comments") {
              return { field: "Comment", editable: true, minWidth: 150, resizable: true, cellRenderer: (params) => (params.value ?? params.data.Comments) ?? `<span style="color: #929292;">Add comment</span>`, onCellValueChanged: async (event) => {
                const { newValue, oldValue, data } = event;
                const payload = { oldvalue: oldValue, newvalue: newValue, celltype: "comment", primary_id: data[this.primary_id_name], secondary_id: data[this.secondary_id_name] };
                try {
                    // Optimistic update
                    this.updateCell({
                        primaryId: data[this.primary_id_name],
                        primaryIdColumn: this.primary_id_name,
                        secondaryId: data[this.secondary_id_name],
                        secondaryIdColumn: this.secondary_id_name,
                        field: 'Comments',
                        newValue: newValue,
                    });
                    // API call in background
                    await API.postCellValueChange(payload);
                } catch (error) {
                    console.error("Error posting cell value change:", error);
                }
              }};
            }
            
            if (cleanedFieldName === "Match score") {
              return { field: cleanedFieldName, minWidth: 150, resizable: true, cellClass: "match-score-column", headerClass: "match-score-column" };
            }

            // Main ID columns
            
            if (cleanedFieldName === "primary_id" && this.primary_id_name !== "primary_id") {
              return { field: cleanedFieldName, hide: true };
            }
            if (cleanedFieldName === "secondary_id" && this.secondary_id_name !== "secondary_id") {
              return { field: cleanedFieldName, hide: true };
            }
            if (cleanedFieldName === this.primary_id_name) {
              const headerName = this.primary_id_name !== "primary_id" ? this.primary_id_name.replace("primary_", "") : this.primary_id_name;
              return { field: this.primary_id_name, headerName: headerName, rowGroup: true, hide: false, headerComponentParams: { menuIcon: "dku-icon-star-fill-16" }, pinned: 'left', headerClass: "blue-header" };
            }
            if (cleanedFieldName === this.secondary_id_name) {
              const headerName = this.secondary_id_name !== "secondary_id" ? this.secondary_id_name.replace("secondary_", "") : this.secondary_id_name;
              return { field: this.secondary_id_name, headerName: headerName, pinned: 'left', headerClass: "blue-header" };
            }
            
            // General primary/secondary key columns

            if (isPrimaryKey) {
              return { field: cleanedFieldName, minWidth: 200, resizable: true, headerName: headerName, headerComponentParams: { menuIcon: "dku-icon-star-fill-16" }, cellClass: "matched-cell", headerClass: (index >= 2) && (Math.floor((index - 2) / 2) % 2 === 0) ? 'grey-header' : 'blue-header' };
            }
            
            if (isSecondaryKey) { 
              const secondaryKeyIndex = this.secondary_keys.indexOf(cleanedFieldName);
              const primaryKeyForSecondary = this.primary_keys[secondaryKeyIndex];
              const headerName = cleanedFieldName.includes("secondary_") ? cleanedFieldName.replace("secondary_", '') : cleanedFieldName;
              return { field: cleanedFieldName, minWidth: 200, resizable: true, headerName: headerName, cellClassRules: { 'matched-cell': (params) => params.data[primaryKeyForSecondary] === params.value }, cellClass: "secondary-column", headerClass: (index >= 2) && (Math.floor((index - 2) / 2) % 2 === 0) ? 'grey-header secondary-column' : 'blue-header secondary-column' };
            }
            
            // Default column definition
            return { field: cleanedFieldName, headerName: headerName, minWidth: 200, resizable: true };
          });

          // --- REACTIVITY FIX ---
          // Transform column-oriented data to a *new* row-oriented array
          
          const newRows = []; // 1. Build a new, local array
          const keys = Object.keys(this.fullTable);
          
          if (keys.length > 0) {
            const length = Object.keys(this.fullTable[keys[0]]).length;
            for (let i = 0; i < length; i++) {
              let row = {};
              keys.forEach(key => {
                row[key] = this.fullTable[key][i];
              });
              newRows.push(row); // 2. Push to the local array
            }
          }

          // 3. Assign the new array reference to the prop. This forces reactivity.
          this.rows_grid = newRows; 
          
        } catch (error) {
          console.error("Error processing table data:", error);
        } finally {
          this.loading = false;
        }
    }
  }
};
</script>

<style>
/* Add a top border to the first row within each group for visual separation. */
.first-row-in-group,
.ag-row-group-contracted {
  border-top: black solid 1px !important;
}

.search-box-legend {
  display: flex;
  left: 17px;
  position: absolute;
}

/* Add a right border to all secondary columns. */
.ag-theme-alpine .secondary-column {
  border-right: 1px solid #929292 !important;
}

/* Add a left border to the Match Score column for visual separation. */
.ag-theme-alpine .match-score-column {
  border-left: 1px solid #929292 !important;
}

/* Custom light green background for cells with matching values. */
.ag-theme-alpine .matched-cell {
  background-color: #d6f0d6 !important;
}

/* Custom background colors for headers to differentiate column groups. */
.blue-header {
  background-color: #e6f1fa !important;
}

.grey-header {
  background-color: #eeedee !important;
}
</style>