'use client';
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { LeaveRequest, LEAVE_POLICIES } from '../app/hr/leave/leaveData';

interface LeaveStoreContextType {
  requests: LeaveRequest[];
  setRequests: (r: LeaveRequest[]) => void;
  updateRequests: (updater: (prev: LeaveRequest[]) => LeaveRequest[]) => void;
  isLoading: boolean;
  refreshRequests: () => Promise<void>;
  getBalance: (type: string, isIntern: boolean) => { entitlement: number; taken: number; remaining: number };
  getMyBalances: (employeeId: string, isIntern: boolean) => Array<{ type: string; entitlement: number; taken: number; remaining: number }>;
  getUserRequests: (employeeId: string) => LeaveRequest[];
}

const LeaveStoreContext = createContext<LeaveStoreContextType | null>(null);

function mapDbToLeaveRequest(row: any): LeaveRequest {
  return {
    id: row.id,
    employeeId: row.employeeId,
    employee: row.employeeName,
    dept: row.dept,
    position: row.position,
    employeeType: (row.employeeType as 'Employee' | 'Intern') || 'Employee',
    gender: (row.gender as 'Male' | 'Female') || 'Male',
    type: row.type as 'Annual' | 'Sick' | 'Maternity' | 'Paternity' | 'Bereavement' | 'Unpaid',
    startDate: row.startDate,
    endDate: row.endDate,
    days: row.days,
    reason: row.reason || undefined,
    status: row.status as LeaveRequest['status'],
    submittedOn: row.submittedOn,
    dutyDelegate: row.dutyDelegate || undefined,
    hasDocument: row.hasDocument || false,
    hodApprovedBy: row.hodApprovedBy || undefined,
    hodApprovedOn: row.hodApprovedOn || undefined,
    hosApprovedBy: row.hosApprovedBy || undefined,
    hosApprovedOn: row.hosApprovedOn || undefined,
    hosComment: row.hosComment || undefined,
    approvedBy: row.approvedBy || undefined,
    approvedOn: row.approvedOn || undefined,
    rejectionReason: row.rejectionReason || undefined,
    rejectedBy: row.rejectedBy || undefined,
    rejectedStage: row.rejectedStage || undefined,
    reviewRequested: row.reviewRequested || false,
    reviewComment: row.reviewComment || undefined,
    reviewNewStart: row.reviewNewStart || undefined,
    reviewNewEnd: row.reviewNewEnd || undefined,
    reviewBy: row.reviewBy || undefined,
    reviewDate: row.reviewDate || undefined,
  };
}

function mapLeaveRequestToDb(req: LeaveRequest): any {
  return {
    id: req.id,
    employeeId: req.employeeId,
    employeeName: req.employee,
    dept: req.dept,
    position: req.position,
    employeeType: req.employeeType,
    gender: req.gender,
    type: req.type,
    startDate: req.startDate,
    endDate: req.endDate,
    days: req.days,
    reason: req.reason || null,
    status: req.status,
    submittedOn: req.submittedOn,
    dutyDelegate: req.dutyDelegate || null,
    hasDocument: req.hasDocument || false,
    hodApprovedBy: req.hodApprovedBy || null,
    hodApprovedOn: req.hodApprovedOn || null,
    hosApprovedBy: req.hosApprovedBy || null,
    hosApprovedOn: req.hosApprovedOn || null,
    hosComment: req.hosComment || null,
    approvedBy: req.approvedBy || null,
    approvedOn: req.approvedOn || null,
    rejectionReason: req.rejectionReason || null,
    rejectedBy: req.rejectedBy || null,
    rejectedStage: req.rejectedStage || null,
    reviewRequested: req.reviewRequested || false,
    reviewComment: req.reviewComment || null,
    reviewNewStart: req.reviewNewStart || null,
    reviewNewEnd: req.reviewNewEnd || null,
    reviewBy: req.reviewBy || null,
    reviewDate: req.reviewDate || null,
  };
}

// Helper function to get auth token from localStorage
function getAuthToken(): string | null {
  try {
    const stored = localStorage.getItem('auth_user');
    if (stored) {
      const user = JSON.parse(stored);
      return user.token || null;
    }
  } catch (error) {
    console.error('Error getting auth token:', error);
  }
  return null;
}

// Helper function to get current user from localStorage
function getCurrentUser(): any {
  try {
    const stored = localStorage.getItem('auth_user');
    if (stored) {
      return JSON.parse(stored);
    }
  } catch (error) {
    console.error('Error getting current user:', error);
  }
  return null;
}

