/*
 * File: patientCareSlice.ts
 * Description: Patient care state management slice
 * Design & Developed by Tech4Biz Solutions
 * Copyright (c) Spurrin Innovations. All rights reserved.
 */

import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { Patient, PatientCareState } from '../../../shared/types';

// ============================================================================
// ASYNC THUNKS
// ============================================================================

/**
 * Fetch Patients Async Thunk
 * 
 * Purpose: Fetch patients list from API
 * 
 * @returns Promise with patients data or error
 */
export const fetchPatients = createAsyncThunk(
  'patientCare/fetchPatients',
  async (_, { rejectWithValue }) => {
    try {
      // TODO: Replace with actual API call
      await new Promise(resolve => setTimeout(resolve, 1500));
      
      // Mock patients data
      const mockPatients: Patient[] = [
        {
          id: '1',
          mrn: 'MRN001',
          firstName: 'John',
          lastName: 'Doe',
          dateOfBirth: new Date('1985-03-15'),
          gender: 'MALE',
          age: 38,
          bedNumber: 'A1',
          roomNumber: '101',
          admissionDate: new Date('2024-01-15'),
          status: 'ACTIVE',
          priority: 'CRITICAL',
          department: 'Emergency',
          attendingPhysician: 'Dr. Smith',
          allergies: [
            {
              id: '1',
              name: 'Penicillin',
              severity: 'SEVERE',
              reaction: 'Anaphylaxis',
            },
          ],
          medications: [
            {
              id: '1',
              name: 'Morphine',
              dosage: '2mg',
              frequency: 'Every 4 hours',
              route: 'IV',
              startDate: new Date(),
              status: 'ACTIVE',
              prescribedBy: 'Dr. Smith',
            },
          ],
          vitalSigns: {
            bloodPressure: { systolic: 140, diastolic: 90, timestamp: new Date() },
            heartRate: { value: 95, timestamp: new Date() },
            temperature: { value: 37.2, timestamp: new Date() },
            respiratoryRate: { value: 18, timestamp: new Date() },
            oxygenSaturation: { value: 98, timestamp: new Date() },
          },
          medicalHistory: [],
          currentDiagnosis: 'Chest pain, rule out MI',
          lastUpdated: new Date(),
        },
        {
          id: '2',
          mrn: 'MRN002',
          firstName: 'Jane',
          lastName: 'Smith',
          dateOfBirth: new Date('1990-07-22'),
          gender: 'FEMALE',
          age: 33,
          bedNumber: 'B2',
          roomNumber: '102',
          admissionDate: new Date('2024-01-15'),
          status: 'ACTIVE',
          priority: 'HIGH',
          department: 'Trauma',
          attendingPhysician: 'Dr. Johnson',
          allergies: [],
          medications: [],
          vitalSigns: {
            bloodPressure: { systolic: 120, diastolic: 80, timestamp: new Date() },
            heartRate: { value: 88, timestamp: new Date() },
            temperature: { value: 36.8, timestamp: new Date() },
            respiratoryRate: { value: 16, timestamp: new Date() },
            oxygenSaturation: { value: 99, timestamp: new Date() },
          },
          medicalHistory: [],
          currentDiagnosis: 'Multiple trauma from MVA',
          lastUpdated: new Date(),
        },
      ];
      
      return mockPatients;
    } catch (error) {
      return rejectWithValue('Failed to fetch patients.');
    }
  }
);

/**
 * Fetch Patient Details Async Thunk
 * 
 * Purpose: Fetch detailed patient information
 * 
 * @param patientId - ID of the patient to fetch
 * @returns Promise with patient details or error
 */
