import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { crmAPI } from '../services/crmAPI';
import type { 
  CrmLead, 
  CrmTask, 
  CrmContact, 
  CrmDeal, 
  CrmSalesOrder,
  CrmPurchaseOrder,
  CrmInvoice,
  CrmStats,
  CrmSearchParams,
  CrmApiResponse,
  CrmPaginatedResponse
} from '../types/CrmTypes';

// State interface
export interface CrmState {
  // Data
  leads: CrmLead[];
  tasks: CrmTask[];
  contacts: CrmContact[];
  deals: CrmDeal[];
  salesOrders: CrmSalesOrder[];
  purchaseOrders: CrmPurchaseOrder[];
  invoices: CrmInvoice[];
  
  // Loading states
  loading: {
    leads: boolean;
    tasks: boolean;
    contacts: boolean;
    deals: boolean;
    salesOrders: boolean;
    purchaseOrders: boolean;
    invoices: boolean;
    stats: boolean;
  };
  
  // Error states
  errors: {
    leads: string | null;
    tasks: string | null;
    contacts: string | null;
    deals: string | null;
    salesOrders: string | null;
    purchaseOrders: string | null;
    invoices: string | null;
    stats: string | null;
  };
  
  // Pagination
  pagination: {
    leads: { page: number; count: number; moreRecords: boolean };
    tasks: { page: number; count: number; moreRecords: boolean };
    contacts: { page: number; count: number; moreRecords: boolean };
    deals: { page: number; count: number; moreRecords: boolean };
    salesOrders: { page: number; count: number; moreRecords: boolean };
    purchaseOrders: { page: number; count: number; moreRecords: boolean };
    invoices: { page: number; count: number; moreRecords: boolean };
  };
  
  // Statistics
  stats: CrmStats | null;
  
  // Module counts
  counts: {
    leads: number;
    tasks: number;
    contacts: number;
    deals: number;
    salesOrders: number;
    purchaseOrders: number;
    invoices: number;
    accounts: number;
    vendors: number;
  } | null;
  
  // Comprehensive KPIs report
  kpis: any | null;
  
  // Last updated timestamps
  lastUpdated: {
    leads: string | null;
    tasks: string | null;
    contacts: string | null;
    deals: string | null;
    salesOrders: string | null;
    purchaseOrders: string | null;
    invoices: string | null;
    stats: string | null;
  };
}

// Initial state
const initialState: CrmState = {
  leads: [],
  tasks: [],
  contacts: [],
  deals: [],
  salesOrders: [],
  purchaseOrders: [],
  invoices: [],
  loading: {
    leads: false,
    tasks: false,
    contacts: false,
    deals: false,
    salesOrders: false,
    purchaseOrders: false,
    invoices: false,
    stats: false,
  },
  errors: {
    leads: null,
    tasks: null,
    contacts: null,
    deals: null,
    salesOrders: null,
    purchaseOrders: null,
    invoices: null,
    stats: null,
  },
  pagination: {
    leads: { page: 1, count: 0, moreRecords: false },
    tasks: { page: 1, count: 0, moreRecords: false },
    contacts: { page: 1, count: 0, moreRecords: false },
    deals: { page: 1, count: 0, moreRecords: false },
    salesOrders: { page: 1, count: 0, moreRecords: false },
    purchaseOrders: { page: 1, count: 0, moreRecords: false },
    invoices: { page: 1, count: 0, moreRecords: false },
  },
  stats: null,
  counts: null,
  kpis: null,
  lastUpdated: {
    leads: null,
    tasks: null,
    contacts: null,
    deals: null,
    salesOrders: null,
    purchaseOrders: null,
    invoices: null,
    stats: null,
  },
};

