// resources/assets/ts/ContactsPage/components/CMSTaskSelector/CMSTaskSelectorSlice.ts
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import axios from 'axios';

export interface CMSTreeNode {
  id: number;
  uid: string;
  nodeID: string;
  name: string;
  type: string;
  isExpandable: boolean;
  isCreateable: boolean;
  hasChildren?: boolean;
  children?: CMSTreeNode[];
  agb_activefunc?: number;
}

type Status = 'init' | 'loading' | 'ready' | 'error';

interface CMSTaskSelectorState {
  status: Status;
  treeData: CMSTreeNode[];
  expanded: string[];
  searchTerm: string;
  filteredNodeIds: string[];
  error: string | null;
  entities: Record<string, CMSTreeNode>;
}

const initialState: CMSTaskSelectorState = {
  status: 'init',
  treeData: [],
  expanded: [],
  searchTerm: '',
  filteredNodeIds: [],
  error: null,
  entities: {},
};

function toNode(data: any): CMSTreeNode {
  return {
    id: data.id,
    uid: data.uid || `${data.type}::${data.id}`,
    nodeID: `${data.type}::${data.id}`,
    name: data.name,
    type: data.type,
    isExpandable: data.expandable === 1,
    isCreateable: data.createable > 0,
    hasChildren: data.has_children || false,
    agb_activefunc: data.agb_activefunc,
  };
}

export const fetchCMSTree = createAsyncThunk(
  'CMSTaskSelector/fetchTree',
  async () => {
    const response = await axios.get('/contacts/cms-tree');
    return response.data.map(toNode);
  }
);

export const fetchCMSNode = createAsyncThunk(
  'CMSTaskSelector/fetchNode',
  async (node: CMSTreeNode) => {
    let response;

    if (node.type === 'department' || node.type === 'BER') {
      response = await axios.get(`/contacts/cms-tree/${node.id}`);
    } else if (node.type === 'GRP') {
      response = await axios.get(`/contacts/cms-tree/groups/${node.id}`);
    } else {
      return { nodeID: node.nodeID, children: [] };
    }

    return {
      nodeID: node.nodeID,
      children: response.data.map(toNode)
    };
  }
);

// ✅ NEW: Fast auto-expand using single backend request
export const autoExpandTreeFast = createAsyncThunk(
  'CMSTaskSelector/autoExpandTreeFast',
  async () => {
    console.log('🚀 Starting FAST auto-expand...');
    
    const response = await axios.get('/contacts/cms-tree-full');
    const { tree, totalNodes } = response.data;
    
    console.log('✅ Received full tree:', totalNodes, 'nodes');

    // Flatten tree to extract all nodes and expanded IDs
    const allNodes: CMSTreeNode[] = [];
    const expandedNodeIDs: string[] = [];

    const flattenTree = (nodes: CMSTreeNode[]) => {
      nodes.forEach(node => {
        allNodes.push(node);
        
        // Only expand folders (not tasks)
        if (node.isExpandable) {
          expandedNodeIDs.push(node.nodeID);
        }
        
        if (node.children && node.children.length > 0) {
          flattenTree(node.children);
        }
      });
    };

    flattenTree(tree);

    console.log('📊 Flattened:', allNodes.length, 'nodes');
    console.log('📂 Expanded:', expandedNodeIDs.length, 'folders');

    return {
      treeData: tree,
      allNodes,
      expandedNodeIDs,
    };
  }
);

function getAllDescendants(nodeID: string, entities: Record<string, CMSTreeNode>): string[] {
  const descendants: string[] = [];
  const node = entities[nodeID];

  if (!node || !node.children) {
    return descendants;
  }

  const collectDescendants = (children: CMSTreeNode[]) => {
    children.forEach(child => {
      descendants.push(child.nodeID);
      if (child.children && child.children.length > 0) {
        collectDescendants(child.children);
      }
    });
  };

  collectDescendants(node.children);
  return descendants;
}