export const fetchPatientDetails = createAsyncThunk(
  'patientCare/fetchPatientDetails',
  async (patientId: string, { rejectWithValue }) => {
    try {
      // TODO: Replace with actual API call
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      // Mock patient details (same as above but with more detailed info)
      const mockPatient: Patient = {
        id: patientId,
        mrn: `MRN${patientId.padStart(3, '0')}`,
        firstName: 'John',
        lastName: 'Doe',
        dateOfBirth: new Date('1985-03-15'),
        gender: 'MALE',
        age: 38,
        bedNumber: 'A1',
        roomNumber: '101',
        admissionDate: new Date('2024-01-15'),
        status: 'ACTIVE',
        priority: 'CRITICAL',
        department: 'Emergency',
        attendingPhysician: 'Dr. Smith',
        allergies: [
          {
            id: '1',
            name: 'Penicillin',
            severity: 'SEVERE',
            reaction: 'Anaphylaxis',
          },
        ],
        medications: [
          {
            id: '1',
            name: 'Morphine',
            dosage: '2mg',
            frequency: 'Every 4 hours',
            route: 'IV',
            startDate: new Date(),
            status: 'ACTIVE',
            prescribedBy: 'Dr. Smith',
          },
        ],
        vitalSigns: {
          bloodPressure: { systolic: 140, diastolic: 90, timestamp: new Date() },
          heartRate: { value: 95, timestamp: new Date() },
          temperature: { value: 37.2, timestamp: new Date() },
          respiratoryRate: { value: 18, timestamp: new Date() },
          oxygenSaturation: { value: 98, timestamp: new Date() },
        },
        medicalHistory: [],
        currentDiagnosis: 'Chest pain, rule out MI',
        lastUpdated: new Date(),
      };
      
      return mockPatient;
    } catch (error) {
      return rejectWithValue('Failed to fetch patient details.');
    }
  }
);

/**
 * Update Patient Async Thunk
 * 
 * Purpose: Update patient information
 * 
 * @param patientData - Updated patient data
 * @returns Promise with updated patient or error
 */
export const updatePatient = createAsyncThunk(
  'patientCare/updatePatient',
  async (patientData: Partial<Patient> & { id: string }, { rejectWithValue }) => {
    try {
      // TODO: Replace with actual API call
      await new Promise(resolve => setTimeout(resolve, 800));
      return patientData;
    } catch (error) {
      return rejectWithValue('Failed to update patient.');
    }
  }
);

// ============================================================================
// INITIAL STATE
// ============================================================================

/**
 * Initial Patient Care State
 * 
 * Purpose: Define the initial state for patient care
 * 
 * Features:
 * - Patients list and management
 * - Current patient details
 * - Loading states for async operations
 * - Error handling and messages
 * - Search and filtering
 */
const initialState: PatientCareState = {
  // Patients data
  patients: [],
  currentPatient: null,
  
  // Loading states
  isLoading: false,
  isRefreshing: false,
  isLoadingPatientDetails: false,
  
  // Error handling
  error: null,
  
  // Search and filtering
  searchQuery: '',
  selectedFilter: 'all',
  sortBy: 'priority',
  sortOrder: 'desc',
  
  // Pagination
  currentPage: 1,
  itemsPerPage: 20,
  totalItems: 0,
  
  // Cache
  lastUpdated: null,
  cacheExpiry: null,
};

// ============================================================================
// PATIENT CARE SLICE
// ============================================================================

/**
 * Patient Care Slice
 * 
 * Purpose: Redux slice for patient care state management
 * 
 * Features:
 * - Patient data management
 * - Search and filtering
 * - Pagination
 * - Caching
 * - Error handling
 * - Loading states
 */
