import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import { ViewMode, TopologyNode, TopologyEdge, NetworkInfo, Host, NodeType } from '../types';

export type Orientation = 'LR' | 'TB';
export type StatusFilter = 'all' | 'running' | 'stopped';

// All node types for default filter
const ALL_NODE_TYPES: NodeType[] = [
  'gateway', 'vlan', 'wifi', 'host_physical', 'host_vm', 'host_container',
  'service', 'volume', 'mount', 'path'
];

interface TopologyState {
  nodes: TopologyNode[];
  edges: TopologyEdge[];
  selectedNodeId: string | null;
  viewMode: ViewMode;
  orientation: Orientation;
  searchQuery: string;
  typeFilters: NodeType[];
  statusFilter: StatusFilter;
  leftPanelOpen: boolean;
  rightPanelOpen: boolean;
  lastUpdated: Date | null;
  isLoading: boolean;
  
  networkInfo: NetworkInfo | null;
  hosts: Host[];
  
  setNodes: (nodes: TopologyNode[]) => void;
  setEdges: (edges: TopologyEdge[]) => void;
  setSelectedNode: (nodeId: string | null) => void;
  setViewMode: (mode: ViewMode) => void;
  setOrientation: (orientation: Orientation) => void;
  setSearchQuery: (query: string) => void;
  toggleTypeFilter: (type: NodeType) => void;
  setStatusFilter: (filter: StatusFilter) => void;
  toggleLeftPanel: () => void;
  toggleRightPanel: () => void;
  setLastUpdated: (date: Date) => void;
  setIsLoading: (loading: boolean) => void;
  setNetworkInfo: (info: NetworkInfo) => void;
  setHosts: (hosts: Host[]) => void;
  
  getSelectedNode: () => TopologyNode | null;
  getChildNodes: () => TopologyNode[];
  getFilteredNodes: () => TopologyNode[];
}

export const useTopologyStore = create<TopologyState>()(
  persist(
    (set, get) => ({
  nodes: [],
  edges: [],
  selectedNodeId: null,
  viewMode: 'full',
  orientation: 'LR',
  searchQuery: '',
  typeFilters: ALL_NODE_TYPES,
  statusFilter: 'all',
  leftPanelOpen: true,
  rightPanelOpen: true,
  lastUpdated: null,
  isLoading: false,
  networkInfo: null,
  hosts: [],
  
  setNodes: (nodes) => set({ nodes }),
  setEdges: (edges) => set({ edges }),
  setSelectedNode: (nodeId) => set({ selectedNodeId: nodeId }),
  setViewMode: (mode) => set({ viewMode: mode }),
  setOrientation: (orientation) => set({ orientation }),
  setSearchQuery: (query) => set({ searchQuery: query }),
  toggleTypeFilter: (type) => set((state) => {
    const exists = state.typeFilters.includes(type);
    return { 
      typeFilters: exists 
        ? state.typeFilters.filter(t => t !== type)
        : [...state.typeFilters, type]
    };
  }),
  setStatusFilter: (filter) => set({ statusFilter: filter }),
  toggleLeftPanel: () => set((state) => ({ leftPanelOpen: !state.leftPanelOpen })),
  toggleRightPanel: () => set((state) => ({ rightPanelOpen: !state.rightPanelOpen })),
  setLastUpdated: (date) => set({ lastUpdated: date }),
  setIsLoading: (loading) => set({ isLoading: loading }),
  setNetworkInfo: (info) => set({ networkInfo: info }),
  setHosts: (hosts) => set({ hosts }),
  
  getSelectedNode: () => {
    const { nodes, selectedNodeId } = get();
    return nodes.find(n => n.id === selectedNodeId) || null;
  },
  
  getChildNodes: () => {
    const { nodes, selectedNodeId } = get();
    if (!selectedNodeId) return [];
    const selectedNode = nodes.find(n => n.id === selectedNodeId);
    if (!selectedNode) return [];
    return nodes.filter(n => n.data.parentId === selectedNodeId);
  },
  
  getFilteredNodes: () => {
    const { nodes, viewMode, searchQuery, typeFilters, statusFilter } = get();
    
    let filtered = nodes;
    
    if (searchQuery) {
      const query = searchQuery.toLowerCase();
      filtered = filtered.filter(n => 
        n.name.toLowerCase().includes(query) ||
        n.data.ip?.toLowerCase().includes(query)
      );
    }
    
    if (statusFilter !== 'all') {
      filtered = filtered.filter(n => n.data.status === statusFilter);
    }
    
    if (typeFilters.length > 0 && typeFilters.length < ALL_NODE_TYPES.length) {
      filtered = filtered.filter(n => typeFilters.includes(n.type));
    }
    
    let allowedTypes: NodeType[] = [];
    if (viewMode === 'network') {
      allowedTypes = ['gateway', 'vlan', 'wifi', 'host_physical', 'host_vm', 'host_container'];
    } else if (viewMode === 'host') {
      allowedTypes = ['gateway', 'vlan', 'wifi', 'host_physical', 'host_vm', 'host_container'];
    } else if (viewMode === 'service') {
      allowedTypes = ['host_physical', 'host_vm', 'host_container', 'service', 'volume'];
    } else if (viewMode === 'filesystem') {
      allowedTypes = ['volume', 'mount', 'path'];
    }
    
    if (allowedTypes.length > 0) {
      const nodeMap = new Map(nodes.map(n => [n.id, n]));
      const includeSet = new Set<string>();
      
      nodes.forEach(node => {
        if (allowedTypes.includes(node.type)) {
          includeSet.add(node.id);
          
          let current: TopologyNode | undefined = node;
          while (current?.data?.parentId) {
            const parentId = current.data.parentId;
            includeSet.add(parentId);
            current = nodeMap.get(parentId);
            if (!current) break;
          }
        }
      });
      
      filtered = filtered.filter(n => includeSet.has(n.id));
    }
    
    return filtered;
  }
}),
{
  name: 'homelab-topology-settings',
  version: 1,
  storage: createJSONStorage(() => localStorage),
  partialize: (state: TopologyState) => ({
    viewMode: state.viewMode,
    orientation: state.orientation,
    searchQuery: state.searchQuery,
    typeFilters: state.typeFilters,
    statusFilter: state.statusFilter,
    leftPanelOpen: state.leftPanelOpen,
    rightPanelOpen: state.rightPanelOpen
  })
}));
