import { create } from 'zustand'
import { devtools, persist, subscribeWithSelector } from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'
import type { User, Company, Notification, AuthState } from '@/types'

// ============================================================
// Auth Store
// ============================================================

interface AuthStore extends AuthState {
  login: (email: string, password: string, mfaCode?: string) => Promise<void>
  logout: () => Promise<void>
  refreshUser: () => Promise<void>
  setUser: (user: User | null) => void
  setTokens: (accessToken: string, refreshToken: string) => void
  clearAuth: () => void
  setLoading: (loading: boolean) => void
  setError: (error: string | undefined) => void
}

export const useAuthStore = create<AuthStore>()(
  devtools(
    persist(
      immer((set, get) => ({
        user: null,
        access_token: null,
        refresh_token: null,
        isAuthenticated: false,
        isLoading: false,
        error: undefined,

        login: async (email: string, password: string, mfaCode?: string) => {
          set((state) => {
            state.isLoading = true
            state.error = undefined
          })
          try {
            // API call would go here
            // For now, just set a mock user
            set((state) => {
              state.isLoading = false
              state.isAuthenticated = true
            })
          } catch (error) {
            set((state) => {
              state.isLoading = false
              state.error = (error as Error).message
            })
          }
        },

        logout: async () => {
          set((state) => {
            state.isLoading = true
          })
          try {
            // API call to logout would go here
            set((state) => {
              state.user = null
              state.access_token = null
              state.refresh_token = null
              state.isAuthenticated = false
              state.isLoading = false
            })
          } catch (error) {
            set((state) => {
              state.isLoading = false
              state.error = (error as Error).message
            })
          }
        },

        refreshUser: async () => {
          try {
            // API call to refresh user data would go here
          } catch (error) {
            set((state) => {
              state.error = (error as Error).message
            })
          }
        },

        setUser: (user: User | null) => {
          set((state) => {
            state.user = user
            state.isAuthenticated = !!user
          })
        },

        setTokens: (accessToken: string, refreshToken: string) => {
          set((state) => {
            state.access_token = accessToken
            state.refresh_token = refreshToken
          })
        },

        clearAuth: () => {
          set((state) => {
            state.user = null
            state.access_token = null
            state.refresh_token = null
            state.isAuthenticated = false
            state.error = undefined
          })
        },

        setLoading: (loading: boolean) => {
          set((state) => {
            state.isLoading = loading
          })
        },

        setError: (error: string | undefined) => {
          set((state) => {
            state.error = error
          })
        },
      })),
      {
        name: 'samms-auth',
        partialize: (state) => ({
          access_token: state.access_token,
          refresh_token: state.refresh_token,
          user: state.user,
          isAuthenticated: state.isAuthenticated,
        }),
      }
    ),
    { name: 'auth-store' }
  )
)

// ============================================================
// Company Store
// ============================================================

interface CompanyStore {
  currentCompany: Company | null
  companies: Company[]
  isLoading: boolean
  error: string | undefined
  setCurrentCompany: (company: Company | null) => void
  setCompanies: (companies: Company[]) => void
  addCompany: (company: Company) => void
  updateCompany: (id: string, updates: Partial<Company>) => void
  removeCompany: (id: string) => void
  fetchCompanies: () => Promise<void>
  fetchCurrentCompany: (id: string) => Promise<void>
  clearError: () => void
}

export const useCompanyStore = create<CompanyStore>()(
  devtools(
    persist(
      immer((set, get) => ({
        currentCompany: null,
        companies: [],
        isLoading: false,
        error: undefined,

        setCurrentCompany: (company: Company | null) => {
          set((state) => {
            state.currentCompany = company
          })
        },

        setCompanies: (companies: Company[]) => {
          set((state) => {
            state.companies = companies
          })
        },

        addCompany: (company: Company) => {
          set((state) => {
            state.companies.push(company)
          })
        },

        updateCompany: (id: string, updates: Partial<Company>) => {
          set((state) => {
            const index = state.companies.findIndex((c) => c.id === id)
            if (index !== -1) {
              state.companies[index] = { ...state.companies[index], ...updates }
            }
            if (state.currentCompany?.id === id) {
              state.currentCompany = { ...state.currentCompany, ...updates }
            }
          })
        },

        removeCompany: (id: string) => {
          set((state) => {
            state.companies = state.companies.filter((c) => c.id !== id)
            if (state.currentCompany?.id === id) {
              state.currentCompany = null
            }
          })
        },

        fetchCompanies: async () => {
          set((state) => {
            state.isLoading = true
            state.error = undefined
          })
          try {
            // API call would go here
            set((state) => {
              state.isLoading = false
            })
          } catch (error) {
            set((state) => {
              state.isLoading = false
              state.error = (error as Error).message
            })
          }
        },

        fetchCurrentCompany: async (id: string) => {
          set((state) => {
            state.isLoading = true
            state.error = undefined
          })
          try {
            // API call would go here
            set((state) => {
              state.isLoading = false
            })
          } catch (error) {
            set((state) => {
              state.isLoading = false
              state.error = (error as Error).message
            })
          }
        },

        clearError: () => {
          set((state) => {
            state.error = undefined
          })
        },
      })),
      {
        name: 'samms-company',
        partialize: (state) => ({
          currentCompany: state.currentCompany,
        }),
      }
    ),
    { name: 'company-store' }
  )
)

