/**
 * Chat Store
 * Zustand store for LLM Copilot chat state management
 */

import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import type {
  ChatSession,
  ChatMessage,
  ChatState,
} from '../types/chat.types';
import { chatService } from '../services/chat.service';

// ============================================================================
// Extended State Interface
// ============================================================================

interface ExtendedChatState extends ChatState {
  // Actions
  openChat: () => void;
  closeChat: () => void;
  toggleChat: () => void;

  createNewSession: () => Promise<void>;
  loadSessions: () => Promise<void>;
  loadSession: (sessionId: string) => Promise<void>;
  sendMessage: (message: string) => Promise<void>;
  deleteSession: (sessionId: string) => Promise<void>;
  setCurrentSession: (sessionId: string | null) => void;

  // Utility
  clearError: () => void;
  reset: () => void;
}

// ============================================================================
// Initial State
// ============================================================================

const initialState: ChatState = {
  sessions: [],
  currentSessionId: null,
  messages: [],
  loading: false,
  isOpen: false,
  error: null,
};

// ============================================================================
// Store
// ============================================================================

export const useChatStore = create<ExtendedChatState>()(
  devtools(
    persist(
      (set, get) => ({
        ...initialState,

        // ========================================================================
        // UI Actions
        // ========================================================================

        openChat: () => {
          set({ isOpen: true }, false, 'chat/openChat');

          // Auto-create session if none exists
          const { currentSessionId, sessions } = get();
          if (!currentSessionId && sessions.length === 0) {
            get().createNewSession();
          }
        },

        closeChat: () => {
          set({ isOpen: false }, false, 'chat/closeChat');
        },

        toggleChat: () => {
          const { isOpen } = get();
          if (isOpen) {
            get().closeChat();
          } else {
            get().openChat();
          }
        },

        // ========================================================================
        // Session Management
        // ========================================================================

        createNewSession: async () => {
          try {
            set({ loading: true, error: null }, false, 'chat/createNewSession/start');

            const response = await chatService.createSession();
            const newSession: ChatSession = {
              id: response.sessionId,
              userId: '', // Will be populated by backend
              messages: [],
              createdAt: response.createdAt,
              updatedAt: response.createdAt,
            };

            set(
              (state) => ({
                sessions: [newSession, ...state.sessions],
                currentSessionId: newSession.id,
                messages: [],
                loading: false,
              }),
              false,
              'chat/createNewSession/success'
            );

            // Persist the session ID
            localStorage.setItem('currentChatSessionId', newSession.id);
          } catch (error) {
            console.error('Failed to create session:', error);
            set(
              {
                loading: false,
                error: error instanceof Error ? error.message : 'Failed to create session',
              },
              false,
              'chat/createNewSession/error'
            );
          }
        },

        loadSessions: async () => {
          try {
            set({ loading: true, error: null }, false, 'chat/loadSessions/start');

            const sessions = await chatService.getSessions();

            set(
              {
                sessions,
                loading: false,
              },
              false,
              'chat/loadSessions/success'
            );

            // Restore last session if available
            const savedSessionId = localStorage.getItem('currentChatSessionId');
            if (savedSessionId && sessions.find(s => s.id === savedSessionId)) {
              get().loadSession(savedSessionId);
            }
          } catch (error) {
            console.error('Failed to load sessions:', error);
            set(
              {
                loading: false,
                error: error instanceof Error ? error.message : 'Failed to load sessions',
              },
              false,
              'chat/loadSessions/error'
            );
          }
        },

        loadSession: async (sessionId: string) => {
          try {
            set({ loading: true, error: null }, false, 'chat/loadSession/start');

            const session = await chatService.getSession(sessionId);

            set(
              {
                currentSessionId: session.id,
                messages: session.messages,
                loading: false,
              },
              false,
              'chat/loadSession/success'
            );

            localStorage.setItem('currentChatSessionId', sessionId);
          } catch (error) {
            console.error('Failed to load session:', error);
            set(
              {
                loading: false,
                error: error instanceof Error ? error.message : 'Failed to load session',
              },
              false,
              'chat/loadSession/error'
            );
          }
        },

        sendMessage: async (message: string) => {
          const { currentSessionId } = get();

          if (!currentSessionId) {
            // Create a new session first
            await get().createNewSession();
            // Retry sending the message
            return get().sendMessage(message);
          }

          try {
            set({ loading: true, error: null }, false, 'chat/sendMessage/start');

            // Optimistically add user message
            const userMessage: ChatMessage = {
              id: `temp-${Date.now()}`,
              role: 'user',
              content: message,
              timestamp: new Date().toISOString(),
            };

            set(
              (state) => ({
                messages: [...state.messages, userMessage],
              }),
              false,
              'chat/sendMessage/optimistic'
            );

            // Send message to backend
            const response = await chatService.sendMessage(currentSessionId, message);

            // Update with actual response
            set(
              (state) => ({
                messages: [
                  ...state.messages.filter(m => m.id !== userMessage.id),
                  response.message, // This includes both user message and assistant response from backend
                ],
                loading: false,
              }),
              false,
              'chat/sendMessage/success'
            );
          } catch (error) {
            console.error('Failed to send message:', error);
            set(
              {
                loading: false,
                error: error instanceof Error ? error.message : 'Failed to send message',
              },
              false,
              'chat/sendMessage/error'
            );
          }
        },

        deleteSession: async (sessionId: string) => {
          try {
            set({ loading: true, error: null }, false, 'chat/deleteSession/start');

            await chatService.deleteSession(sessionId);

            set(
              (state) => {
                const newSessions = state.sessions.filter(s => s.id !== sessionId);
                const newCurrentSessionId =
                  state.currentSessionId === sessionId
                    ? (newSessions[0]?.id || null)
                    : state.currentSessionId;

                return {
                  sessions: newSessions,
                  currentSessionId: newCurrentSessionId,
                  messages: newCurrentSessionId === sessionId ? [] : state.messages,
                  loading: false,
                };
              },
              false,
              'chat/deleteSession/success'
            );

            // Update localStorage
            const newSessionId = get().currentSessionId;
            if (newSessionId) {
              localStorage.setItem('currentChatSessionId', newSessionId);
            } else {
              localStorage.removeItem('currentChatSessionId');
            }
          } catch (error) {
            console.error('Failed to delete session:', error);
            set(
              {
                loading: false,
                error: error instanceof Error ? error.message : 'Failed to delete session',
              },
              false,
              'chat/deleteSession/error'
            );
          }
        },

        setCurrentSession: (sessionId: string | null) => {
          set({ currentSessionId: sessionId }, false, 'chat/setCurrentSession');

          if (sessionId) {
            localStorage.setItem('currentChatSessionId', sessionId);
            get().loadSession(sessionId);
          } else {
            localStorage.removeItem('currentChatSessionId');
            set({ messages: [] }, false, 'chat/clearMessages');
          }
        },

        // ========================================================================
        // Utility
        // ========================================================================

        clearError: () => {
          set({ error: null }, false, 'chat/clearError');
        },

        reset: () => {
          set(initialState, false, 'chat/reset');
          localStorage.removeItem('currentChatSessionId');
        },
      }),
      {
        name: 'chat-storage',
        partialize: (state) => ({
          currentSessionId: state.currentSessionId,
          // Don't persist everything, just the essential data
        }),
      }
    ),
    { name: 'ChatStore' }
  )
);

export default useChatStore;
