import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { GraphNode, GraphEdge } from './types/permissions';

interface NodePosition {
  id: string;
  x: number;
  y: number;
}

interface PermissionGraphState {
  // Canvas state
  zoom: number;
  panX: number;
  panY: number;

  // Selection state
  selectedNodeId: string | null;
  selectedEdgeId: string | null;
  hoveredNodeId: string | null;

  // Node positions (persisted per session)
  nodePositions: Record<string, { x: number; y: number }>;

  // UI state
  showMinimap: boolean;
  showLabels: boolean;
  layoutMode: 'force' | 'hierarchical' | 'manual';

  // Filter state
  visibleModules: string[];
  visibleNodeTypes: ('role' | 'permission' | 'team' | 'staff')[];

  // Connection drawing state (for creating edges)
  isDrawingConnection: boolean;
  connectionSourceId: string | null;
  connectionSourceType: 'role' | 'permission' | 'team' | null;

  // Edit mode
  editingNodeId: string | null;
}

const initialState: PermissionGraphState = {
  zoom: 1,
  panX: 0,
  panY: 0,
  selectedNodeId: null,
  selectedEdgeId: null,
  hoveredNodeId: null,
  nodePositions: {},
  showMinimap: true,
  showLabels: true,
  layoutMode: 'force',
  visibleModules: [],
  visibleNodeTypes: ['role', 'permission', 'team', 'staff'],
  isDrawingConnection: false,
  connectionSourceId: null,
  connectionSourceType: null,
  editingNodeId: null,
};

const permissionGraphSlice = createSlice({
  name: 'permissionGraph',
  initialState,
  reducers: {
    // Canvas controls
    setZoom(state, action: PayloadAction<number>) {
      state.zoom = Math.max(0.1, Math.min(2, action.payload));
    },
    zoomIn(state) {
      state.zoom = Math.min(2, state.zoom + 0.1);
    },
    zoomOut(state) {
      state.zoom = Math.max(0.1, state.zoom - 0.1);
    },
    setPan(state, action: PayloadAction<{ x: number; y: number }>) {
      state.panX = action.payload.x;
      state.panY = action.payload.y;
    },
    resetView(state) {
      state.zoom = 1;
      state.panX = 0;
      state.panY = 0;
    },

    // Selection
    selectNode(state, action: PayloadAction<string | null>) {
      state.selectedNodeId = action.payload;
      state.selectedEdgeId = null;
    },
    selectEdge(state, action: PayloadAction<string | null>) {
      state.selectedEdgeId = action.payload;
      state.selectedNodeId = null;
    },
    clearSelection(state) {
      state.selectedNodeId = null;
      state.selectedEdgeId = null;
    },
    setHoveredNode(state, action: PayloadAction<string | null>) {
      state.hoveredNodeId = action.payload;
    },

    // Node positions
    setNodePosition(state, action: PayloadAction<NodePosition>) {
      state.nodePositions[action.payload.id] = {
        x: action.payload.x,
        y: action.payload.y,
      };
    },
    setNodePositions(state, action: PayloadAction<NodePosition[]>) {
      action.payload.forEach(pos => {
        state.nodePositions[pos.id] = { x: pos.x, y: pos.y };
      });
    },
    clearNodePositions(state) {
      state.nodePositions = {};
    },

    // UI toggles
    toggleMinimap(state) {
      state.showMinimap = !state.showMinimap;
    },
    setShowMinimap(state, action: PayloadAction<boolean>) {
      state.showMinimap = action.payload;
    },
    toggleLabels(state) {
      state.showLabels = !state.showLabels;
    },
    setShowLabels(state, action: PayloadAction<boolean>) {
      state.showLabels = action.payload;
    },
    setLayoutMode(state, action: PayloadAction<'force' | 'hierarchical' | 'manual'>) {
      state.layoutMode = action.payload;
    },

    // Filters
    setVisibleModules(state, action: PayloadAction<string[]>) {
      state.visibleModules = action.payload;
    },
    toggleModule(state, action: PayloadAction<string>) {
      const idx = state.visibleModules.indexOf(action.payload);
      if (idx >= 0) {
        state.visibleModules.splice(idx, 1);
      } else {
        state.visibleModules.push(action.payload);
      }
    },
    setVisibleNodeTypes(state, action: PayloadAction<('role' | 'permission' | 'team' | 'staff')[]>) {
      state.visibleNodeTypes = action.payload;
    },
    toggleNodeType(state, action: PayloadAction<'role' | 'permission' | 'team' | 'staff'>) {
      const idx = state.visibleNodeTypes.indexOf(action.payload);
      if (idx >= 0) {
        state.visibleNodeTypes.splice(idx, 1);
      } else {
        state.visibleNodeTypes.push(action.payload);
      }
    },

    // Connection drawing (for creating role-permission links)
    startDrawingConnection(state, action: PayloadAction<{ sourceId: string; sourceType: 'role' | 'permission' | 'team' }>) {
      state.isDrawingConnection = true;
      state.connectionSourceId = action.payload.sourceId;
      state.connectionSourceType = action.payload.sourceType;
    },
    cancelDrawingConnection(state) {
      state.isDrawingConnection = false;
      state.connectionSourceId = null;
      state.connectionSourceType = null;
    },
    finishDrawingConnection(state) {
      state.isDrawingConnection = false;
      state.connectionSourceId = null;
      state.connectionSourceType = null;
    },

    // Edit mode
    setEditingNode(state, action: PayloadAction<string | null>) {
      state.editingNodeId = action.payload;
    },
  },
});

export const {
  setZoom,
  zoomIn,
  zoomOut,
  setPan,
  resetView,
  selectNode,
  selectEdge,
  clearSelection,
  setHoveredNode,
  setNodePosition,
  setNodePositions,
  clearNodePositions,
  toggleMinimap,
  setShowMinimap,
  toggleLabels,
  setShowLabels,
  setLayoutMode,
  setVisibleModules,
  toggleModule,
  setVisibleNodeTypes,
  toggleNodeType,
  startDrawingConnection,
  cancelDrawingConnection,
  finishDrawingConnection,
  setEditingNode,
} = permissionGraphSlice.actions;

export default permissionGraphSlice.reducer;