export function LeaveStoreProvider({ children }: { children: ReactNode }) {
  const [requests, setRequestsState] = useState<LeaveRequest[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [currentUser, setCurrentUser] = useState<any>(null);

  // Load current user on mount
  useEffect(() => {
    const user = getCurrentUser();
    setCurrentUser(user);
  }, []);

  const getFetchUrl = () => {
    const user = currentUser || getCurrentUser();
    if (!user) return '/api/leave';
    
    const userRole = user.role?.toLowerCase();
    const employeeId = user.employeeId || user.id;
    
    // For employees and interns - get only their own requests
    if (userRole === 'employee' || userRole === 'intern' || user.isIntern) {
      if (employeeId) {
        return `/api/leave?employeeId=${encodeURIComponent(employeeId)}`;
      }
    }
    
    // For HOD - get requests from their department
    if (userRole === 'hod' && user.dept) {
      return `/api/leave?dept=${encodeURIComponent(user.dept)}`;
    }
    
    // For HOS - get all HOD approved requests
    if (userRole === 'hos') {
      return `/api/leave?status=HOD Approved`;
    }
    
    // For HR - get all HOS approved requests
    if (userRole === 'hr') {
      return `/api/leave?status=HOS Approved`;
    }
    
    // For admin - get all requests
    if (userRole === 'admin') {
      return '/api/leave';
    }
    
    // Default - try to filter by employeeId
    if (employeeId) {
      return `/api/leave?employeeId=${encodeURIComponent(employeeId)}`;
    }
    
    return '/api/leave';
  };

  const refreshRequests = async () => {
    try {
      setIsLoading(true);
      const url = getFetchUrl();
      console.log('Fetching leave requests from:', url);
      
      const token = getAuthToken();
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      };
      
      if (token) {
        headers['Authorization'] = `Bearer ${token}`;
      }
      
      const response = await fetch(url, {
        headers,
        credentials: 'include'
      });
      
      if (response.status === 401) {
        console.error('Unauthorized - user may not be logged in');
        setRequestsState([]);
        return;
      }
      
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        console.error('API Error:', errorData);
        throw new Error(errorData.error || 'Failed to fetch leave requests');
      }
      
      const data = await response.json();
      setRequestsState(data.map(mapDbToLeaveRequest));
    } catch (error) {
      console.error('Error fetching leave requests:', error);
      setRequestsState([]);
    } finally {
      setIsLoading(false);
    }
  };

  useEffect(() => {
    if (currentUser) {
      refreshRequests();
    }
  }, [currentUser]);

  const setRequests = (r: LeaveRequest[]) => setRequestsState(r);

  const updateRequests = (updater: (prev: LeaveRequest[]) => LeaveRequest[]) => {
    setRequestsState(prev => {
      const next = updater(prev);
      const changed = next.find(r => !prev.some(p => p.id === r.id && p.status === r.status));
      
      if (changed) {
        const dbRecord = mapLeaveRequestToDb(changed);
        const isExisting = prev.some(p => p.id === changed.id);
        
        const url = isExisting ? `/api/leave/${changed.id}` : '/api/leave';
        const method = isExisting ? 'PUT' : 'POST';
        
        const token = getAuthToken();
        const headers: Record<string, string> = {
          'Content-Type': 'application/json',
        };
        
        if (token) {
          headers['Authorization'] = `Bearer ${token}`;
        }
        
        fetch(url, {
          method,
          headers,
          credentials: 'include',
          body: JSON.stringify(dbRecord),
        })
          .then(async (res) => {
            if (res.ok) {
              await refreshRequests();
            } else {
              const errorData = await res.json().catch(() => ({}));
              console.error('API Error:', errorData);
            }
          })
          .catch(console.error);
      }
      return next;
    });
  };

  // Calculate balance for a specific leave type
  const getBalance = (type: string, isIntern: boolean) => {
    const policy = LEAVE_POLICIES.find(p => p.type === type);
    if (!policy) {
      return { entitlement: 0, taken: 0, remaining: 0 };
    }

    const approvedRequests = requests.filter(
      r => r.type === type && 
           (r.status === 'Approved' || r.status === 'HOS Approved')
    );
    
    const taken = approvedRequests.reduce((sum, r) => sum + (r.days || 0), 0);
    const entitlement = isIntern ? policy.internEntitlement : policy.entitlement;
    const remaining = Math.max(0, entitlement - taken);
    
    return { entitlement, taken, remaining };
  };

  // Get all balances for an employee
  const getMyBalances = (employeeId: string, isIntern: boolean) => {
    const employeeRequests = requests.filter(r => r.employeeId === employeeId);
    const leaveTypes = ['Annual', 'Sick', 'Maternity', 'Paternity', 'Bereavement', 'Unpaid'];
    
    return leaveTypes.map(type => {
      const policy = LEAVE_POLICIES.find(p => p.type === type);
      if (!policy) return { type, entitlement: 0, taken: 0, remaining: 0 };
      
      const approvedRequests = employeeRequests.filter(
        r => r.type === type && 
             (r.status === 'Approved' || r.status === 'HOS Approved')
      );
      
      const taken = approvedRequests.reduce((sum, r) => sum + (r.days || 0), 0);
      const entitlement = isIntern ? policy.internEntitlement : policy.entitlement;
      const remaining = Math.max(0, entitlement - taken);
      
      return { type, entitlement, taken, remaining };
    });
  };

  // Get only the current user's requests
  const getUserRequests = (employeeId: string) => {
    return requests.filter(r => r.employeeId === employeeId);
  };

  return (
    <LeaveStoreContext.Provider 
      value={{ 
        requests, 
        setRequests, 
        updateRequests, 
        isLoading, 
        refreshRequests,
        getBalance,
        getMyBalances,
        getUserRequests
      }}
    >
      {children}
    </LeaveStoreContext.Provider>
  );
}

export function useLeaveStore() {
  const ctx = useContext(LeaveStoreContext);
  if (!ctx) throw new Error('useLeaveStore must be used within LeaveStoreProvider');
  return ctx;
}