// ============================================================
// UI Store
// ============================================================

interface UIStore {
  sidebarCollapsed: boolean
  sidebarOpen: boolean
  commandPaletteOpen: boolean
  theme: 'light' | 'dark' | 'system'
  language: string
  isLoading: boolean
  loadingMessage: string
  toggleSidebar: () => void
  setSidebarCollapsed: (collapsed: boolean) => void
  setSidebarOpen: (open: boolean) => void
  setCommandPaletteOpen: (open: boolean) => void
  setTheme: (theme: 'light' | 'dark' | 'system') => void
  setLanguage: (language: string) => void
  setLoading: (loading: boolean, message?: string) => void
  modals: Record<string, boolean>
  openModal: (modalId: string) => void
  closeModal: (modalId: string) => void
  toggleModal: (modalId: string) => void
}

export const useUIStore = create<UIStore>()(
  devtools(
    persist(
      immer((set) => ({
        sidebarCollapsed: false,
        sidebarOpen: true,
        commandPaletteOpen: false,
        theme: 'system',
        language: 'en',
        isLoading: false,
        loadingMessage: '',
        modals: {},

        toggleSidebar: () => {
          set((state) => {
            state.sidebarCollapsed = !state.sidebarCollapsed
          })
        },

        setSidebarCollapsed: (collapsed: boolean) => {
          set((state) => {
            state.sidebarCollapsed = collapsed
          })
        },

        setSidebarOpen: (open: boolean) => {
          set((state) => {
            state.sidebarOpen = open
          })
        },

        setCommandPaletteOpen: (open: boolean) => {
          set((state) => {
            state.commandPaletteOpen = open
          })
        },

        setTheme: (theme: 'light' | 'dark' | 'system') => {
          set((state) => {
            state.theme = theme
          })
        },

        setLanguage: (language: string) => {
          set((state) => {
            state.language = language
          })
        },

        setLoading: (loading: boolean, message: string = '') => {
          set((state) => {
            state.isLoading = loading
            state.loadingMessage = message
          })
        },

        openModal: (modalId: string) => {
          set((state) => {
            state.modals[modalId] = true
          })
        },

        closeModal: (modalId: string) => {
          set((state) => {
            state.modals[modalId] = false
          })
        },

        toggleModal: (modalId: string) => {
          set((state) => {
            state.modals[modalId] = !state.modals[modalId]
          })
        },
      })),
      {
        name: 'samms-ui',
        partialize: (state) => ({
          sidebarCollapsed: state.sidebarCollapsed,
          theme: state.theme,
          language: state.language,
        }),
      }
    ),
    { name: 'ui-store' }
  )
)

// ============================================================
// Notification Store
// ============================================================

interface NotificationStore {
  notifications: Notification[]
  unreadCount: number
  isLoading: boolean
  addNotification: (notification: Notification) => void
  removeNotification: (id: string) => void
  markAsRead: (id: string) => void
  markAllAsRead: () => void
  clearNotifications: () => void
  fetchNotifications: () => Promise<void>
}

