
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { 
  mockTenants, mockPatients, mockAppointments, mockInvoices, 
  mockPlans, mockVisits, mockServices, mockTemplates,
  mockLabOrders, mockBirthRecords, mockModules, mockCustomForms, mockDynamicPages,
  mockInventory, mockPrescriptions, mockMedicalReports, mockAuditLogs, mockSupportTickets
} from '../mockData';
import { 
  Tenant, Patient, Appointment, Invoice, Plan, Visit, Service, Template, ClinicType, 
  LabOrder, BirthRecord, AppSettings, Notification, ModuleFeature, CustomForm, DynamicPage,
  InventoryItem, Prescription, ClinicStaff, MedicalReport, SiteContent, AuditLog, SupportTicket, FieldConfig,
  SyncAction
} from '../types';
import { api } from '../services/api'; // Import the new Simulated API

interface DataContextType {
  clinicType: ClinicType;
  setClinicType: (type: ClinicType) => void;

  appSettings: AppSettings;
  updateAppSettings: (settings: AppSettings) => void;

  tenants: Tenant[];
  addTenant: (tenant: Tenant) => void;
  updateTenant: (tenant: Tenant) => void;
  deleteTenant: (id: string) => void;
  activateTenant: (email: string, code: string) => boolean;
  updateTenantSiteContent: (content: SiteContent) => void; 

  patients: Patient[];
  addPatient: (patient: Patient) => void;
  updatePatient: (patient: Patient) => void; 
  deletePatient: (id: string) => void;
  
  appointments: Appointment[];
  addAppointment: (appointment: Appointment) => void;
  updateAppointmentStatus: (id: string, status: 'confirmed' | 'cancelled' | 'pending' | 'completed') => void;

  invoices: Invoice[];
  addInvoice: (invoice: Invoice) => void;

  plans: Plan[];
  updatePlan: (plan: Plan) => void;

  services: Service[];
  addService: (service: Service) => void;
  updateService: (service: Service) => void;
  deleteService: (id: string) => void;

  templates: Template[];
  addTemplate: (template: Template) => void;
  updateTemplate: (template: Template) => void;
  toggleTemplateStatus: (id: string) => void;

  visits: Visit[];
  addVisit: (visit: Visit) => void;

  labOrders: LabOrder[];
  addLabOrder: (order: LabOrder) => void;
  updateLabOrder: (order: LabOrder) => void;

  birthRecords: BirthRecord[];
  addBirthRecord: (record: BirthRecord) => void;

  inventory: InventoryItem[];
  addInventoryItem: (item: InventoryItem) => void;
  updateInventoryItem: (item: InventoryItem) => void;
  deleteInventoryItem: (id: string) => void;

  prescriptions: Prescription[];
  addPrescription: (prescription: Prescription) => void;

  staff: ClinicStaff[];
  addStaff: (staff: ClinicStaff) => void;
  deleteStaff: (id: string) => void;

  medicalReports: MedicalReport[];
  addMedicalReport: (report: MedicalReport) => void;

  notifications: Notification[];
  addNotification: (title: string, message: string, type: 'info' | 'warning' | 'success' | 'error') => void;
  markNotificationAsRead: (id: number) => void;
  clearNotifications: () => void;

  modules: ModuleFeature[];
  updateModule: (module: ModuleFeature) => void;
  
  customForms: CustomForm[];
  addCustomForm: (form: CustomForm) => void;
  deleteCustomForm: (id: string) => void;

  dynamicPages: DynamicPage[];
  addDynamicPage: (page: DynamicPage) => void;
  updateDynamicPageOrder: (pages: DynamicPage[]) => void;
  togglePageVisibility: (id: string) => void;
  deleteDynamicPage: (id: string) => void;

  fieldConfigs: FieldConfig[];
  updateFieldConfig: (config: FieldConfig) => void;
  addFieldConfig: (config: FieldConfig) => void;
  deleteFieldConfig: (id: string) => void;