// Async thunks for infinite scrolling
export const fetchLeads = createAsyncThunk(
  'crm/fetchLeads',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getLeads(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchTasks = createAsyncThunk(
  'crm/fetchTasks',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getTasks(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchContacts = createAsyncThunk(
  'crm/fetchContacts',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getContacts(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchDeals = createAsyncThunk(
  'crm/fetchDeals',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getDeals(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchSalesOrders = createAsyncThunk(
  'crm/fetchSalesOrders',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getSalesOrders(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchPurchaseOrders = createAsyncThunk(
  'crm/fetchPurchaseOrders',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getPurchaseOrders(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

export const fetchInvoices = createAsyncThunk(
  'crm/fetchInvoices',
  async (params?: CrmSearchParams & { append?: boolean }) => {
    const response = await crmAPI.getInvoices(params);
    return { 
      data: response.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      append: params?.append || false
    };
  }
);

// Fetch CRM counts
export const fetchCrmCounts = createAsyncThunk(
  'crm/fetchCounts',
  async () => {
    const response = await crmAPI.getCrmCounts();
    return response.data?.data || {
      data: {
        accounts: { count: 0, success: false },
        leads: { count: 0, success: false },
        tasks: { count: 0, success: false },
        invoices: { count: 0, success: false },
        sales_orders: { count: 0, success: false },
        purchase_orders: { count: 0, success: false },
        deals: { count: 0, success: false },
        contacts: { count: 0, success: false },
        vendors: { count: 0, success: false },
      },
      info: {
        totalModules: 0,
        successfulModules: 0,
        failedModules: 0,
      }
    };
  }
);

// Fetch comprehensive CRM KPIs
export const fetchCrmKPIs = createAsyncThunk(
  'crm/fetchKPIs',
  async () => {
    const response = await crmAPI.getCrmKPIs();
    return response.data?.data || null;
  }
);

// Fetch all CRM data
export const fetchAllCrmData = createAsyncThunk(
  'crm/fetchAllData',
  async (params?: CrmSearchParams) => {
    const [
      leadsResponse, 
      tasksResponse, 
      contactsResponse, 
      dealsResponse,
      salesOrdersResponse,
      purchaseOrdersResponse,
      invoicesResponse
    ] = await Promise.all([
      crmAPI.getLeads(params),
      crmAPI.getTasks(params),
      crmAPI.getContacts(params),
      crmAPI.getDeals(params),
      crmAPI.getSalesOrders(params),
      crmAPI.getPurchaseOrders(params),
      crmAPI.getInvoices(params),
    ]);
    console.log('leads response data',leadsResponse)
    return {
      leads: leadsResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      tasks: tasksResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      contacts: contactsResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      deals: dealsResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      salesOrders: salesOrdersResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      purchaseOrders: purchaseOrdersResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
      invoices: invoicesResponse.data?.data || { data: [], info: { count: 0, moreRecords: false, page: 1 } },
    };
  }
);

// Slice
const crmSlice = createSlice({
  name: 'crm',
  initialState,
  reducers: {
    clearErrors: (state) => {
      state.errors = {
        leads: null,
        tasks: null,
        contacts: null,
        deals: null,
        salesOrders: null,
        purchaseOrders: null,
        invoices: null,
        stats: null,
      };
    },
    clearData: (state) => {
      state.leads = [];
      state.tasks = [];
      state.contacts = [];
      state.deals = [];
      state.salesOrders = [];
      state.purchaseOrders = [];
      state.invoices = [];
      state.stats = null;
    },
    setLeadsPage: (state, action: PayloadAction<number>) => {
      state.pagination.leads.page = action.payload;
    },
    setTasksPage: (state, action: PayloadAction<number>) => {
      state.pagination.tasks.page = action.payload;
    },
    setContactsPage: (state, action: PayloadAction<number>) => {
      state.pagination.contacts.page = action.payload;
    },
    setDealsPage: (state, action: PayloadAction<number>) => {
      state.pagination.deals.page = action.payload;
    },
    setSalesOrdersPage: (state, action: PayloadAction<number>) => {
      state.pagination.salesOrders.page = action.payload;
    },
    setPurchaseOrdersPage: (state, action: PayloadAction<number>) => {
      state.pagination.purchaseOrders.page = action.payload;
    },
    setInvoicesPage: (state, action: PayloadAction<number>) => {
      state.pagination.invoices.page = action.payload;
    },
    // Reset pagination for specific data types
    resetLeadsPagination: (state) => {
      state.pagination.leads = { page: 1, count: 0, moreRecords: false };
      state.leads = [];
    },
    resetTasksPagination: (state) => {
      state.pagination.tasks = { page: 1, count: 0, moreRecords: false };
      state.tasks = [];
    },
    resetContactsPagination: (state) => {
      state.pagination.contacts = { page: 1, count: 0, moreRecords: false };
      state.contacts = [];
    },
    resetDealsPagination: (state) => {
      state.pagination.deals = { page: 1, count: 0, moreRecords: false };
      state.deals = [];
    },
    resetSalesOrdersPagination: (state) => {
      state.pagination.salesOrders = { page: 1, count: 0, moreRecords: false };
      state.salesOrders = [];
    },
    resetPurchaseOrdersPagination: (state) => {
      state.pagination.purchaseOrders = { page: 1, count: 0, moreRecords: false };
      state.purchaseOrders = [];
    },
    resetInvoicesPagination: (state) => {
      state.pagination.invoices = { page: 1, count: 0, moreRecords: false };
      state.invoices = [];
    },
  },
  extraReducers: (builder) => {
    // Fetch leads
    builder
      .addCase(fetchLeads.pending, (state) => {
        state.loading.leads = true;
        state.errors.leads = null;
      })
       .addCase(fetchLeads.fulfilled, (state, action) => {
         state.loading.leads = false;
         const { data, append } = action.payload;
         
         if (append) {
           // Append new data to existing data for infinite scrolling
           state.leads = [...state.leads, ...(data.data || [])];
         } else {
           // Replace data for initial load or refresh
           state.leads = data.data || [];
         }
         
         state.pagination.leads = data.info || { page: 1, count: 0, moreRecords: false };
         state.lastUpdated.leads = new Date().toISOString();
       })
      .addCase(fetchLeads.rejected, (state, action) => {
        state.loading.leads = false;
        state.errors.leads = action.error.message || 'Failed to fetch leads';
      })
      
      // Fetch tasks
      .addCase(fetchTasks.pending, (state) => {
        state.loading.tasks = true;
        state.errors.tasks = null;
      })
       .addCase(fetchTasks.fulfilled, (state, action) => {
         state.loading.tasks = false;
         const { data, append } = action.payload;
         
         if (append) {
           // Append new data to existing data for infinite scrolling
           state.tasks = [...state.tasks, ...(data.data || [])];
         } else {
           // Replace data for initial load or refresh
           state.tasks = data.data || [];
         }
         
         state.pagination.tasks = data.info || { page: 1, count: 0, moreRecords: false };
         state.lastUpdated.tasks = new Date().toISOString();
       })
      .addCase(fetchTasks.rejected, (state, action) => {
        state.loading.tasks = false;
        state.errors.tasks = action.error.message || 'Failed to fetch tasks';
      })
      
      // Fetch contacts
      .addCase(fetchContacts.pending, (state) => {
        state.loading.contacts = true;
        state.errors.contacts = null;
      })
       .addCase(fetchContacts.fulfilled, (state, action) => {
         state.loading.contacts = false;
         const { data, append } = action.payload;
         
         if (append) {
           // Append new data to existing data for infinite scrolling
           state.contacts = [...state.contacts, ...(data.data || [])];
         } else {
           // Replace data for initial load or refresh
           state.contacts = data.data || [];
         }
         
         state.pagination.contacts = data.info || { page: 1, count: 0, moreRecords: false };
         state.lastUpdated.contacts = new Date().toISOString();
       })
      .addCase(fetchContacts.rejected, (state, action) => {
        state.loading.contacts = false;
        state.errors.contacts = action.error.message || 'Failed to fetch contacts';
      })
      
      // Fetch deals
      .addCase(fetchDeals.pending, (state) => {
        state.loading.deals = true;
        state.errors.deals = null;
      })
       .addCase(fetchDeals.fulfilled, (state, action) => {
         state.loading.deals = false;
         const { data, append } = action.payload;
         
         if (append) {
           // Append new data to existing data for infinite scrolling
           state.deals = [...state.deals, ...(data.data || [])];
         } else {
           // Replace data for initial load or refresh
           state.deals = data.data || [];
         }
         
         state.pagination.deals = data.info || { page: 1, count: 0, moreRecords: false };
         state.lastUpdated.deals = new Date().toISOString();
       })
      .addCase(fetchDeals.rejected, (state, action) => {
        state.loading.deals = false;
        state.errors.deals = action.error.message || 'Failed to fetch deals';
      })
      
      // Fetch sales orders
      .addCase(fetchSalesOrders.pending, (state) => {
        state.loading.salesOrders = true;
        state.errors.salesOrders = null;
      })
      .addCase(fetchSalesOrders.fulfilled, (state, action) => {
        state.loading.salesOrders = false;
        const { data, append } = action.payload;
        
        if (append) {
          // Append new data to existing data for infinite scrolling
          state.salesOrders = [...state.salesOrders, ...(data.data || [])];
        } else {
          // Replace data for initial load or refresh
          state.salesOrders = data.data || [];
        }
        
        state.pagination.salesOrders = data.info || { page: 1, count: 0, moreRecords: false };
        state.lastUpdated.salesOrders = new Date().toISOString();
      })
      .addCase(fetchSalesOrders.rejected, (state, action) => {
        state.loading.salesOrders = false;
        state.errors.salesOrders = action.error.message || 'Failed to fetch sales orders';
      })
      
      // Fetch purchase orders
      .addCase(fetchPurchaseOrders.pending, (state) => {
        state.loading.purchaseOrders = true;
        state.errors.purchaseOrders = null;
      })
      .addCase(fetchPurchaseOrders.fulfilled, (state, action) => {
        state.loading.purchaseOrders = false;
        const { data, append } = action.payload;
        
        if (append) {
          // Append new data to existing data for infinite scrolling
          state.purchaseOrders = [...state.purchaseOrders, ...(data.data || [])];
        } else {
          // Replace data for initial load or refresh
          state.purchaseOrders = data.data || [];
        }
        
        state.pagination.purchaseOrders = data.info || { page: 1, count: 0, moreRecords: false };
        state.lastUpdated.purchaseOrders = new Date().toISOString();
      })
      .addCase(fetchPurchaseOrders.rejected, (state, action) => {
        state.loading.purchaseOrders = false;
        state.errors.purchaseOrders = action.error.message || 'Failed to fetch purchase orders';
      })
      
      // Fetch invoices
      .addCase(fetchInvoices.pending, (state) => {
        state.loading.invoices = true;
        state.errors.invoices = null;
      })
      .addCase(fetchInvoices.fulfilled, (state, action) => {
        state.loading.invoices = false;
        const { data, append } = action.payload;
        
        if (append) {
          // Append new data to existing data for infinite scrolling
          state.invoices = [...state.invoices, ...(data.data || [])];
        } else {
          // Replace data for initial load or refresh
          state.invoices = data.data || [];
        }
        
        state.pagination.invoices = data.info || { page: 1, count: 0, moreRecords: false };
        state.lastUpdated.invoices = new Date().toISOString();
      })
      .addCase(fetchInvoices.rejected, (state, action) => {
        state.loading.invoices = false;
        state.errors.invoices = action.error.message || 'Failed to fetch invoices';
      })
      
      // Fetch all CRM data
      .addCase(fetchAllCrmData.pending, (state) => {
        state.loading.leads = true;
        state.loading.tasks = true;
        state.loading.contacts = true;
        state.loading.deals = true;
        state.loading.salesOrders = true;
        state.loading.purchaseOrders = true;
        state.loading.invoices = true;
        state.errors.leads = null;
        state.errors.tasks = null;
        state.errors.contacts = null;
        state.errors.deals = null;
        state.errors.salesOrders = null;
        state.errors.purchaseOrders = null;
        state.errors.invoices = null;
      })
      .addCase(fetchAllCrmData.fulfilled, (state, action) => {
        const { leads, tasks, contacts, deals, salesOrders, purchaseOrders, invoices } = action.payload;
        
        state.loading.leads = false;
        state.loading.tasks = false;
        state.loading.contacts = false;
        state.loading.deals = false;
        state.loading.salesOrders = false;
        state.loading.purchaseOrders = false;
        state.loading.invoices = false;
        
        state.leads = leads.data || [];
        state.tasks = tasks.data || [];
        state.contacts = contacts.data || [];
        state.deals = deals.data || [];
        state.salesOrders = salesOrders.data || [];
        state.purchaseOrders = purchaseOrders.data || [];
        state.invoices = invoices.data || [];
        
        state.pagination.leads = leads.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.tasks = tasks.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.contacts = contacts.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.deals = deals.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.salesOrders = salesOrders.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.purchaseOrders = purchaseOrders.info || { page: 1, count: 0, moreRecords: false };
        state.pagination.invoices = invoices.info || { page: 1, count: 0, moreRecords: false };
        
        const now = new Date().toISOString();
        state.lastUpdated.leads = now;
        state.lastUpdated.tasks = now;
        state.lastUpdated.contacts = now;
        state.lastUpdated.deals = now;
        state.lastUpdated.salesOrders = now;
        state.lastUpdated.purchaseOrders = now;
        state.lastUpdated.invoices = now;
      })
      .addCase(fetchAllCrmData.rejected, (state, action) => {
        state.loading.leads = false;
        state.loading.tasks = false;
        state.loading.contacts = false;
        state.loading.deals = false;
        state.loading.salesOrders = false;
        state.loading.purchaseOrders = false;
        state.loading.invoices = false;
        
        const errorMessage = action.error.message || 'Failed to fetch CRM data';
        state.errors.leads = errorMessage;
        state.errors.tasks = errorMessage;
        state.errors.contacts = errorMessage;
        state.errors.deals = errorMessage;
        state.errors.salesOrders = errorMessage;
        state.errors.purchaseOrders = errorMessage;
        state.errors.invoices = errorMessage;
      })
      
      // Fetch CRM counts
      .addCase(fetchCrmCounts.pending, (state) => {
        // No loading state needed for counts as it's fetched in background
      })
      .addCase(fetchCrmCounts.fulfilled, (state, action) => {
        const { data } = action.payload;
        state.counts = {
          leads: data.leads?.count || 0,
          tasks: data.tasks?.count || 0,
          contacts: data.contacts?.count || 0,
          deals: data.deals?.count || 0,
          salesOrders: data.sales_orders?.count || 0,
          purchaseOrders: data.purchase_orders?.count || 0,
          invoices: data.invoices?.count || 0,
          accounts: data.accounts?.count || 0,
          vendors: data.vendors?.count || 0,
        };
      })
      .addCase(fetchCrmCounts.rejected, (state) => {
        // Keep existing counts on error
        console.warn('Failed to fetch CRM counts');
      })
      
      // Fetch CRM KPIs
      .addCase(fetchCrmKPIs.pending, (state) => {
        // No loading state needed for KPIs as it's fetched in background
      })
      .addCase(fetchCrmKPIs.fulfilled, (state, action) => {
        state.kpis = action.payload;
      })
      .addCase(fetchCrmKPIs.rejected, (state) => {
        // Keep existing KPIs on error
        console.warn('Failed to fetch CRM KPIs');
      });
  },
});

export const {
  clearErrors,
  clearData,
  setLeadsPage,
  setTasksPage,
  setContactsPage,
  setDealsPage,
  setSalesOrdersPage,
  setPurchaseOrdersPage,
  setInvoicesPage,
  resetLeadsPagination,
  resetTasksPagination,
  resetContactsPagination,
  resetDealsPagination,
  resetSalesOrdersPagination,
  resetPurchaseOrdersPagination,
  resetInvoicesPagination,
} = crmSlice.actions;

export default crmSlice.reducer;