export const useNotificationStore = create<NotificationStore>()(
  devtools(
    immer((set, get) => ({
      notifications: [],
      unreadCount: 0,
      isLoading: false,

      addNotification: (notification: Notification) => {
        set((state) => {
          state.notifications.unshift(notification)
          if (!notification.read) {
            state.unreadCount += 1
          }
        })
      },

      removeNotification: (id: string) => {
        set((state) => {
          const notification = state.notifications.find((n) => n.id === id)
          if (notification && !notification.read) {
            state.unreadCount = Math.max(0, state.unreadCount - 1)
          }
          state.notifications = state.notifications.filter((n) => n.id !== id)
        })
      },

      markAsRead: (id: string) => {
        set((state) => {
          const notification = state.notifications.find((n) => n.id === id)
          if (notification && !notification.read) {
            notification.read = true
            notification.read_at = new Date().toISOString()
            state.unreadCount = Math.max(0, state.unreadCount - 1)
          }
        })
      },

      markAllAsRead: () => {
        set((state) => {
          state.notifications.forEach((n) => {
            if (!n.read) {
              n.read = true
              n.read_at = new Date().toISOString()
            }
          })
          state.unreadCount = 0
        })
      },

      clearNotifications: () => {
        set((state) => {
          state.notifications = []
          state.unreadCount = 0
        })
      },

      fetchNotifications: async () => {
        set((state) => {
          state.isLoading = true
        })
        try {
          // API call would go here
          set((state) => {
            state.isLoading = false
          })
        } catch (error) {
          set((state) => {
            state.isLoading = false
          })
        }
      },
    })),
    { name: 'notification-store' }
  )
)

// ============================================================
// Command Palette Store
// ============================================================

interface CommandAction {
  id: string
  title: string
  description?: string
  icon?: string
  shortcut?: string
  category: string
  action: () => void
}

interface CommandPaletteStore {
  commands: CommandAction[]
  recentCommands: string[]
  searchQuery: string
  selectedIndex: number
  registerCommand: (command: CommandAction) => void
  unregisterCommand: (id: string) => void
  executeCommand: (id: string) => void
  setSearchQuery: (query: string) => void
  setSelectedIndex: (index: number) => void
  addRecentCommand: (id: string) => void
  clearRecentCommands: () => void
}

export const useCommandPaletteStore = create<CommandPaletteStore>()(
  devtools(
    persist(
      immer((set, get) => ({
        commands: [],
        recentCommands: [],
        searchQuery: '',
        selectedIndex: 0,

        registerCommand: (command: CommandAction) => {
          set((state) => {
            const exists = state.commands.find((c) => c.id === command.id)
            if (!exists) {
              state.commands.push(command)
            }
          })
        },

        unregisterCommand: (id: string) => {
          set((state) => {
            state.commands = state.commands.filter((c) => c.id !== id)
          })
        },

        executeCommand: (id: string) => {
          const command = get().commands.find((c) => c.id === id)
          if (command) {
            command.action()
            set((state) => {
              state.recentCommands = [
                id,
                ...state.recentCommands.filter((c) => c !== id),
              ].slice(0, 10)
            })
          }
        },

        setSearchQuery: (query: string) => {
          set((state) => {
            state.searchQuery = query
            state.selectedIndex = 0
          })
        },

        setSelectedIndex: (index: number) => {
          set((state) => {
            state.selectedIndex = index
          })
        },

        addRecentCommand: (id: string) => {
          set((state) => {
            state.recentCommands = [
              id,
              ...state.recentCommands.filter((c) => c !== id),
            ].slice(0, 10)
          })
        },

        clearRecentCommands: () => {
          set((state) => {
            state.recentCommands = []
          })
        },
      })),
      {
        name: 'samms-commands',
        partialize: (state) => ({
          recentCommands: state.recentCommands,
        }),
      }
    ),
    { name: 'command-palette-store' }
  )
)

// ============================================================
// Data Table Store
// ============================================================

interface TableState {
  sortBy: string
  sortOrder: 'asc' | 'desc'
  filters: Record<string, unknown>
  page: number
  pageSize: number
  selectedRows: string[]
  searchQuery: string
}

interface DataTableStore {
  tables: Record<string, TableState>
  initTable: (tableId: string, defaultState?: Partial<TableState>) => void
  setSort: (tableId: string, sortBy: string, sortOrder: 'asc' | 'desc') => void
  setFilter: (tableId: string, key: string, value: unknown) => void
  clearFilters: (tableId: string) => void
  setPage: (tableId: string, page: number) => void
  setPageSize: (tableId: string, pageSize: number) => void
  setSelectedRows: (tableId: string, rows: string[]) => void
  toggleRowSelection: (tableId: string, rowId: string) => void
  selectAllRows: (tableId: string, rowIds: string[]) => void
  clearSelection: (tableId: string) => void
  setSearchQuery: (tableId: string, query: string) => void
  resetTable: (tableId: string) => void
}