const CMSTaskSelectorSlice = createSlice({
  name: 'CMSTaskSelector',
  initialState,
  reducers: {
    toggleExpanded(state, action: PayloadAction<string>) {
      const nodeID = action.payload;
      const index = state.expanded.indexOf(nodeID);

      if (index > -1) {
        state.expanded.splice(index, 1);
        const descendants = getAllDescendants(nodeID, state.entities);
        state.expanded = state.expanded.filter(id => !descendants.includes(id));
        console.log('📕 Collapsed:', nodeID, 'and', descendants.length, 'descendants');
      } else {
        state.expanded.push(nodeID);
        console.log('📖 Expanded:', nodeID);
      }
    },

    setSearchTerm: (state, action: PayloadAction<string>) => {
      state.searchTerm = action.payload;

      if (!action.payload.trim()) {
        state.filteredNodeIds = [];
        return;
      }

      const searchLower = action.payload.toLowerCase();
      const matchingIds: string[] = [];

      Object.values(state.entities).forEach((node) => {
        if (node && node.name.toLowerCase().includes(searchLower)) {
          matchingIds.push(node.nodeID);
        }
      });

      state.filteredNodeIds = matchingIds;
    },

    resetSelector: () => initialState,
  },

  extraReducers: (builder) => {
    builder
      // fetchCMSTree
      .addCase(fetchCMSTree.pending, (state) => {
        state.status = 'loading';
        state.error = null;
      })
      .addCase(fetchCMSTree.fulfilled, (state, action) => {
        state.status = 'ready';
        state.treeData = action.payload;
        state.entities = {};
        action.payload.forEach((node: CMSTreeNode) => {
          state.entities[node.nodeID] = node;
        });
      })
      .addCase(fetchCMSTree.rejected, (state, action) => {
        state.status = 'error';
        state.error = action.error.message || 'Failed to fetch tree';
      })

      // autoExpandTree
      // .addCase(autoExpandTree.pending, (state) => {
      //   state.status = 'loading';
      //   state.error = null;
      // })
      // .addCase(autoExpandTree.fulfilled, (state, action) => {
      //   const { treeData, allNodes, expandedNodeIDs } = action.payload;

      //   state.treeData = treeData;
      //   state.expanded = expandedNodeIDs;
      //   state.entities = {};
      //   allNodes.forEach(node => {
      //     state.entities[node.nodeID] = node;
      //   });

      //   state.status = 'ready';
      //   console.log('✅ Auto-expand complete');
      //   console.log('Total nodes loaded:', allNodes.length);
      //   console.log('Entity keys:', Object.keys(state.entities).length);
      // })

      .addCase(autoExpandTreeFast.pending, (state) => {
  state.status = 'loading';
  state.error = null;
})
.addCase(autoExpandTreeFast.fulfilled, (state, action) => {
  const { treeData, allNodes, expandedNodeIDs } = action.payload;

  state.treeData = treeData;
  state.expanded = expandedNodeIDs;
  state.entities = {};
  allNodes.forEach(node => {
    state.entities[node.nodeID] = node;
  });

  state.status = 'ready';
  console.log('✅ Fast auto-expand complete');
  console.log('Total nodes loaded:', allNodes.length);
  console.log('Entity keys:', Object.keys(state.entities).length);
})
.addCase(autoExpandTreeFast.rejected, (state, action) => {
  state.status = 'error';
  state.error = action.error.message || 'Failed to load CMS tree';
})
    

      // fetchCMSNode
      .addCase(fetchCMSNode.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchCMSNode.fulfilled, (state, action) => {
        const { nodeID, children } = action.payload;

        console.log('✅ Fetched children for:', nodeID, 'count:', children.length);

        if (state.entities[nodeID]) {
          state.entities[nodeID].children = children;
        }

        children.forEach((child) => {
          const existing = state.entities[child.nodeID];

          if (existing && existing.children) {
            state.entities[child.nodeID] = {
              ...child,
              children: existing.children,
            };
          } else {
            state.entities[child.nodeID] = child;
          }
        });

        if (!state.expanded.includes(nodeID)) {
          state.expanded.push(nodeID);
        }

        state.status = 'ready';
      })
      .addCase(fetchCMSNode.rejected, (state, action) => {
        state.status = 'error';
        state.error = action.error.message || 'Failed to fetch node children';
      });
  },
});

export const { toggleExpanded, setSearchTerm, resetSelector } = CMSTaskSelectorSlice.actions;
export default CMSTaskSelectorSlice.reducer;

export const selectCMSTree = (state: { CMSTaskSelector: CMSTaskSelectorState }) =>
  state.CMSTaskSelector.treeData;

export const selectCMSNodeById =
  (id: string) =>
  (state: { CMSTaskSelector: CMSTaskSelectorState }) =>
    state.CMSTaskSelector.entities[id];

  