const patientCareSlice = createSlice({
  name: 'patientCare',
  initialState,
  reducers: {
    /**
     * Clear Error Action
     * 
     * Purpose: Clear patient care errors
     */
    clearError: (state) => {
      state.error = null;
    },
    
    /**
     * Set Search Query Action
     * 
     * Purpose: Set search query for patients
     */
    setSearchQuery: (state, action: PayloadAction<string>) => {
      state.searchQuery = action.payload;
      state.currentPage = 1; // Reset to first page when searching
    },
    
    /**
     * Set Filter Action
     * 
     * Purpose: Set patient filter
     */
    setFilter: (state, action: PayloadAction<'all' | 'active' | 'discharged' | 'critical'>) => {
      state.selectedFilter = action.payload;
      state.currentPage = 1; // Reset to first page when filtering
    },
    
    /**
     * Set Sort Action
     * 
     * Purpose: Set patient sort options
     */
    setSort: (state, action: PayloadAction<{ by: string; order: 'asc' | 'desc' }>) => {
      state.sortBy = action.payload.by;
      state.sortOrder = action.payload.order;
    },
    
    /**
     * Set Current Page Action
     * 
     * Purpose: Set current page for pagination
     */
    setCurrentPage: (state, action: PayloadAction<number>) => {
      state.currentPage = action.payload;
    },
    
    /**
     * Set Items Per Page Action
     * 
     * Purpose: Set items per page for pagination
     */
    setItemsPerPage: (state, action: PayloadAction<number>) => {
      state.itemsPerPage = action.payload;
      state.currentPage = 1; // Reset to first page when changing items per page
    },
    
    /**
     * Set Current Patient Action
     * 
     * Purpose: Set the currently selected patient
     */
    setCurrentPatient: (state, action: PayloadAction<Patient | null>) => {
      state.currentPatient = action.payload;
    },
    
    /**
     * Update Patient in List Action
     * 
     * Purpose: Update a patient in the patients list
     */
    updatePatientInList: (state, action: PayloadAction<Patient>) => {
      const index = state.patients.findIndex(patient => patient.id === action.payload.id);
      if (index !== -1) {
        state.patients[index] = action.payload;
      }
      
      // Update current patient if it's the same patient
      if (state.currentPatient && state.currentPatient.id === action.payload.id) {
        state.currentPatient = action.payload;
      }
    },
    
    /**
     * Add Patient Action
     * 
     * Purpose: Add a new patient to the list
     */
    addPatient: (state, action: PayloadAction<Patient>) => {
      state.patients.unshift(action.payload);
      state.totalItems += 1;
    },
    
    /**
     * Remove Patient Action
     * 
     * Purpose: Remove a patient from the list
     */
    removePatient: (state, action: PayloadAction<string>) => {
      const index = state.patients.findIndex(patient => patient.id === action.payload);
      if (index !== -1) {
        state.patients.splice(index, 1);
        state.totalItems -= 1;
      }
      
      // Clear current patient if it's the same patient
      if (state.currentPatient && state.currentPatient.id === action.payload) {
        state.currentPatient = null;
      }
    },
    
    /**
     * Clear Cache Action
     * 
     * Purpose: Clear patient data cache
     */
    clearCache: (state) => {
      state.patients = [];
      state.currentPatient = null;
      state.lastUpdated = null;
      state.cacheExpiry = null;
    },
  },
  extraReducers: (builder) => {
    // Fetch Patients
    builder
      .addCase(fetchPatients.pending, (state) => {
        state.isLoading = true;
        state.error = null;
      })
      .addCase(fetchPatients.fulfilled, (state, action) => {
        state.isLoading = false;
        state.patients = action.payload;
        state.totalItems = action.payload.length;
        state.lastUpdated = new Date();
        state.cacheExpiry = new Date(Date.now() + 5 * 60 * 1000); // 5 minutes
        state.error = null;
      })
      .addCase(fetchPatients.rejected, (state, action) => {
        state.isLoading = false;
        state.error = action.payload as string;
      });
    
    // Fetch Patient Details
    builder
      .addCase(fetchPatientDetails.pending, (state) => {
        state.isLoadingPatientDetails = true;
        state.error = null;
      })
      .addCase(fetchPatientDetails.fulfilled, (state, action) => {
        state.isLoadingPatientDetails = false;
        state.currentPatient = action.payload;
        state.error = null;
      })
      .addCase(fetchPatientDetails.rejected, (state, action) => {
        state.isLoadingPatientDetails = false;
        state.error = action.payload as string;
      });
    
    // Update Patient
    builder
      .addCase(updatePatient.fulfilled, (state, action) => {
        // Update patient in list
        const index = state.patients.findIndex(patient => patient.id === action.payload.id);
        if (index !== -1) {
          state.patients[index] = { ...state.patients[index], ...action.payload };
        }
        
        // Update current patient if it's the same patient
        if (state.currentPatient && state.currentPatient.id === action.payload.id) {
          state.currentPatient = { ...state.currentPatient, ...action.payload };
        }
      })
      .addCase(updatePatient.rejected, (state, action) => {
        state.error = action.payload as string;
      });
  },
});

// ============================================================================
// EXPORTS
// ============================================================================

export const {
  clearError,
  setSearchQuery,
  setFilter,
  setSort,
  setCurrentPage,
  setItemsPerPage,
  setCurrentPatient,
  updatePatientInList,
  addPatient,
  removePatient,
  clearCache,
} = patientCareSlice.actions;

export default patientCareSlice.reducer;

/*
 * End of File: patientCareSlice.ts
 * Design & Developed by Tech4Biz Solutions
 * Copyright (c) Spurrin Innovations. All rights reserved.
 */ 