const defaultTableState: TableState = {
  sortBy: 'created_at',
  sortOrder: 'desc',
  filters: {},
  page: 1,
  pageSize: 25,
  selectedRows: [],
  searchQuery: '',
}

export const useDataTableStore = create<DataTableStore>()(
  devtools(
    immer((set, get) => ({
      tables: {},

      initTable: (tableId: string, defaultState?: Partial<TableState>) => {
        set((state) => {
          if (!state.tables[tableId]) {
            state.tables[tableId] = {
              ...defaultTableState,
              ...defaultState,
            }
          }
        })
      },

      setSort: (tableId: string, sortBy: string, sortOrder: 'asc' | 'desc') => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].sortBy = sortBy
            state.tables[tableId].sortOrder = sortOrder
            state.tables[tableId].page = 1
          }
        })
      },

      setFilter: (tableId: string, key: string, value: unknown) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].filters[key] = value
            state.tables[tableId].page = 1
          }
        })
      },

      clearFilters: (tableId: string) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].filters = {}
            state.tables[tableId].page = 1
          }
        })
      },

      setPage: (tableId: string, page: number) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].page = page
          }
        })
      },

      setPageSize: (tableId: string, pageSize: number) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].pageSize = pageSize
            state.tables[tableId].page = 1
          }
        })
      },

      setSelectedRows: (tableId: string, rows: string[]) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].selectedRows = rows
          }
        })
      },

      toggleRowSelection: (tableId: string, rowId: string) => {
        set((state) => {
          if (state.tables[tableId]) {
            const index = state.tables[tableId].selectedRows.indexOf(rowId)
            if (index === -1) {
              state.tables[tableId].selectedRows.push(rowId)
            } else {
              state.tables[tableId].selectedRows.splice(index, 1)
            }
          }
        })
      },

      selectAllRows: (tableId: string, rowIds: string[]) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].selectedRows = rowIds
          }
        })
      },

      clearSelection: (tableId: string) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].selectedRows = []
          }
        })
      },

      setSearchQuery: (tableId: string, query: string) => {
        set((state) => {
          if (state.tables[tableId]) {
            state.tables[tableId].searchQuery = query
            state.tables[tableId].page = 1
          }
        })
      },

      resetTable: (tableId: string) => {
        set((state) => {
          state.tables[tableId] = { ...defaultTableState }
        })
      },
    })),
    { name: 'data-table-store' }
  )
)

// ============================================================
// Workflow Editor Store
// ============================================================

interface WorkflowNode {
  id: string
  type: string
  position: { x: number; y: number }
  data: Record<string, unknown>
}

interface WorkflowEdge {
  id: string
  source: string
  target: string
  sourceHandle?: string
  targetHandle?: string
  label?: string
}

interface WorkflowEditorStore {
  nodes: WorkflowNode[]
  edges: WorkflowEdge[]
  selectedNodeId: string | null
  selectedEdgeId: string | null
  isDirty: boolean
  zoom: number
  addNode: (node: WorkflowNode) => void
  updateNode: (id: string, updates: Partial<WorkflowNode>) => void
  removeNode: (id: string) => void
  addEdge: (edge: WorkflowEdge) => void
  updateEdge: (id: string, updates: Partial<WorkflowEdge>) => void
  removeEdge: (id: string) => void
  setSelectedNode: (id: string | null) => void
  setSelectedEdge: (id: string | null) => void
  setNodes: (nodes: WorkflowNode[]) => void
  setEdges: (edges: WorkflowEdge[]) => void
  setZoom: (zoom: number) => void
  setDirty: (dirty: boolean) => void
  clearEditor: () => void
}