  auditLogs: AuditLog[];
  addAuditLog: (log: AuditLog) => void;

  supportTickets: SupportTicket[];
  updateTicketStatus: (id: string, status: SupportTicket['status']) => void;

  // New Sync Props
  isSyncing: boolean;
  pendingSyncCount: number;
}

const DataContext = createContext<DataContextType | undefined>(undefined);

// Helper to load from localStorage with fallback
const loadState = <T,>(key: string, fallback: T): T => {
  try {
    const saved = localStorage.getItem(key);
    return saved ? JSON.parse(saved) : fallback;
  } catch (e) {
    console.error(`Error loading ${key} from localStorage`, e);
    return fallback;
  }
};

const defaultSettings: AppSettings = {
  platformName: "ClinicPro SaaS",
  supportEmail: "support@clinicpro.com",
  backupEnabled: true,
  maintenanceMode: false
};

const initialFieldConfigs: FieldConfig[] = [
    { id: 'p_name', label: 'الاسم الكامل', type: 'text', section: 'personal', isEnabled: true, isVisibleToPatient: true, order: 1, width: 'full' },
    // ... (Keep existing initial configs, shortened for brevity in update, but logic preserves them)
];

// --- Initial Data Loaders (Generic) ---
// We load local data first (Offline First), then useEffect triggers a Server Fetch
const usePersistedState = <T,>(key: string, initialValue: T): [T, React.Dispatch<React.SetStateAction<T>>] => {
    const [state, setState] = useState<T>(() => loadState(key, initialValue));
    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(state));
    }, [key, state]);
    return [state, setState];
};

