import React, { createContext, useContext, useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { toast } from 'sonner';
import { storage } from '../lib/storage';
import { useAuth } from './AuthContext';

export interface Project {
  id: string;
  name: string;
  client: string;
  status: string;
  team: number;
  deadline: string;
  assignedTo?: string;
  description?: string;
  currency?: string;
  ticketId?: string;
  personName?: string;
  email?: string;
  contactNumber?: string;
  assignedEmail?: string;
  assignedContactNumber?: string;
  hourlyRate?: number;
  halfDayRate?: number;
  fullDayRate?: number;
  monthlyRate?: number;
  travelCost?: number;
  materialCost?: number;
  clientHourlyRate?: number;
  clientHalfDayRate?: number;
  clientFullDayRate?: number;
  clientMonthlyRate?: number;
  clientTravelCost?: number;
  clientMaterialCost?: number;
  clientTotalAmount?: number;
  timeIn?: string;
  timeOut?: string;
  totalTime?: string;
  totalAmount?: number;
  totalDays?: number;
  completedDate?: string;
  address?: string;
  clientAddress?: string;
  companyName?: string;
  companyEmail?: string;
  companyPhone?: string;
  companyAddress?: string;
  issueDate?: string;
  issuedMonth?: string;
  clientStatus?: string;
  assignedRole?: string;
  engineerInvoiceStatus?: 'Paid' | 'Unpaid' | 'Overdue';
  clientInvoiceStatus?: 'Paid' | 'Unpaid' | 'Overdue';
  taxRate?: number;
  taxAmount?: number;
  thirdPartyName?: string;
  thirdPartyCommissionRate?: number;
  thirdPartyCommissionAmount?: number;
  thirdPartyStatus?: 'Paid' | 'Unpaid';
  commissions?: {
    id: string;
    vendorName: string;
    rate: number;
    amount: number;
    status: 'Paid' | 'Unpaid';
  }[];
  files?: { name: string; url: string; size: string; type: string; uploadedAt: string }[];
}

export interface Task {
  id: string;
  title: string;
  project: string;
  projectId?: string;
  assignDate: string;
  status: 'To Do' | 'In Progress' | 'Completed';
  dueDate: string;
  assignee: string;
  completedDate?: string;
  approvalStatus?: 'Pending' | 'Approved' | 'Rejected';
  timeLogged?: string;
}

export interface Expense {
  id: string;
  description: string;
  category: string;
  amount: number;
  date: string;
  status: 'Approved' | 'Pending' | 'Rejected';
  paymentMethod: string;
  reference?: string;
}

export interface ClientContact {
  id: string;
  name: string;
  role: string;
  email: string;
  phone: string;
}

export interface Client {
  id: string;
  name: string;
  industry: string;
  contactPerson: string;
  email: string;
  phone: string;
  status: 'Active' | 'Inactive' | 'Onboarding';
  projects: number;
  revenue: number;
  website?: string;
  contacts?: ClientContact[];
}

export interface Engineer {
  id: string;
  name: string;
  role: string;
  department: string;
  email: string;
  phone: string;
  status: 'Active' | 'On Leave' | 'Available' | 'Pending Approval';
  experience: string;
  type: 'Internal' | 'External';
  workedDays?: number;
  skills?: string[];
}

export interface Department {
  id: string;
  name: string;
  manager: string;
  teams: number;
  parentId?: string;
}

export interface JobOpening {
  id: string;
  title: string;
  department: string;
  location: string;
  type: 'Full-time' | 'Contract' | 'Remote';
  status: 'Open' | 'Closed' | 'Draft' | 'Rejected' | 'Interviewing';
  applicants: number;
  postedDate: string;
}

export interface Candidate {
  id: string;
  name: string;
  role: string;
  experience: string;
  status: 'Applied' | 'Screening' | 'Interview' | 'Offer' | 'Hired' | 'Rejected';
  appliedDate: string;
  email: string;
}

export interface Folder {
  id: string;
  name: string;
  color: string;
}

export interface CompanySettings {
  name: string;
  logo?: string;
  email?: string;
  location?: string;
  phone?: string;
  corporateTaxRate?: number;
  vatTaxRate?: number;
}

export interface Document {
  id: string;
  name: string;
  type: 'PDF' | 'DOCX' | 'XLSX' | 'PPTX' | 'ZIP' | 'IMG' | 'CODE';
  size: string;
  lastModified: string;
  owner: string;
  isStarred?: boolean;
  folder?: string;
}

export interface BankDetail {
  id: string;
  entityId: string;
  entityType: 'Client' | 'Engineer' | 'Third-party';
  entityName: string;
  bankName: string;
  accountName: string;
  accountNumber: string;
  iban: string;
  swiftCode: string;
  routingNumber?: string;
  sortCode?: string;
  institutionNumber?: string;
  transitNumber?: string;
  bankAddress?: string;
  currency: string;
  createdAt: string;
}

interface AppContextType {
  projects: Project[];
  tasks: Task[];
  expenses: Expense[];
  clients: Client[];
  engineers: Engineer[];
  departments: Department[];
  jobs: JobOpening[];
  candidates: Candidate[];
  folders: Folder[];
  bankDetails: BankDetail[];
  currencies: { code: string; symbol: string }[];
  companySettings: CompanySettings;
  updateCompanySettings: (settings: Partial<CompanySettings>) => void;
  addProject: (project: Project) => Promise<number | null | void>;
  updateProject: (id: string, updates: Partial<Project>) => Promise<number | null | void>;
  deleteProject: (id: string) => Promise<number | null | void>;
  addTask: (task: Task) => Promise<number | null | void>;
  updateTask: (id: string, updates: Partial<Task>) => Promise<number | null | void>;
  deleteTask: (id: string) => Promise<number | null | void>;
  addExpense: (expense: Expense) => Promise<number | null | void>;
  updateExpense: (id: string, updates: Partial<Expense>) => Promise<number | null | void>;
  deleteExpense: (id: string) => Promise<number | null | void>;
  addClient: (client: Client) => Promise<number | null | void>;
  updateClient: (id: string, updates: Partial<Client>) => Promise<number | null | void>;
  deleteClient: (id: string) => Promise<number | null | void>;
  addEngineer: (engineer: Engineer) => Promise<number | null | void>;
  updateEngineer: (id: string, updates: Partial<Engineer>) => Promise<number | null | void>;
  deleteEngineer: (id: string) => Promise<number | null | void>;
  addDepartment: (dept: Department) => Promise<number | null | void>;
  updateDepartment: (id: string, updates: Partial<Department>) => Promise<number | null | void>;
  deleteDepartment: (id: string) => Promise<number | null | void>;
  addJob: (job: JobOpening) => Promise<number | null | void>;
  updateJob: (id: string, updates: Partial<JobOpening>) => Promise<number | null | void>;
  deleteJob: (id: string) => Promise<number | null | void>;
  addCandidate: (candidate: Candidate) => Promise<number | null | void>;
  updateCandidate: (id: string, updates: Partial<Candidate>) => Promise<number | null | void>;
  deleteCandidate: (id: string) => Promise<number | null | void>;
  addDocument: (doc: Document) => Promise<number | null | void>;
  updateDocument: (id: string, updates: Partial<Document>) => Promise<number | null | void>;
  deleteDocument: (id: string) => Promise<number | null | void>;
  addFolder: (folder: Folder) => Promise<number | null | void>;
  deleteFolder: (id: string) => Promise<number | null | void>;
  addBankDetail: (detail: BankDetail) => Promise<number | null | void>;
  updateBankDetail: (id: string, updates: Partial<BankDetail>) => Promise<number | null | void>;
  deleteBankDetail: (id: string) => Promise<number | null | void>;
  addCurrency: (code: string, symbol: string) => Promise<number | null | void>;
  deleteCurrency: (code: string) => Promise<number | null | void>;
  syncEngineersFromProjects: () => Promise<number>;
}

const AppContext = createContext<AppContextType | undefined>(undefined);

const defaultCompanySettings: CompanySettings = {
  name: 'MA IT TECH',
  email: 'support@ma-it-tech.com',
  location: 'Dubai, UAE',
  phone: '+971 4 123 4567',
  corporateTaxRate: 25,
  vatTaxRate: 20
};

export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const { user, loading: authLoading } = useAuth();
  const [projects, setProjects] = useState<Project[]>([]);
  const [tasks, setTasks] = useState<Task[]>([]);
  const [expenses, setExpenses] = useState<Expense[]>([]);
  const [clients, setClients] = useState<Client[]>([]);
  const [engineers, setEngineers] = useState<Engineer[]>([]);
  const [departments, setDepartments] = useState<Department[]>([]);
  const [jobs, setJobs] = useState<JobOpening[]>([]);
  const [candidates, setCandidates] = useState<Candidate[]>([]);
  const [documents, setDocuments] = useState<Document[]>([]);
  const [folders, setFolders] = useState<Folder[]>([]);
  const [bankDetails, setBankDetails] = useState<BankDetail[]>([]);
  const [currencies, setCurrencies] = useState<{ code: string; symbol: string }[]>([]);
  const [companySettings, setCompanySettings] = useState<CompanySettings>(defaultCompanySettings);

  const lastSyncTime = useRef<number>(0);
  const isSyncing = useRef<boolean>(false);
  const pendingSyncs = useRef<Set<string>>(new Set());

  const loadData = useCallback(async (force = false, targetKey?: string) => {
    if (authLoading) return;
    
    // Queue synchronization if already in progress
    if (isSyncing.current) {
      pendingSyncs.current.add(targetKey || 'all');
      return;
    }

    if (!user) {
      setProjects([]);
      setTasks([]);
      setExpenses([]);
      setClients([]);
      setEngineers([]);
      setDepartments([]);
      setJobs([]);
      setCandidates([]);
      setDocuments([]);
      setFolders([]);
      setBankDetails([]);
      lastSyncTime.current = 0;
      return;
    }

    isSyncing.current = true;
    try {
      // Quick check for updates with cache buster
      const healthRes = await fetch(`/api/health?t=${Date.now()}`, {
        headers: { 
          'Cache-Control': 'no-cache', 
          'Pragma': 'no-cache',
          'Accept': 'application/json'
        },
        credentials: 'include'
      });
      
      if (!healthRes.ok) return;

      const contentType = healthRes.headers.get('content-type');
      if (!contentType || !contentType.includes('application/json')) return;

      const health = await healthRes.json();
      
      if (!force && health.lastChange <= lastSyncTime.current) return;

      if (targetKey) {
        console.log(`[AppContext] Syncing targeted key: ${targetKey}`);
        const normalizedKey = targetKey.toLowerCase();
        
        switch (normalizedKey) {
          case 'projects':
            setProjects(await storage.getProjects());
            break;
          case 'tasks':
            setTasks(await storage.getTasks());
            break;
          case 'expenses':
            setExpenses(await storage.getExpenses());
            break;
          case 'clients':
            setClients(await storage.getClients());
            break;
          case 'engineers':
            setEngineers(await storage.getEngineers());
            break;
          case 'departments':
            setDepartments(await storage.get('departments', []));
            break;
          case 'jobs':
            setJobs(await storage.get('jobs', []));
            break;
          case 'candidates':
            setCandidates(await storage.get('candidates', []));
            break;
          case 'documents':
            setDocuments(await storage.get('documents', []));
            break;
          case 'folders':
            setFolders(await storage.get('folders', []));
            break;
          case 'companysettings':
            setCompanySettings(await storage.get('companySettings', defaultCompanySettings));
            break;
          case 'bankdetails':
            setBankDetails(await storage.get('bankDetails', []));
            break;
          case 'currencies':
            setCurrencies(await storage.get('currencies', []));
            break;
          default:
            console.warn(`[AppContext] Unrecognized target key for sync: ${targetKey}`);
        }
      } else {
        console.log('[AppContext] Syncing all data with server...');
        const [p, t, e, c, eng, d, j, cand, docs, f, cs, bd, curr] = await Promise.all([
          storage.getProjects(),
          storage.getTasks(),
          storage.getExpenses(),
          storage.getClients(),
          storage.getEngineers(),
          storage.get('departments', []),
          storage.get('jobs', []),
          storage.get('candidates', []),
          storage.get('documents', []),
          storage.get('folders', [
            { id: '1', name: 'Projects', color: 'text-blue-500' },
            { id: '2', name: 'Human Resources', color: 'text-purple-500' },
            { id: '3', name: 'Finance', color: 'text-green-500' },
            { id: '4', name: 'Legal', color: 'text-red-500' },
          ]),
          storage.get('companySettings', defaultCompanySettings),
          storage.get('bankDetails', []),
          storage.get('currencies', [
            { code: 'USD', symbol: '$' },
            { code: 'EUR', symbol: '€' },
            { code: 'GBP', symbol: '£' },
            { code: 'CAD', symbol: 'C$' }
          ])
        ]);

        console.log('[AppContext] All data synced');
        
        setProjects(p || []);
        setTasks(t || []);
        setExpenses(e || []);
        setClients(c || []);
        setEngineers(eng || []);
        setDepartments(d || []);
        setJobs(j || []);
        setCandidates(cand || []);
        setDocuments(docs || []);
        setFolders(f || []);
        setCompanySettings(prev => {
          const next = { ...defaultCompanySettings, ...cs };
          if (JSON.stringify(prev) === JSON.stringify(next)) return prev;
          return next;
        });
        setBankDetails(bd || []);
        setCurrencies(curr || []);
      }
      
      lastSyncTime.current = health.lastChange || Date.now();
    } catch (err) {
      console.error('[AppContext] Failed to sync data:', err);
    } finally {
      isSyncing.current = false;
      // Handle pending sync requests
      if (pendingSyncs.current.size > 0) {
        const nextSyncs = Array.from(pendingSyncs.current);
        pendingSyncs.current.clear();
        const nextKey = nextSyncs.includes('all') ? undefined : nextSyncs[nextSyncs.length - 1];
        console.log(`[AppContext] Executing queued sync for: ${nextKey || 'all'}`);
        setTimeout(() => loadData(false, nextKey), 100);
      }
    }
  }, [authLoading, user?.uid]);

  const withSyncLock = async (fn: () => Promise<number | null | void>) => {
    if (isSyncing.current) {
      console.warn('[AppContext] Sync already in progress, blocking action');
      throw new Error('SYSTEM_BUSY');
    }
    
    isSyncing.current = true;
    try {
      const serverChangeTime = await fn();
      
      // Use server provided time if available, otherwise fallback to now
      lastSyncTime.current = typeof serverChangeTime === 'number' ? serverChangeTime : Date.now();
      return serverChangeTime;
    } catch (error: any) {
      console.error('[AppContext] Error during data operation:', error);
      
      let message = "An error occurred while saving your changes.";
      if (error.message === 'SYSTEM_BUSY') {
        message = "System is busy. Please wait a moment.";
      } else if (error.message === 'SERVER_TIMEOUT') {
        message = "Server timed out. Please check your connection.";
      } else if (error.message) {
        message = error.message;
      }
      
      toast.error(message, { duration: 5000 });
      throw error; // Re-throw so components know it failed
    } finally {
      // Keep locked for a very short duration to allow backend to finish writing to disk
      setTimeout(() => { isSyncing.current = false; }, 300);
    }
  };

  // Load data from Server
  useEffect(() => {
    // Initial load
    loadData(true);
  }, [loadData]);

  // Replacement for Socket.io: Periodic polling for data changes
  useEffect(() => {
    if (!user) return;

    console.log('[AppContext] Initializing polling for data updates...');
    const pollInterval = setInterval(() => {
      loadData(false);
    }, 10000); // Poll every 10 seconds

    return () => {
      clearInterval(pollInterval);
    };
  }, [user, loadData]);

  const addProject = useCallback(async (project: Project) => {
    await withSyncLock(async () => {
      const newProjects = [...projects, project];
      setProjects(newProjects);
      const changeId = await storage.setProjects(newProjects);
      
      // Auto-create a task for this project
      const taskId = `TSK-${project.id.replace('PRJ', '') || Math.random().toString(36).substr(2, 5).toUpperCase()}`;
      const newTask: Task = {
        id: taskId,
        title: `${project.name} Main Task`,
        project: project.name,
        projectId: project.id,
        assignDate: new Date().toISOString().split('T')[0],
        status: (project.status === 'Completed' || project.status === 'Accepted' || project.status === 'Rejected') ? 'Completed' : 
                (project.status === 'In Progress' || project.status === 'Work In Progress' || project.status === 'Active') ? 'In Progress' : 'To Do',
        dueDate: project.deadline,
        assignee: project.assignedTo || 'Unassigned'
      };
      
      if (project.completedDate) {
        newTask.completedDate = project.completedDate;
      }
      
      const newTasks = [...tasks, newTask];
      setTasks(newTasks);
      await storage.setTasks(newTasks);
      return changeId;
    });
  }, [projects, tasks]);

  const updateProject = useCallback(async (id: string, updates: Partial<Project>) => {
    await withSyncLock(async () => {
      const newProjects = projects.map(p => p.id === id ? { ...p, ...updates } : p);
      setProjects(newProjects);
      const changeId = await storage.setProjects(newProjects);
      
      // Update associated tasks if project name, status, or completed date changes
      if (updates.name || updates.status || updates.completedDate) {
        const newTasks = tasks.map(task => {
          if (task.projectId === id) {
            let updatedTask: Partial<Task> = {};
            if (updates.name) updatedTask.project = updates.name;
            if (updates.completedDate) updatedTask.completedDate = updates.completedDate;
            
            if (updates.status) {
              const mapProjectStatusToTaskStatus = (status: string): 'To Do' | 'In Progress' | 'Completed' => {
                switch (status) {
                  case 'Work In Progress':
                  case 'Active':
                  case 'In Progress': return 'In Progress';
                  case 'Completed':
                  case 'Accepted':
                  case 'Rejected': return 'Completed';
                  default: return 'To Do';
                }
              };
              updatedTask.status = mapProjectStatusToTaskStatus(updates.status);
              
              if (updatedTask.status === 'Completed' && !updatedTask.completedDate) {
                updatedTask.completedDate = updates.completedDate || new Date().toISOString().split('T')[0];
              }
            }
            return { ...task, ...updatedTask };
          }
          return task;
        });
        setTasks(newTasks);
        await storage.setTasks(newTasks);
      }
      return changeId;
    });
  }, [projects, tasks]);

  const deleteProject = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newProjects = projects.filter(p => p.id !== id);
      setProjects(newProjects);
      const changeId = await storage.setProjects(newProjects);
      
      const newTasks = tasks.filter(t => t.projectId !== id);
      setTasks(newTasks);
      await storage.setTasks(newTasks);
      return changeId;
    });
  }, [projects, tasks]);

  const addTask = useCallback(async (task: Task) => {
    await withSyncLock(async () => {
      const newTasks = [...tasks, task];
      setTasks(newTasks);
      return await storage.setTasks(newTasks);
    });
  }, [tasks]);

  const updateTask = useCallback(async (id: string, updates: Partial<Task>) => {
    await withSyncLock(async () => {
      const newTasks = tasks.map(t => t.id === id ? { ...t, ...updates } : t);
      setTasks(newTasks);
      return await storage.setTasks(newTasks);
    });
  }, [tasks]);

  const deleteTask = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newTasks = tasks.filter(t => t.id !== id);
      setTasks(newTasks);
      return await storage.setTasks(newTasks);
    });
  }, [tasks]);

  const addExpense = useCallback(async (expense: Expense) => {
    await withSyncLock(async () => {
      const newExpenses = [...expenses, expense];
      setExpenses(newExpenses);
      return await storage.setExpenses(newExpenses);
    });
  }, [expenses]);

  const updateExpense = useCallback(async (id: string, updates: Partial<Expense>) => {
    await withSyncLock(async () => {
      const newExpenses = expenses.map(e => e.id === id ? { ...e, ...updates } : e);
      setExpenses(newExpenses);
      return await storage.setExpenses(newExpenses);
    });
  }, [expenses]);

  const deleteExpense = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newExpenses = expenses.filter(e => e.id !== id);
      setExpenses(newExpenses);
      return await storage.setExpenses(newExpenses);
    });
  }, [expenses]);

  const addClient = useCallback(async (client: Client) => {
    await withSyncLock(async () => {
      const newClients = [...clients, client];
      setClients(newClients);
      return await storage.setClients(newClients);
    });
  }, [clients]);

  const updateClient = useCallback(async (id: string, updates: Partial<Client>) => {
    await withSyncLock(async () => {
      const newClients = clients.map(c => c.id === id ? { ...c, ...updates } : c);
      setClients(newClients);
      return await storage.setClients(newClients);
    });
  }, [clients]);

  const deleteClient = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newClients = clients.filter(c => c.id !== id);
      setClients(newClients);
      return await storage.setClients(newClients);
    });
  }, [clients]);

  const addEngineer = useCallback(async (engineer: Engineer) => {
    await withSyncLock(async () => {
      const updated = [...engineers, engineer];
      setEngineers(updated);
      return await storage.setEngineers(updated);
    });
  }, [engineers]);

  const updateEngineer = useCallback(async (id: string, updates: Partial<Engineer>) => {
    await withSyncLock(async () => {
      const newEngineers = engineers.map(e => e.id === id ? { ...e, ...updates } : e);
      setEngineers(newEngineers);
      return await storage.setEngineers(newEngineers);
    });
  }, [engineers]);

  const deleteEngineer = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newEngineers = engineers.filter(e => e.id !== id);
      setEngineers(newEngineers);
      return await storage.setEngineers(newEngineers);
    });
  }, [engineers]);

  const addDepartment = useCallback(async (dept: Department) => {
    await withSyncLock(async () => {
      const newDepts = [...departments, dept];
      setDepartments(newDepts);
      return await storage.set('departments', newDepts);
    });
  }, [departments]);

  const updateDepartment = useCallback(async (id: string, updates: Partial<Department>) => {
    await withSyncLock(async () => {
      const newDepts = departments.map(d => d.id === id ? { ...d, ...updates } : d);
      setDepartments(newDepts);
      return await storage.set('departments', newDepts);
    });
  }, [departments]);

  const deleteDepartment = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newDepts = departments.filter(d => d.id !== id);
      setDepartments(newDepts);
      return await storage.set('departments', newDepts);
    });
  }, [departments]);

  const addJob = useCallback(async (job: JobOpening) => {
    await withSyncLock(async () => {
      const newJobs = [...jobs, job];
      setJobs(newJobs);
      return await storage.set('jobs', newJobs);
    });
  }, [jobs]);

  const updateJob = useCallback(async (id: string, updates: Partial<JobOpening>) => {
    await withSyncLock(async () => {
      const newJobs = jobs.map(j => j.id === id ? { ...j, ...updates } : j);
      setJobs(newJobs);
      return await storage.set('jobs', newJobs);
    });
  }, [jobs]);

  const deleteJob = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newJobs = jobs.filter(j => j.id !== id);
      setJobs(newJobs);
      return await storage.set('jobs', newJobs);
    });
  }, [jobs]);

  const addCandidate = useCallback(async (candidate: Candidate) => {
    await withSyncLock(async () => {
      const newCandidates = [...candidates, candidate];
      setCandidates(newCandidates);
      return await storage.set('candidates', newCandidates);
    });
  }, [candidates]);

  const updateCandidateStatus = useCallback(async (id: string, updates: Partial<Candidate>) => {
    await withSyncLock(async () => {
      const newCandidates = candidates.map(c => c.id === id ? { ...c, ...updates } : c);
      setCandidates(newCandidates);
      return await storage.set('candidates', newCandidates);
    });
  }, [candidates]);

  const deleteCandidate = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newCandidates = candidates.filter(c => c.id !== id);
      setCandidates(newCandidates);
      return await storage.set('candidates', newCandidates);
    });
  }, [candidates]);

  const addDocument = useCallback(async (document: Document) => {
    await withSyncLock(async () => {
      const newDocs = [...documents, document];
      setDocuments(newDocs);
      return await storage.set('documents', newDocs);
    });
  }, [documents]);

  const updateDocument = useCallback(async (id: string, updates: Partial<Document>) => {
    await withSyncLock(async () => {
      const newDocs = documents.map(d => d.id === id ? { ...d, ...updates } : d);
      setDocuments(newDocs);
      return await storage.set('documents', newDocs);
    });
  }, [documents]);

  const deleteDocument = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newDocs = documents.filter(d => d.id !== id);
      setDocuments(newDocs);
      return await storage.set('documents', newDocs);
    });
  }, [documents]);

  const addFolder = useCallback(async (folder: Folder) => {
    await withSyncLock(async () => {
      const newFolders = [...folders, folder];
      setFolders(newFolders);
      return await storage.set('folders', newFolders);
    });
  }, [folders]);

  const deleteFolder = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newFolders = folders.filter(f => f.id !== id);
      setFolders(newFolders);
      let res = await storage.set('folders', newFolders);
      
      // Also remove folder association from documents
      const folderToDelete = folders.find(f => f.id === id);
      if (folderToDelete) {
        const newDocs = documents.map(doc => 
          doc.folder === folderToDelete.name ? { ...doc, folder: undefined } : doc
        );
        setDocuments(newDocs);
        res = await storage.set('documents', newDocs);
      }
      return res;
    });
  }, [folders, documents]);

  const addBankDetail = useCallback(async (detail: BankDetail) => {
    await withSyncLock(async () => {
      const newDetails = [...bankDetails, detail];
      setBankDetails(newDetails);
      return await storage.set('bankDetails', newDetails);
    });
  }, [bankDetails]);

  const updateBankDetail = useCallback(async (id: string, updates: Partial<BankDetail>) => {
    await withSyncLock(async () => {
      const newDetails = bankDetails.map(bd => bd.id === id ? { ...bd, ...updates } : bd);
      setBankDetails(newDetails);
      return await storage.set('bankDetails', newDetails);
    });
  }, [bankDetails]);

  const deleteBankDetail = useCallback(async (id: string) => {
    await withSyncLock(async () => {
      const newDetails = bankDetails.filter(bd => bd.id !== id);
      setBankDetails(newDetails);
      return await storage.set('bankDetails', newDetails);
    });
  }, [bankDetails]);

  const addCurrency = useCallback(async (code: string, symbol: string) => {
    await withSyncLock(async () => {
      const newCurrencies = [...currencies, { code, symbol }];
      setCurrencies(newCurrencies);
      return await storage.set('currencies', newCurrencies);
    });
  }, [currencies]);

  const deleteCurrency = useCallback(async (code: string) => {
    await withSyncLock(async () => {
      const newCurrencies = currencies.filter(c => c.code !== code);
      setCurrencies(newCurrencies);
      return await storage.set('currencies', newCurrencies);
    });
  }, [currencies]);

  const updateCompanySettings = useCallback(async (updates: Partial<CompanySettings>) => {
    await withSyncLock(async () => {
      const newSettings = { ...companySettings, ...updates };
      setCompanySettings(newSettings);
      return await storage.set('companySettings', newSettings);
    });
  }, [companySettings]);

  const syncEngineersFromProjects = useCallback(async () => {
    const engineerMap = new Map<string, any>();
    
    projects.forEach(project => {
      if (project.assignedTo) {
        const key = project.assignedTo.toLowerCase().trim();
        if (!engineerMap.has(key)) {
          const role = project.assignedRole || 'Engineer';
          const roleLower = role.toLowerCase();
          const type = roleLower.includes('external') ? 'External' : (roleLower.includes('internal') ? 'Internal' : 'External');
          
          engineerMap.set(key, {
            name: project.assignedTo,
            role: role,
            email: project.assignedEmail || project.email || `${project.assignedTo.toLowerCase().replace(/\s+/g, '.')}@company.com`,
            phone: project.assignedContactNumber || project.contactNumber || 'N/A',
            status: project.status === 'Completed' ? 'Available' : 'Active',
            type: type,
            experience: 'Synced from Project',
            department: 'Technical'
          });
        }
      }
    });

    let addedCount = 0;
    const currentEngineers = [...engineers];
    const newEngineersList = [...engineers];

    for (const [key, data] of engineerMap.entries()) {
      const exists = currentEngineers.find(e => e.name.toLowerCase().trim() === key);
      if (!exists) {
        const newId = `ENG-SYNC-${Math.random().toString(36).substr(2, 5).toUpperCase()}`;
        newEngineersList.push({ ...data, id: newId } as Engineer);
        addedCount++;
      }
    }

    if (addedCount > 0) {
      setEngineers(newEngineersList);
      await storage.setEngineers(newEngineersList);
    }

    return addedCount;
  }, [projects, engineers]);

  const value = useMemo(() => ({ 
    projects, 
    tasks, 
    expenses,
    clients,
    engineers,
    departments,
    jobs,
    candidates,
    documents,
    folders,
    bankDetails,
    currencies,
    companySettings,
    addProject, 
    updateProject, 
    deleteProject, 
    addTask, 
    updateTask,
    deleteTask,
    addExpense,
    updateExpense,
    deleteExpense,
    addClient,
    updateClient,
    deleteClient,
    addEngineer,
    updateEngineer,
    deleteEngineer,
    addDepartment,
    updateDepartment,
    deleteDepartment,
    addJob,
    updateJob,
    deleteJob,
    addCandidate,
    updateCandidate: updateCandidateStatus,
    deleteCandidate,
    addDocument,
    updateDocument,
    deleteDocument,
    addFolder,
    deleteFolder,
    addBankDetail,
    updateBankDetail,
    deleteBankDetail,
    addCurrency,
    deleteCurrency,
    updateCompanySettings,
    syncEngineersFromProjects
  }), [projects, tasks, expenses, clients, engineers, departments, jobs, candidates, documents, folders, bankDetails, currencies, companySettings, addProject, updateProject, deleteProject, addTask, updateTask, deleteTask, addExpense, updateExpense, deleteExpense, addClient, updateClient, deleteClient, addEngineer, updateEngineer, deleteEngineer, addDepartment, updateDepartment, deleteDepartment, addJob, updateJob, deleteJob, addCandidate, updateCandidateStatus, deleteCandidate, addDocument, updateDocument, deleteDocument, addFolder, deleteFolder, addBankDetail, updateBankDetail, deleteBankDetail, addCurrency, deleteCurrency, updateCompanySettings, syncEngineersFromProjects]);

  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );
};

export const useApp = () => {
  const context = useContext(AppContext);
  if (context === undefined) {
    throw new Error('useApp must be used within an AppProvider');
  }
  return context;
};
