import { AxiosError } from 'axios';
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import {
  ClientDocumentData,
  ClientDocumentsResponse,
  CreateClientDocumentRequest,
  UpdateClientDocumentRequest,
} from '@/utils/types/attachments.types';

export interface ClientDocumentsState {
  loading: boolean;
  error: string | null;
  data: ClientDocumentsResponse | null;
  createLoading: boolean;
  createError: string | null;
  createResponse: ClientDocumentData | null;
  updateLoading: boolean;
  updateError: string | null;
  updateResponse: ClientDocumentData | null;
  deleteLoading: boolean;
  deleteError: string | null;
  deleteSuccess: boolean;

  // Actions
  getClientDocuments: (
    clientId: number,
    apiGet: (url: string) => Promise<ClientDocumentsResponse>
  ) => Promise<void>;
  createClientDocument: (
    data: CreateClientDocumentRequest,
    apiPost: (url: string, data: CreateClientDocumentRequest) => Promise<{ data: ClientDocumentData }>
  ) => Promise<void>;
  updateClientDocument: (
    id: number,
    data: UpdateClientDocumentRequest,
    apiPut: (url: string, data: UpdateClientDocumentRequest) => Promise<{ data: ClientDocumentData }>
  ) => Promise<void>;
  deleteClientDocument: (
    clientId: number,
    documentId: number,
    apiDelete: (url: string) => Promise<void>
  ) => Promise<void>;
  clearError: () => void;
  clearCreateError: () => void;
  clearUpdateError: () => void;
  clearDeleteError: () => void;
  reset: () => void;
}

export interface ClientDocumentsActions {
  getClientDocuments: (clientId: number) => Promise<void>;
  createClientDocument: (data: CreateClientDocumentRequest) => Promise<void>;
  updateClientDocument: (id: number, data: UpdateClientDocumentRequest) => Promise<void>;
  deleteClientDocument: (clientId: number, documentId: number) => Promise<void>;
  clearError: () => void;
  clearCreateError: () => void;
  clearUpdateError: () => void;
  clearDeleteError: () => void;
  reset: () => void;
}

export type ClientDocumentsStore = ClientDocumentsState & ClientDocumentsActions;

const initialState = {
  data: null,
  loading: false,
  error: null,
  createLoading: false,
  createError: null,
  createResponse: null,
  updateLoading: false,
  updateError: null,
  updateResponse: null,
  deleteLoading: false,
  deleteError: null,
  deleteSuccess: false,
};

export const useClientDocumentsStore = create<ClientDocumentsStore>()(
  devtools(
    set => ({
      ...initialState,

      getClientDocuments: async (
        clientId: number,
        apiGet: (url: string) => Promise<ClientDocumentsResponse>
      ) => {
        set({ loading: true, error: null }, false, 'getClientDocuments/pending');

        try {
          const url = `/customer/clients/${clientId}/client-documents`;
          const data = await apiGet(url);
          set({ data, loading: false }, false, 'getClientDocuments/fulfilled');
        } catch (err) {
          const error = err as AxiosError<{ message?: string }>;
          const message = error.message || 'Unknown error occurred';
          set(
            { error: message, loading: false },
            false,
            'getClientDocuments/rejected'
          );
        }
      },

      createClientDocument: async (
        data: CreateClientDocumentRequest,
        apiPost: (url: string, data: CreateClientDocumentRequest) => Promise<{ data: ClientDocumentData }>
      ) => {
        set(
          { createLoading: true, createError: null },
          false,
          'createClientDocument/pending'
        );

        try {
          const url = '/customer/client-documents';
          const response = await apiPost(url, data);
          set(
            {
              createResponse: response.data,
              createLoading: false,
            },
            false,
            'createClientDocument/fulfilled'
          );
        } catch (err) {
          const error = err as AxiosError<{ message?: string }>;
          const message = error.message || 'Unknown error occurred';
          set(
            { createError: message, createLoading: false },
            false,
            'createClientDocument/rejected'
          );
          // Re-throw the error so it can be caught by the calling code
          throw err;
        }
      },

      updateClientDocument: async (
        id: number,
        data: UpdateClientDocumentRequest,
        apiPut: (url: string, data: UpdateClientDocumentRequest) => Promise<{ data: ClientDocumentData }>
      ) => {
        set(
          { updateLoading: true, updateError: null },
          false,
          'updateClientDocument/pending'
        );

        try {
          const url = `/customer/client-documents/${id}`;
          const response = await apiPut(url, data);
          set(
            {
              updateResponse: response.data,
              updateLoading: false,
            },
            false,
            'updateClientDocument/fulfilled'
          );
        } catch (err) {
          const error = err as AxiosError<{ message?: string }>;
          const message = error.message || 'Unknown error occurred';
          set(
            { updateError: message, updateLoading: false },
            false,
            'updateClientDocument/rejected'
          );
          // Re-throw the error so it can be caught by the calling code
          throw err;
        }
      },

      deleteClientDocument: async (
        clientId: number,
        documentId: number,
        apiDelete: (url: string) => Promise<void>
      ) => {
        set(
          { deleteLoading: true, deleteError: null, deleteSuccess: false },
          false,
          'deleteClientDocument/pending'
        );

        try {
          const url = `/customer/clients/${clientId}/client-documents/${documentId}`;
          await apiDelete(url);
          set(
            { deleteLoading: false, deleteSuccess: true },
            false,
            'deleteClientDocument/fulfilled'
          );
        } catch (err) {
          const error = err as AxiosError<{ message?: string }>;
          const message = error.message || 'Unknown error occurred';
          set(
            { deleteError: message, deleteLoading: false },
            false,
            'deleteClientDocument/rejected'
          );
        }
      },

      clearError: () => set({ error: null }, false, 'clearError'),
      clearCreateError: () => set({ createError: null }, false, 'clearCreateError'),
      clearUpdateError: () => set({ updateError: null }, false, 'clearUpdateError'),
      clearDeleteError: () => set({ deleteError: null, deleteSuccess: false }, false, 'clearDeleteError'),
      reset: () => set(initialState, false, 'reset'),
    }),
    {
      name: 'client-documents-store',
    }
  )
);

// Selector functions for optimized subscriptions
export const clientDocumentsSelector = {
  // Data selectors
  getData: () => useClientDocumentsStore.getState().data,
  getCreateResponse: () => useClientDocumentsStore.getState().createResponse,
  getUpdateResponse: () => useClientDocumentsStore.getState().updateResponse,

  // Loading selectors
  getLoading: () => useClientDocumentsStore.getState().loading,
  getCreateLoading: () => useClientDocumentsStore.getState().createLoading,
  getUpdateLoading: () => useClientDocumentsStore.getState().updateLoading,
  getDeleteLoading: () => useClientDocumentsStore.getState().deleteLoading,

  // Error selectors
  getError: () => useClientDocumentsStore.getState().error,
  getCreateError: () => useClientDocumentsStore.getState().createError,
  getUpdateError: () => useClientDocumentsStore.getState().updateError,
  getDeleteError: () => useClientDocumentsStore.getState().deleteError,
  getDeleteSuccess: () => useClientDocumentsStore.getState().deleteSuccess,
};

export default useClientDocumentsStore; 