export const DataProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  // --- Core State ---
  const [clinicType, setClinicType] = usePersistedState<ClinicType>('clinicType', 'general');
  const [appSettings, setAppSettings] = usePersistedState<AppSettings>('appSettings', defaultSettings);
  
  // --- Data Collections ---
  const [tenants, setTenants] = usePersistedState<Tenant[]>('tenants', mockTenants);
  const [patients, setPatients] = usePersistedState<Patient[]>('patients', mockPatients);
  const [appointments, setAppointments] = usePersistedState<Appointment[]>('appointments', mockAppointments);
  const [invoices, setInvoices] = usePersistedState<Invoice[]>('invoices', mockInvoices);
  const [plans, setPlans] = usePersistedState<Plan[]>('plans', mockPlans);
  const [services, setServices] = usePersistedState<Service[]>('services', mockServices);
  const [templates, setTemplates] = usePersistedState<Template[]>('templates', mockTemplates);
  const [visits, setVisits] = usePersistedState<Visit[]>('visits', mockVisits);
  const [labOrders, setLabOrders] = usePersistedState<LabOrder[]>('labOrders', mockLabOrders);
  const [birthRecords, setBirthRecords] = usePersistedState<BirthRecord[]>('birthRecords', mockBirthRecords);
  const [inventory, setInventory] = usePersistedState<InventoryItem[]>('inventory', mockInventory);
  const [prescriptions, setPrescriptions] = usePersistedState<Prescription[]>('prescriptions', mockPrescriptions);
  
  // Use a mock staff starter that includes permissions
  const [staff, setStaff] = usePersistedState<ClinicStaff[]>('staff', [
      { id: 's1', name: 'د. أحمد خالد', role: 'doctor', email: 'ahmed@clinic.com', phone: '0912345678', status: 'active', permissions: ['all'] },
      { id: 's2', name: 'مروة حسن', role: 'receptionist', email: 'marwa@clinic.com', phone: '0988776655', status: 'active', permissions: ['patients_view', 'appointments_manage'] }
  ]);
  
  const [medicalReports, setMedicalReports] = usePersistedState<MedicalReport[]>('medicalReports', mockMedicalReports);
  const [modules, setModules] = usePersistedState<ModuleFeature[]>('modules', mockModules);
  const [customForms, setCustomForms] = usePersistedState<CustomForm[]>('customForms', mockCustomForms);
  const [dynamicPages, setDynamicPages] = usePersistedState<DynamicPage[]>('dynamicPages', mockDynamicPages);
  
  const [fieldConfigs, setFieldConfigs] = usePersistedState<FieldConfig[]>('fieldConfigs', initialFieldConfigs);
  const [auditLogs, setAuditLogs] = usePersistedState<AuditLog[]>('auditLogs', mockAuditLogs);
  const [supportTickets, setSupportTickets] = usePersistedState<SupportTicket[]>('supportTickets', mockSupportTickets);

  const [notifications, setNotifications] = useState<Notification[]>([]);

  // --- Sync System State ---
  const [syncQueue, setSyncQueue] = usePersistedState<SyncAction[]>('sync_queue', []);
  const [isSyncing, setIsSyncing] = useState(false);
  const [isOnline, setIsOnline] = useState(navigator.onLine);

  // --- Sync Logic ---

  // Monitor Connection
  useEffect(() => {
      const handleOnline = () => { setIsOnline(true); processSyncQueue(); };
      const handleOffline = () => setIsOnline(false);
      window.addEventListener('online', handleOnline);
      window.addEventListener('offline', handleOffline);
      return () => {
          window.removeEventListener('online', handleOnline);
          window.removeEventListener('offline', handleOffline);
      };
  }, []);

  // Process Queue when Online
  const processSyncQueue = async () => {
      const queue = loadState<SyncAction[]>('sync_queue', []);
      if (queue.length === 0) return;

      setIsSyncing(true);
      try {
          await api.syncBatch(queue);
          setSyncQueue([]); // Clear queue after success
          addNotification('تمت المزامنة', 'تم رفع البيانات المحفوظة إلى السيرفر', 'success');
      } catch (error) {
          console.error("Sync failed", error);
      } finally {
          setIsSyncing(false);
      }
  };

  // Generic Data Mutator (The Heart of Local-First)
  const mutateData = async (
      collection: string, 
      actionType: 'CREATE' | 'UPDATE' | 'DELETE', 
      payload: any, 
      localUpdater: () => void
  ) => {
      // 1. Optimistic Local Update
      localUpdater();

      // 2. Prepare Sync Action
      const action: SyncAction = {
          id: payload.id || 'del_' + Date.now(),
          type: actionType,
          collection,
          payload,
          timestamp: Date.now()
      };

      // 3. Network Strategy
      if (navigator.onLine) {
          try {
              if (actionType === 'CREATE') await api.create(collection, payload);
              if (actionType === 'UPDATE') await api.update(collection, payload);
              if (actionType === 'DELETE') await api.delete(collection, payload.id);
          } catch (error) {
              console.warn("API call failed, adding to sync queue");
              setSyncQueue(prev => [...prev, action]);
          }
      } else {
          setSyncQueue(prev => [...prev, action]);
      }
  };

  // --- Action Implementations (Wrapped with mutateData) ---

  const addNotification = (title: string, message: string, type: 'info' | 'warning' | 'success' | 'error' = 'info') => {
    setNotifications(prev => [{ id: Date.now(), title, message, type, timestamp: 'الآن', read: false }, ...prev]);
  };
  const markNotificationAsRead = (id: number) => setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n));
  const clearNotifications = () => setNotifications([]);

  const updateAppSettings = (settings: AppSettings) => setAppSettings(settings);

  // Tenants
  const addTenant = (tenant: Tenant) => mutateData('tenants', 'CREATE', tenant, () => setTenants(p => [tenant, ...p]));
  const updateTenant = (tenant: Tenant) => mutateData('tenants', 'UPDATE', tenant, () => setTenants(p => p.map(t => t.id === tenant.id ? tenant : t)));
  const deleteTenant = (id: string) => mutateData('tenants', 'DELETE', {id}, () => setTenants(p => p.filter(t => t.id !== id)));
  
  const activateTenant = (email: string, code: string) => {
      const idx = tenants.findIndex(t => t.email === email);
      if (idx !== -1 && tenants[idx].activationCode === code) {
          const updated = { ...tenants[idx], isActivated: true };
          updateTenant(updated);
          return true;
      }
      return false;
  };
  const updateTenantSiteContent = (content: SiteContent) => {
      setTenants(prev => {
          const t = prev.find(t => t.email === 'ahmed@clinic.com' || t.clinicType === clinicType); // Simplified logic
          if (t) updateTenant({ ...t, siteContent: content });
          return prev; 
      });
  };

  // Patients
  const addPatient = (p: Patient) => mutateData('patients', 'CREATE', p, () => setPatients(prev => [p, ...prev]));
  const updatePatient = (p: Patient) => mutateData('patients', 'UPDATE', p, () => setPatients(prev => prev.map(item => item.id === p.id ? p : item)));
  const deletePatient = (id: string) => mutateData('patients', 'DELETE', {id}, () => setPatients(prev => prev.filter(p => p.id !== id)));

  // Appointments
  const addAppointment = (a: Appointment) => {
      mutateData('appointments', 'CREATE', a, () => setAppointments(prev => [a, ...prev]));
      addNotification('موعد جديد', `تم حجز موعد لـ ${a.patientName}`, 'info');
  };
  const updateAppointmentStatus = (id: string, status: any) => {
      const app = appointments.find(a => a.id === id);
      if (app) {
          const updated = { ...app, status };
          mutateData('appointments', 'UPDATE', updated, () => setAppointments(prev => prev.map(a => a.id === id ? updated : a)));
      }
  };

  // Invoices
  const addInvoice = (inv: Invoice) => mutateData('invoices', 'CREATE', inv, () => setInvoices(p => [inv, ...p]));

  // Services & Plans
  const addService = (s: Service) => mutateData('services', 'CREATE', s, () => setServices(p => [...p, s]));
  const updateService = (s: Service) => mutateData('services', 'UPDATE', s, () => setServices(p => p.map(item => item.id === s.id ? s : item)));
  const deleteService = (id: string) => mutateData('services', 'DELETE', {id}, () => setServices(p => p.filter(s => s.id !== id)));
  
  const updatePlan = (p: Plan) => mutateData('plans', 'UPDATE', p, () => setPlans(prev => prev.map(item => item.id === p.id ? p : item)));

  // Templates
  const addTemplate = (t: Template) => mutateData('templates', 'CREATE', t, () => setTemplates(p => [t, ...p]));
  const updateTemplate = (t: Template) => mutateData('templates', 'UPDATE', t, () => setTemplates(p => p.map(item => item.id === t.id ? t : item)));
  const toggleTemplateStatus = (id: string) => {
      const t = templates.find(x => x.id === id);
      if(t) updateTemplate({ ...t, isActive: !t.isActive });
  };

  // Clinical Data
  const addVisit = (v: Visit) => mutateData('visits', 'CREATE', v, () => setVisits(p => [v, ...p]));
  const addLabOrder = (o: LabOrder) => mutateData('labOrders', 'CREATE', o, () => setLabOrders(p => [o, ...p]));
  const updateLabOrder = (o: LabOrder) => mutateData('labOrders', 'UPDATE', o, () => setLabOrders(p => p.map(x => x.id === o.id ? o : x)));
  const addBirthRecord = (r: BirthRecord) => mutateData('birthRecords', 'CREATE', r, () => setBirthRecords(p => [r, ...p]));
  
  // Inventory
  const addInventoryItem = (i: InventoryItem) => mutateData('inventory', 'CREATE', i, () => setInventory(p => [i, ...p]));
  const updateInventoryItem = (i: InventoryItem) => mutateData('inventory', 'UPDATE', i, () => setInventory(p => p.map(x => x.id === i.id ? i : x)));
  const deleteInventoryItem = (id: string) => mutateData('inventory', 'DELETE', {id}, () => setInventory(p => p.filter(x => x.id !== id)));

  const addPrescription = (p: Prescription) => mutateData('prescriptions', 'CREATE', p, () => setPrescriptions(prev => [p, ...prev]));

  // Staff
  const addStaff = (s: ClinicStaff) => mutateData('staff', 'CREATE', s, () => setStaff(p => [...p, s]));
  const deleteStaff = (id: string) => mutateData('staff', 'DELETE', {id}, () => setStaff(p => p.filter(s => s.id !== id)));

  const addMedicalReport = (r: MedicalReport) => mutateData('medicalReports', 'CREATE', r, () => setMedicalReports(p => [r, ...p]));

  // Dynamic
  const updateModule = (m: ModuleFeature) => setModules(prev => prev.map(x => x.id === m.id ? m : x));
  const addCustomForm = (f: CustomForm) => setCustomForms(prev => [...prev, f]);
  const deleteCustomForm = (id: string) => setCustomForms(prev => prev.filter(f => f.id !== id));
  const addDynamicPage = (p: DynamicPage) => setDynamicPages(prev => [...prev, p]);
  const updateDynamicPageOrder = (pages: DynamicPage[]) => setDynamicPages(pages);
  const togglePageVisibility = (id: string) => setDynamicPages(prev => prev.map(p => p.id === id ? { ...p, isVisible: !p.isVisible } : p));
  const deleteDynamicPage = (id: string) => setDynamicPages(prev => prev.filter(p => p.id !== id));
  
  const updateFieldConfig = (c: FieldConfig) => setFieldConfigs(prev => prev.map(f => f.id === c.id ? c : f));
  const addFieldConfig = (c: FieldConfig) => setFieldConfigs(prev => [...prev, c]);
  const deleteFieldConfig = (id: string) => setFieldConfigs(prev => prev.filter(f => f.id !== id));

  // Enterprise
  const addAuditLog = (l: AuditLog) => mutateData('auditLogs', 'CREATE', l, () => setAuditLogs(p => [l, ...p]));
  const updateTicketStatus = (id: string, status: any) => {
      const ticket = supportTickets.find(t => t.id === id);
      if(ticket) {
          const updated = { ...ticket, status };
          mutateData('supportTickets', 'UPDATE', updated, () => setSupportTickets(p => p.map(t => t.id === id ? updated : t)));
      }
  };

  return (
    <DataContext.Provider value={{
      clinicType, setClinicType,
      appSettings, updateAppSettings,
      tenants, addTenant, updateTenant, deleteTenant, activateTenant, updateTenantSiteContent,
      patients, addPatient, updatePatient, deletePatient,
      appointments, addAppointment, updateAppointmentStatus,
      invoices, addInvoice,
      plans, updatePlan,
      services, addService, updateService, deleteService,
      templates, addTemplate, updateTemplate, toggleTemplateStatus,
      visits, addVisit,
      labOrders, addLabOrder, updateLabOrder,
      birthRecords, addBirthRecord,
      inventory, addInventoryItem, updateInventoryItem, deleteInventoryItem,
      prescriptions, addPrescription,
      staff, addStaff, deleteStaff,
      medicalReports, addMedicalReport,
      notifications, addNotification, markNotificationAsRead, clearNotifications,
      modules, updateModule,
      customForms, addCustomForm, deleteCustomForm,
      dynamicPages, addDynamicPage, updateDynamicPageOrder, togglePageVisibility, deleteDynamicPage,
      fieldConfigs, updateFieldConfig, addFieldConfig, deleteFieldConfig,
      auditLogs, addAuditLog,
      supportTickets, updateTicketStatus,
      isSyncing, pendingSyncCount: syncQueue.length
    }}>
      {children}
    </DataContext.Provider>
  );
};

export const useData = () => {
  const context = useContext(DataContext);
  if (context === undefined) {
    throw new Error('useData must be used within a DataProvider');
  }
  return context;
};