export const useWorkflowEditorStore = create<WorkflowEditorStore>()(
  devtools(
    immer((set) => ({
      nodes: [],
      edges: [],
      selectedNodeId: null,
      selectedEdgeId: null,
      isDirty: false,
      zoom: 1,

      addNode: (node: WorkflowNode) => {
        set((state) => {
          state.nodes.push(node)
          state.isDirty = true
        })
      },

      updateNode: (id: string, updates: Partial<WorkflowNode>) => {
        set((state) => {
          const index = state.nodes.findIndex((n) => n.id === id)
          if (index !== -1) {
            state.nodes[index] = { ...state.nodes[index], ...updates }
            state.isDirty = true
          }
        })
      },

      removeNode: (id: string) => {
        set((state) => {
          state.nodes = state.nodes.filter((n) => n.id !== id)
          state.edges = state.edges.filter(
            (e) => e.source !== id && e.target !== id
          )
          state.isDirty = true
        })
      },

      addEdge: (edge: WorkflowEdge) => {
        set((state) => {
          state.edges.push(edge)
          state.isDirty = true
        })
      },

      updateEdge: (id: string, updates: Partial<WorkflowEdge>) => {
        set((state) => {
          const index = state.edges.findIndex((e) => e.id === id)
          if (index !== -1) {
            state.edges[index] = { ...state.edges[index], ...updates }
            state.isDirty = true
          }
        })
      },

      removeEdge: (id: string) => {
        set((state) => {
          state.edges = state.edges.filter((e) => e.id !== id)
          state.isDirty = true
        })
      },

      setSelectedNode: (id: string | null) => {
        set((state) => {
          state.selectedNodeId = id
        })
      },

      setSelectedEdge: (id: string | null) => {
        set((state) => {
          state.selectedEdgeId = id
        })
      },

      setNodes: (nodes: WorkflowNode[]) => {
        set((state) => {
          state.nodes = nodes
          state.isDirty = true
        })
      },

      setEdges: (edges: WorkflowEdge[]) => {
        set((state) => {
          state.edges = edges
          state.isDirty = true
        })
      },

      setZoom: (zoom: number) => {
        set((state) => {
          state.zoom = zoom
        })
      },

      setDirty: (dirty: boolean) => {
        set((state) => {
          state.isDirty = dirty
        })
      },

      clearEditor: () => {
        set((state) => {
          state.nodes = []
          state.edges = []
          state.selectedNodeId = null
          state.selectedEdgeId = null
          state.isDirty = false
          state.zoom = 1
        })
      },
    })),
    { name: 'workflow-editor-store' }
  )
)

// ============================================================
// Dashboard Builder Store
// ============================================================

interface DashboardWidget {
  id: string
  type: string
  title: string
  config: Record<string, unknown>
  position: { x: number; y: number; w: number; h: number }
}

interface DashboardBuilderStore {
  widgets: DashboardWidget[]
  selectedWidgetId: string | null
  isDirty: boolean
  gridColumns: number
  addWidget: (widget: DashboardWidget) => void
  updateWidget: (id: string, updates: Partial<DashboardWidget>) => void
  removeWidget: (id: string) => void
  moveWidget: (id: string, position: DashboardWidget['position']) => void
  setSelectedWidget: (id: string | null) => void
  setWidgets: (widgets: DashboardWidget[]) => void
  setGridColumns: (columns: number) => void
  setDirty: (dirty: boolean) => void
  clearDashboard: () => void
}

export const useDashboardBuilderStore = create<DashboardBuilderStore>()(
  devtools(
    immer((set) => ({
      widgets: [],
      selectedWidgetId: null,
      isDirty: false,
      gridColumns: 12,

      addWidget: (widget: DashboardWidget) => {
        set((state) => {
          state.widgets.push(widget)
          state.isDirty = true
        })
      },

      updateWidget: (id: string, updates: Partial<DashboardWidget>) => {
        set((state) => {
          const index = state.widgets.findIndex((w) => w.id === id)
          if (index !== -1) {
            state.widgets[index] = { ...state.widgets[index], ...updates }
            state.isDirty = true
          }
        })
      },

      removeWidget: (id: string) => {
        set((state) => {
          state.widgets = state.widgets.filter((w) => w.id !== id)
          state.isDirty = true
        })
      },

      moveWidget: (id: string, position: DashboardWidget['position']) => {
        set((state) => {
          const index = state.widgets.findIndex((w) => w.id === id)
          if (index !== -1) {
            state.widgets[index].position = position
            state.isDirty = true
          }
        })
      },

      setSelectedWidget: (id: string | null) => {
        set((state) => {
          state.selectedWidgetId = id
        })
      },

      setWidgets: (widgets: DashboardWidget[]) => {
        set((state) => {
          state.widgets = widgets
          state.isDirty = true
        })
      },

      setGridColumns: (columns: number) => {
        set((state) => {
          state.gridColumns = columns
        })
      },

      setDirty: (dirty: boolean) => {
        set((state) => {
          state.isDirty = dirty
        })
      },

      clearDashboard: () => {
        set((state) => {
          state.widgets = []
          state.selectedWidgetId = null
          state.isDirty = false
        })
      },
    })),
    { name: 'dashboard-builder-store' }
  )
)