
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { createRoot } from 'react-dom/client';
import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';

// --- API UTILITY ---
const API_BASE_URL = 'api';

async function apiCall<T>(endpoint: string, method: 'GET' | 'POST' = 'POST', body?: any): Promise<T> {
    const options: RequestInit = {
        method,
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
        },
    };

    if (body && method !== 'GET') {
        options.body = JSON.stringify(body);
    }

    const response = await fetch(`${API_BASE_URL}/${endpoint}`, options);

    if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`API call failed for ${method} ${API_BASE_URL}/${endpoint}:\n${response.status} ${response.statusText}\n${errorText}`);
    }

    if (response.status === 204) { // Handle No Content success response
        return null as T;
    }

    return response.json();
}


// --- TYPES & MOCKS ---
type Page = 'dashboard' | 'products' | 'sales' | 'purchases' | 'orders' | 'payments' | 'expenses' | 'contacts' | 'returns' | 'damages' | 'reports' | 'users' | 'audit';
type Theme = 'light' | 'dark';
type Role = 'Admin' | 'Manager' | 'Staff';

type User = {
  id: number;
  name: string;
  email: string;
  role: Role;
};

type Product = {
  id: number;
  sku: string;
  name: string;
  imageUrl?: string;
  description?: string;
  price: number;
  averageCost?: number;
  stock: number;
};

type Contact = {
  id: number;
  name: string;
  email: string;
  role: 'Customer' | 'Vendor';
  creditLimit?: number;
};

type SaleItem = {
  productId: number;
  name: string;
  quantity: number;
  price: number;
  total: number;
};

type Sale = {
  id: number;
  customerId: number;
  customerName: string;
  date: string;
  items: SaleItem[];
  totalAmount: number;
  amountPaid: number;
  balance: number;
  status: 'Paid' | 'Partially Paid' | 'Unpaid';
};

type PurchaseItem = {
    productId: number;
    name: string;
    quantity: number;
    cost: number;
    total: number;
};

type Purchase = {
    id: number;
    vendorId: number;
    vendorName: string;
    date: string;
    items: PurchaseItem[];
    totalAmount: number;
    amountPaid: number;
    balance: number;
    status: 'Paid' | 'Partially Paid' | 'Unpaid';
};

type Order = {
  id: number;
  customerId: number;
  customerName: string;
  date: string;
  items: SaleItem[];
  totalAmount: number;
  status: 'Received' | 'Processed' | 'Delivered';
};


type ExpenseCategory = {
    id: number;
    name: string;
};

type Expense = {
    id: number;
    date: string;
    description: string;
    categoryId: number;
    categoryName: string;
    amount: number;
};

type Payment = {
    id: number;
    date: string;
    type: 'Sale' | 'Purchase';
    transactionId: number;
    contactName: string;
    amount: number;
    method: 'Cash' | 'Bank Transfer' | 'Credit Card' | 'Mobile Wallet';
    reference: string;
};

type ReturnItem = {
    productId: number;
    name: string;
    quantity: number;
    price: number;
    total: number;
};

type Return = {
    id: number;
    date: string;
    saleId: number;
    customerName: string;
    items: ReturnItem[];
    totalValue: number;
};

type Damage = {
    id: number;
    date: string;
    productId: number;
    productName: string;
    quantity: number;
    reason: string;
};

type AuditLogEntry = {
    id: string;
    timestamp: string;
    userId: number;
    userName: string;
    action: string;
    details: string;
};

const navItems: { id: Page; label: string; icon: string }[] = [
  { id: 'dashboard', label: 'Dashboard', icon: 'dashboard' },
  { id: 'products', label: 'Products', icon: 'inventory_2' },
  { id: 'sales', label: 'Sales', icon: 'receipt_long' },
  { id: 'purchases', label: 'Purchases', icon: 'shopping_cart' },
  { id: 'orders', label: 'Orders', icon: 'list_alt' },
  { id: 'returns', label: 'Returns', icon: 'assignment_return' },
  { id: 'damages', label: 'Damaged Stock', icon: 'report' },
  { id: 'payments', label: 'Payments', icon: 'paid' },
  { id: 'expenses', label: 'Expenses', icon: 'wallet' },
  { id: 'contacts', label: 'Contacts', icon: 'contacts' },
  { id: 'reports', label: 'Reports', icon: 'analytics' },
  { id: 'users', label: 'Users', icon: 'group' },
  { id: 'audit', label: 'Audit Trail', icon: 'history' },
];

const permissions = {
    canViewPage: (role: Role, page: Page) => {
        if (role === 'Admin') return true;
        if (role === 'Manager') {
            return !['users', 'audit'].includes(page);
        }
        if (role === 'Staff') {
            const allowedPages: Page[] = ['dashboard', 'sales', 'purchases', 'orders', 'payments', 'expenses', 'contacts', 'returns', 'damages'];
            return allowedPages.includes(page);
        }
        return false;
    },
    canManageProducts: (role: Role) => {
        return role === 'Admin' || role === 'Manager';
    },
    canAddEditDeleteProducts: (role: Role) => {
        return role === 'Admin' || role === 'Manager';
    }
};

const formatCurrency = (amount: number) => {
    return `Rs. ${amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
};

const mockStats = [
  { title: "Total Revenue", value: formatCurrency(54320), change: "+5.2%", icon: "monitoring", changeType: "positive" },
  { title: "Today's Sales", value: formatCurrency(1890), change: "+12.1%", icon: "today", changeType: "positive" },
  { title: "Pending Orders", value: "24", change: "-2.5%", icon: "pending_actions", changeType: "negative" },
  { title: "New Customers", value: "12", change: "+8.0%", icon: "person_add", changeType: "positive" },
];

// --- UTILITIES ---
const downloadAsCsv = (filename: string, headers: string[], data: (string | number)[][]) => {
  const csvContent = [
    headers.join(','),
    ...data.map(row => row.map(field => `"${String(field).replace(/"/g, '""')}"`).join(','))
  ].join('\n');

  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
  const link = document.createElement('a');
  if (link.href) {
    URL.revokeObjectURL(link.href);
  }
  link.href = URL.createObjectURL(blob);
  link.download = `${filename}.csv`;
  link.style.visibility = 'hidden';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

const downloadAsPdf = (filename: string, title: string, headers: {header: string, dataKey: string}[], data: Record<string, any>[]) => {
  const doc = new jsPDF();
  doc.text(title, 14, 16);
  autoTable(doc, {
    head: [headers.map(h => h.header)],
    body: data.map(row => headers.map(h => row[h.dataKey])),
    startY: 22,
  });
  doc.save(`${filename}.pdf`);
};


// --- REUSABLE COMPONENTS ---
const Modal: React.FC<{
  isOpen: boolean;
  onClose: () => void;
  title: string;
  children: React.ReactNode;
  footer?: React.ReactNode;
  size?: 'sm' | 'md' | 'lg';
}> = ({ isOpen, onClose, title, children, footer, size = 'md' }) => {
  const [isRendered, setIsRendered] = useState(isOpen);
  const modalRef = useRef<HTMLDivElement>(null);
  const triggerElementRef = useRef<HTMLElement | null>(null);

  useEffect(() => {
    if (isOpen) {
      triggerElementRef.current = document.activeElement as HTMLElement;
      setIsRendered(true);
    }
  }, [isOpen]);

  const onAnimationEnd = () => {
    if (!isOpen) {
      setIsRendered(false);
      triggerElementRef.current?.focus();
    }
  };

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && isOpen) {
        onClose();
      }
      if (event.key === 'Tab' && isOpen && modalRef.current) {
        const focusableElements = modalRef.current.querySelectorAll<HTMLElement>(
          'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        );
        if (focusableElements.length === 0) return;
        
        const firstElement = focusableElements[0];
        const lastElement = focusableElements[focusableElements.length - 1];

        if (event.shiftKey) {
          if (document.activeElement === firstElement) {
            lastElement.focus();
            event.preventDefault();
          }
        } else {
          if (document.activeElement === lastElement) {
            firstElement.focus();
            event.preventDefault();
          }
        }
      }
    };

    document.addEventListener('keydown', handleKeyDown);

    if (isOpen && isRendered) {
      setTimeout(() => {
        modalRef.current?.querySelector<HTMLElement>(
          'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        )?.focus();
      }, 50);
    }

    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [isOpen, isRendered, onClose]);
  
  if (!isRendered) return null;

  return (
    <div 
      className={`modal-overlay ${isOpen ? 'open' : ''}`} 
      onClick={onClose} 
      onTransitionEnd={onAnimationEnd}
      role="dialog" 
      aria-modal="true" 
      aria-labelledby="modal-title"
    >
      <div ref={modalRef} className={`modal-content modal-${size}`} onClick={(e) => e.stopPropagation()}>
        <div className="modal-header">
          <h2 id="modal-title">{title}</h2>
          <button onClick={onClose} className="icon-button" aria-label="Close modal">
            <span className="material-symbols-outlined">close</span>
          </button>
        </div>
        <div className="modal-body">
          {children}
        </div>
        {footer && <div className="modal-footer">{footer}</div>}
      </div>
    </div>
  );
};

const ConfirmationModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onConfirm: () => void;
    title: string;
    message: string;
    isSaving?: boolean;
}> = ({ isOpen, onClose, onConfirm, title, message, isSaving = false }) => (
    <Modal
        isOpen={isOpen}
        onClose={onClose}
        title={title}
        size="sm"
        footer={<>
            <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
            <button className="button button-danger" onClick={onConfirm} disabled={isSaving}>
                {isSaving ? 'Confirming...' : 'Confirm'}
            </button>
        </>}
    >
        <p>{message}</p>
    </Modal>
);

const Pagination: React.FC<{
    currentPage: number;
    totalItems: number;
    itemsPerPage: number;
    onPageChange: (page: number) => void;
}> = ({ currentPage, totalItems, itemsPerPage, onPageChange }) => {
    const totalPages = Math.ceil(totalItems / itemsPerPage);
    if (totalPages <= 1) return null;

    const handlePageClick = (page: number) => {
        if (page >= 1 && page <= totalPages) {
            onPageChange(page);
        }
    };
    
    const pageNumbers = [];
    for (let i = 1; i <= totalPages; i++) {
        pageNumbers.push(i);
    }

    return (
        <div className="pagination">
            <button
                className="pagination-button"
                onClick={() => handlePageClick(currentPage - 1)}
                disabled={currentPage === 1}
            >
                &laquo; Prev
            </button>
            {pageNumbers.map(number => (
                <button
                    key={number}
                    className={`pagination-button ${currentPage === number ? 'active' : ''}`}
                    onClick={() => handlePageClick(number)}
                >
                    {number}
                </button>
            ))}
            <button
                className="pagination-button"
                onClick={() => handlePageClick(currentPage + 1)}
                disabled={currentPage === totalPages}
            >
                Next &raquo;
            </button>
        </div>
    );
};


// --- AI INSIGHTS COMPONENT ---
const AIInsights: React.FC = () => {
  const [prompt, setPrompt] = useState('');
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState('');

  const handleGenerate = async () => {
    if (!prompt.trim()) return;

    setLoading(true);
    setResult('');
    try {
      const businessContext = `
        You are a business analyst for Zargoona Wholesale Management.
        Here is a snapshot of our current business data:
        - Total Revenue: ${formatCurrency(54320)}
        - Sales Today: ${formatCurrency(1890)}
        - Top Selling Product: 'Product A' (500 units sold this month)
        - Slowest Selling Product: 'Product C' (20 units sold this month)
        - Pending Orders: 24
        - New Customers this month: 45
        
        Please provide a concise, actionable insight based on the user's question.
      `;

      const fullPrompt = `${businessContext}\n\nUser Question: "${prompt}"`;
      
      // Call our secure PHP backend script instead of the Gemini SDK directly
      const response = await apiCall<{ text: string }>('ai_handler.php', 'POST', { prompt: fullPrompt });
      
      setResult(response.text);

    } catch (error) {
      console.error("AI generation failed:", error);
      setResult("A server error occurred while generating the insight. Please ensure 'api/ai_handler.php' is configured correctly.");
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="ai-insights-container card">
      <h2 className="card-title">AI-Powered Insights</h2>
      <div className="ai-input-group">
        <input
          type="text"
          className="ai-input"
          placeholder="e.g., How can we increase sales for Product C?"
          value={prompt}
          onChange={(e) => setPrompt(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && handleGenerate()}
          disabled={loading}
          aria-label="Ask for an AI insight"
        />
        <button className="button" onClick={handleGenerate} disabled={loading || !prompt.trim()}>
          <span className="material-symbols-outlined">auto_awesome</span>
          <span>{loading ? 'Analyzing...' : 'Get Insight'}</span>
        </button>
      </div>
      {(loading || result) && (
        <div className={`ai-result ${loading ? 'loading' : ''}`}>
          {loading ? (
            <>
              <div className="spinner"></div>
              <span>Generating insight...</span>
            </>
          ) : (
            result
          )}
        </div>
      )}
    </div>
  );
};


// --- DASHBOARD PAGE ---
const DashboardPage: React.FC = () => {
  return (
    <>
      <h1 className="page-title">Dashboard</h1>
      <div className="stats-grid">
        {mockStats.map((stat) => (
          <div key={stat.title} className="card stat-card">
            <div className="stat-card-header">
              <span>{stat.title}</span>
              <span className={`material-symbols-outlined stat-card-icon`}>{stat.icon}</span>
            </div>
            <div className="stat-card-value">{stat.value}</div>
            <div className={`stat-card-change ${stat.changeType}`}>{stat.change} vs last period</div>
          </div>
        ))}
      </div>
      <AIInsights />
    </>
  );
};

// --- PROFILE MODAL ---
const ProfileModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    user: User;
    onSave: (user: Omit<User, 'id' | 'role' | 'email'>) => void;
}> = ({ isOpen, onClose, user, onSave }) => {
    const [name, setName] = useState(user.name);
    const [currentPassword, setCurrentPassword] = useState('');
    const [newPassword, setNewPassword] = useState('');
    const [confirmPassword, setConfirmPassword] = useState('');
    const [isSaving, setIsSaving] = useState(false);

    useEffect(() => {
        if (isOpen) {
            setName(user.name);
            setCurrentPassword('');
            setNewPassword('');
            setConfirmPassword('');
            setIsSaving(false);
        }
    }, [isOpen, user]);

    const handleSave = async () => {
        setIsSaving(true);
        try {
            const payload: any = { id: user.id };
            if (name !== user.name) payload.name = name;
            
            if (newPassword) {
                if (newPassword !== confirmPassword) {
                    alert("New passwords do not match.");
                    setIsSaving(false);
                    return;
                }
                payload.currentPassword = currentPassword;
                payload.newPassword = newPassword;
            }

            await apiCall('users.php', 'POST', { action: 'updateProfile', data: payload });
            onSave({ name });
        } catch (error) {
            console.error("Failed to update profile", error);
            alert(`Error updating profile: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="My Profile"
            size="md"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Saving...' : 'Save Changes'}
                </button>
            </>}
        >
            <h3 className="profile-modal-section-title">Personal Information</h3>
            <div className="form-group">
                <label htmlFor="profile-name">Full Name</label>
                <input type="text" id="profile-name" value={name} onChange={e => setName(e.target.value)} />
            </div>
            <div className="form-group">
                <label htmlFor="profile-email">Email Address</label>
                <input type="email" id="profile-email" value={user.email} disabled />
            </div>
            
            <hr className="profile-modal-separator" />

            <h3 className="profile-modal-section-title">Change Password</h3>
            <div className="form-group">
                <label htmlFor="current-password">Current Password</label>
                <input type="password" id="current-password" value={currentPassword} onChange={e => setCurrentPassword(e.target.value)} placeholder="Required to change password" />
            </div>
            <div className="form-group">
                <label htmlFor="new-password">New Password</label>
                <input type="password" id="new-password" value={newPassword} onChange={e => setNewPassword(e.target.value)} placeholder="Leave blank to keep unchanged" />
            </div>
            <div className="form-group">
                <label htmlFor="confirm-password">Confirm New Password</label>
                <input type="password" id="confirm-password" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} />
            </div>
        </Modal>
    );
};


// --- PRODUCTS PAGE ---
const CameraModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onCapture: (dataUrl: string) => void;
}> = ({ isOpen, onClose, onCapture }) => {
    const videoRef = useRef<HTMLVideoElement>(null);
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const streamRef = useRef<MediaStream | null>(null);
    const [error, setError] = useState<string | null>(null);

    const stopStream = useCallback(() => {
        if (streamRef.current) {
            streamRef.current.getTracks().forEach(track => track.stop());
            streamRef.current = null;
        }
    }, []);

    useEffect(() => {
        if (isOpen) {
            setError(null);
            navigator.mediaDevices.getUserMedia({ video: true })
                .then(stream => {
                    streamRef.current = stream;
                    if (videoRef.current) {
                        videoRef.current.srcObject = stream;
                    }
                })
                .catch(err => {
                    console.error("Camera access denied:", err);
                    setError("Camera access was denied. Please allow camera permissions in your browser settings.");
                });
        } else {
            stopStream();
        }

        return () => {
            stopStream();
        };
    }, [isOpen, stopStream]);

    const handleCapture = () => {
        const video = videoRef.current;
        const canvas = canvasRef.current;
        if (video && canvas) {
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            const context = canvas.getContext('2d');
            context?.drawImage(video, 0, 0, canvas.width, canvas.height);
            const dataUrl = canvas.toDataURL('image/png');
            onCapture(dataUrl);
            onClose();
        }
    };
    
    return (
        <Modal isOpen={isOpen} onClose={onClose} title="Capture Image from Camera" size="md">
            {error ? (
                <p className="error-message">{error}</p>
            ) : (
                <div className="camera-container">
                    <video ref={videoRef} id="camera-feed" autoPlay playsInline muted></video>
                    <canvas ref={canvasRef} style={{ display: 'none' }}></canvas>
                    <div className="camera-controls">
                        <button className="button capture-button" onClick={handleCapture}>
                            <span className="material-symbols-outlined">photo_camera</span>
                            <span>Take Photo</span>
                        </button>
                    </div>
                </div>
            )}
        </Modal>
    );
};

const ProductModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (product: Product) => void;
    productToEdit: Product | null;
}> = ({ isOpen, onClose, onSave, productToEdit }) => {
    const [product, setProduct] = useState<Omit<Product, 'id'>>({ sku: '', name: '', price: 0, imageUrl: '', description: '', averageCost: 0, stock: 0 });
    const [isSaving, setIsSaving] = useState(false);
    const [isCameraOpen, setIsCameraOpen] = useState(false);
    const fileInputRef = useRef<HTMLInputElement>(null);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            if (productToEdit) {
                setProduct(productToEdit);
            } else {
                setProduct({ sku: '', name: '', price: 0, imageUrl: '', description: '', averageCost: 0, stock: 0 });
            }
        }
    }, [isOpen, productToEdit]);
    
    const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const { name, value, type } = e.target;
        setProduct(prev => ({ ...prev, [name]: type === 'number' ? parseFloat(value) || 0 : value }));
    };
    
    const handleFileSelected = (event: React.ChangeEvent<HTMLInputElement>) => {
        const file = event.target.files?.[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const dataUrl = e.target?.result as string;
                setProduct(prev => ({ ...prev, imageUrl: dataUrl }));
            };
            reader.readAsDataURL(file);
        }
    };

    const handleCapture = (dataUrl: string) => {
        setProduct(prev => ({ ...prev, imageUrl: dataUrl }));
        setIsCameraOpen(false);
    };

    const handleRemoveImage = () => {
        setProduct(prev => ({ ...prev, imageUrl: '' }));
        if(fileInputRef.current) {
            fileInputRef.current.value = '';
        }
    };

    const handleSave = async () => {
        setIsSaving(true);
        try {
            const payload = { 
                ...product,
                ...(productToEdit && { id: productToEdit.id }),
            };

            const action = productToEdit ? 'update' : 'create';
            const savedProduct = await apiCall<Product>('products.php', 'POST', { action, data: payload });
            onSave(savedProduct);
        } catch (error) {
            console.error("Failed to save product", error);
            alert(`Error saving product: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <>
            <Modal
                isOpen={isOpen}
                onClose={onClose}
                title={productToEdit ? 'Edit Product' : 'Add New Product'}
                size="md"
                footer={<>
                    <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                    <button className="button" onClick={handleSave} disabled={isSaving}>
                        {isSaving ? 'Saving...' : 'Save Product'}
                    </button>
                </>}
            >
                <div className="form-group">
                    <label htmlFor="sku">SKU</label>
                    <input type="text" id="sku" name="sku" value={product.sku} onChange={handleChange} />
                </div>
                <div className="form-group">
                    <label htmlFor="name">Product Name</label>
                    <input type="text" id="name" name="name" value={product.name} onChange={handleChange} />
                </div>
                 <div className="form-group">
                    <label htmlFor="description">Description</label>
                    <textarea id="description" name="description" value={product.description || ''} onChange={handleChange} rows={3}></textarea>
                </div>
                <div className="form-group">
                    <label>Product Image</label>
                    <div className="image-uploader">
                        <div className="image-preview">
                            {product.imageUrl ? (
                                <img src={product.imageUrl} alt="Product Preview" />
                            ) : (
                                <div className="image-placeholder">
                                    <span className="material-symbols-outlined">image</span>
                                    <span>No Image</span>
                                </div>
                            )}
                        </div>
                        <div className="image-controls">
                            <div className="form-group" style={{ flexGrow: 1, margin: 0 }}>
                                <label htmlFor="imageUrl">Image URL</label>
                                <input type="text" id="imageUrl" name="imageUrl" value={product.imageUrl || ''} onChange={handleChange} placeholder="Or paste image URL" />
                            </div>
                            <div className="image-buttons">
                                <input type="file" ref={fileInputRef} onChange={handleFileSelected} accept="image/*" style={{ display: 'none' }} />
                                <button type="button" className="button-secondary" onClick={() => fileInputRef.current?.click()}>
                                    <span className="material-symbols-outlined">upload_file</span>
                                    <span>Upload</span>
                                </button>
                                <button type="button" className="button-secondary" onClick={() => setIsCameraOpen(true)}>
                                    <span className="material-symbols-outlined">photo_camera</span>
                                    <span>Camera</span>
                                </button>
                                {product.imageUrl && (
                                    <button type="button" className="icon-button icon-button-delete" onClick={handleRemoveImage} aria-label="Remove image">
                                        <span className="material-symbols-outlined">delete</span>
                                    </button>
                                )}
                            </div>
                        </div>
                    </div>
                </div>
                <div className="form-row">
                    <div className="form-group">
                        <label htmlFor="price">Sale Price</label>
                        <input type="number" id="price" name="price" value={product.price} onChange={handleChange} min="0" step="0.01" />
                    </div>
                     <div className="form-group">
                        <label htmlFor="averageCost">Average Cost</label>
                        <input type="number" id="averageCost" name="averageCost" value={product.averageCost || ''} onChange={handleChange} min="0" step="0.01" disabled />
                    </div>
                </div>
                <hr className="profile-modal-separator" />
                <h3 className="profile-modal-section-title">Stock Level</h3>
                 <div className="form-group">
                    <label htmlFor="stock">Initial Stock Quantity</label>
                    <input 
                        type="number" 
                        id="stock" 
                        name="stock"
                        value={product.stock}
                        onChange={handleChange}
                        min="0"
                        disabled={!!productToEdit} 
                    />
                    {!!productToEdit && <small>Stock levels must be updated via Purchases, Returns, or Damages.</small>}
                </div>
            </Modal>
            <CameraModal
                isOpen={isCameraOpen}
                onClose={() => setIsCameraOpen(false)}
                onCapture={handleCapture}
            />
        </>
    );
};

const BulkPriceUpdateModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (type: 'fixed' | 'increase' | 'decrease', value: number, isPercentage: boolean) => void;
    selectedCount: number;
}> = ({ isOpen, onClose, onSave, selectedCount }) => {
    const [updateType, setUpdateType] = useState<'fixed' | 'increase' | 'decrease'>('fixed');
    const [value, setValue] = useState(0);
    const [isPercentage, setIsPercentage] = useState(false);
    const [isSaving, setIsSaving] = useState(false);

    const handleSave = async () => {
        setIsSaving(true);
        await new Promise(res => setTimeout(res, 200)); // simulate async
        onSave(updateType, value, isPercentage);
        setIsSaving(false);
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={`Update Prices for ${selectedCount} Products`}
            size="md"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Applying...' : 'Apply Update'}
                </button>
            </>}
        >
            <div className="form-group">
                <label>Update Method</label>
                <div className="price-update-options">
                    <label><input type="radio" name="updateType" checked={updateType === 'fixed'} onChange={() => { setUpdateType('fixed'); setIsPercentage(false); }} /> Set new fixed price</label>
                    <label><input type="radio" name="updateType" checked={updateType === 'increase'} onChange={() => setUpdateType('increase')} /> Increase by amount/percentage</label>
                    <label><input type="radio" name="updateType" checked={updateType === 'decrease'} onChange={() => setUpdateType('decrease')} /> Decrease by amount/percentage</label>
                </div>
            </div>
            <div className="form-row">
                <div className="form-group" style={{ flexGrow: 3 }}>
                    <label htmlFor="update-value">{updateType === 'fixed' ? 'New Price' : 'Value'}</label>
                    <input type="number" id="update-value" value={value} onChange={e => setValue(parseFloat(e.target.value) || 0)} min="0" />
                </div>
                {updateType !== 'fixed' && (
                    <div className="form-group">
                        <label>Type</label>
                        <select value={isPercentage ? 'percent' : 'fixed'} onChange={e => setIsPercentage(e.target.value === 'percent')}>
                            <option value="fixed">Fixed Amount (Rs.)</option>
                            <option value="percent">Percentage (%)</option>
                        </select>
                    </div>
                )}
            </div>
        </Modal>
    );
};


const ProductsPage: React.FC<{
  products: Product[];
  setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
  currentUser: User | null;
}> = ({ products, setProducts, currentUser }) => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isConfirmOpen, setIsConfirmOpen] = useState(false);
  const [isBulkPriceModalOpen, setIsBulkPriceModalOpen] = useState(false);
  const [editingProduct, setEditingProduct] = useState<Product | null>(null);
  const [productToDelete, setProductToDelete] = useState<Product | null>(null);
  const [searchTerm, setSearchTerm] = useState('');
  const [stockStatusFilter, setStockStatusFilter] = useState<'all' | 'inStock' | 'lowStock' | 'outOfStock'>('all');
  const [currentPage, setCurrentPage] = useState(1);
  const [selectedProductIds, setSelectedProductIds] = useState<Set<number>>(new Set());
  const [isDeleting, setIsDeleting] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const itemsPerPage = 10;
  
  const canManageProducts = currentUser && permissions.canAddEditDeleteProducts(currentUser.role);

  const filteredProducts = useMemo(() => {
    return products.filter(p => {
        // Stock Status Filter
        if (stockStatusFilter !== 'all') {
            const totalStock = p.stock;
            if (stockStatusFilter === 'outOfStock' && totalStock !== 0) {
                return false;
            }
            if (stockStatusFilter === 'lowStock' && (totalStock === 0 || totalStock >= 20)) {
                return false;
            }
            if (stockStatusFilter === 'inStock' && totalStock < 20) {
                return false;
            }
        }

        // Text Search Filter
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) {
            return true;
        }

        const searchableText = `${p.name.toLowerCase()} ${p.sku.toLowerCase()} ${p.description?.toLowerCase() || ''}`;
        return searchKeywords.every(keyword => searchableText.includes(keyword));
    });
  }, [products, searchTerm, stockStatusFilter]);

  const paginatedProducts = useMemo(() => {
    const startIndex = (currentPage - 1) * itemsPerPage;
    return filteredProducts.slice(startIndex, startIndex + itemsPerPage);
  }, [filteredProducts, currentPage, itemsPerPage]);

  useEffect(() => {
    setCurrentPage(1);
  }, [searchTerm, stockStatusFilter]);

  useEffect(() => {
    setSelectedProductIds(new Set());
  }, [searchTerm, products, stockStatusFilter]);
  
  const getStockStatus = (stock: number) => {
    if (stock === 0) return { text: 'Out of Stock', className: 'out-of-stock' };
    if (stock < 20) return { text: 'Low Stock', className: 'low-stock' };
    return { text: 'In Stock', className: 'in-stock' };
  };

  const handleOpenAddModal = () => {
    setEditingProduct(null);
    setIsModalOpen(true);
  };
  
  const handleOpenEditModal = (product: Product) => {
    setEditingProduct(product);
    setIsModalOpen(true);
  };
  
  const handleOpenDeleteConfirm = (product: Product) => {
    setProductToDelete(product);
    setIsConfirmOpen(true);
  };
  
  const handleCloseModals = () => {
    setIsModalOpen(false);
    setIsConfirmOpen(false);
    setIsBulkPriceModalOpen(false);
    setEditingProduct(null);
    setProductToDelete(null);
  };
  
  const handleSaveProduct = (savedProduct: Product) => {
    if (editingProduct) { // Editing
      setProducts(products.map(p => p.id === savedProduct.id ? savedProduct : p));
    } else { // Adding
      setProducts([savedProduct, ...products]);
    }
    handleCloseModals();
  };
  
  const handleConfirmDelete = async () => {
    setIsDeleting(true);
    try {
        if (productToDelete) {
            await apiCall('products.php', 'POST', { action: 'delete', data: { id: productToDelete.id }});
            setProducts(products.filter(p => p.id !== productToDelete.id));
        } else if (selectedProductIds.size > 0) {
            await apiCall('products.php', 'POST', { action: 'bulkDelete', data: { ids: Array.from(selectedProductIds) }});
            setProducts(products.filter(p => !selectedProductIds.has(p.id)));
            setSelectedProductIds(new Set());
        }
    } catch (error) {
        console.error("Failed to delete product(s)", error);
        alert(`Error deleting: ${(error as Error).message}`);
    } finally {
        setIsDeleting(false);
        handleCloseModals();
    }
  };

  const handleToggleSelect = (productId: number) => {
    const newSelection = new Set(selectedProductIds);
    if (newSelection.has(productId)) {
        newSelection.delete(productId);
    } else {
        newSelection.add(productId);
    }
    setSelectedProductIds(newSelection);
  };

  const handleToggleSelectAll = () => {
    const allVisibleIds = new Set(paginatedProducts.map(p => p.id));
    if (selectedProductIds.size === allVisibleIds.size && paginatedProducts.length > 0) {
        setSelectedProductIds(new Set());
    } else {
        setSelectedProductIds(allVisibleIds);
    }
  };

  const handleExportTemplate = () => {
    const headers = ['sku', 'name', 'description', 'imageUrl', 'price', 'stock'];
    downloadAsCsv('product-import-template', headers, []);
  };

  const handleImportClick = () => {
    fileInputRef.current?.click();
  };

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = async (e) => {
        try {
            const text = e.target?.result as string;
            // This entire block should be a single API call
            const response = await apiCall<{ importedProducts: Product[] }>('products.php', 'POST', { action: 'import', data: { csv: text } });
            setProducts(prev => [...response.importedProducts, ...prev]);
            alert(`${response.importedProducts.length} products imported successfully!`);
        } catch (error) {
            console.error("CSV import failed:", error);
            alert(`CSV import failed: ${(error as Error).message}`);
        }
    };
    reader.readAsText(file);
    event.target.value = ''; // Reset file input
  };
  
  const handleSaveBulkPriceUpdate = async (type: 'fixed' | 'increase' | 'decrease', value: number, isPercentage: boolean) => {
    try {
        const payload = {
            ids: Array.from(selectedProductIds),
            update: { type, value, isPercentage }
        };
        const updatedProducts = await apiCall<Product[]>('products.php', 'POST', { action: 'bulkPriceUpdate', data: payload });
        
        const updatedProductsMap = new Map(updatedProducts.map(p => [p.id, p]));
        setProducts(prev => prev.map(p => updatedProductsMap.get(p.id) || p));

        setSelectedProductIds(new Set());
        setIsBulkPriceModalOpen(false);
    } catch (error) {
        console.error("Failed to update prices", error);
        alert(`Error updating prices: ${(error as Error).message}`);
    }
  };


  return (
    <>
      <div className="page-header">
        <h1 className="page-title">Products</h1>
        {canManageProducts && (
            <div className="page-actions">
                <div className="button-group">
                    <input type="file" ref={fileInputRef} onChange={handleFileChange} accept=".csv" style={{ display: 'none' }} />
                    <button className="button-secondary" onClick={handleImportClick}>Import CSV</button>
                    <button className="button-secondary" onClick={handleExportTemplate}>Export Template</button>
                </div>
                <button className="button" onClick={handleOpenAddModal}>
                  <span className="material-symbols-outlined">add</span>
                  <span>Add New Product</span>
                </button>
            </div>
        )}
      </div>
      <div className="page-controls">
        <div className="search-container">
            <span className="material-symbols-outlined">search</span>
            <input 
                type="search" 
                placeholder="Search by name, SKU, or description..."
                value={searchTerm}
                onChange={e => setSearchTerm(e.target.value)}
            />
        </div>
        <div className="filter-group">
            <label htmlFor="stock-filter">Stock Status</label>
            <select 
                id="stock-filter" 
                value={stockStatusFilter}
                onChange={e => setStockStatusFilter(e.target.value as any)}
            >
                <option value="all">All Statuses</option>
                <option value="inStock">In Stock</option>
                <option value="lowStock">Low Stock</option>
                <option value="outOfStock">Out of Stock</option>
            </select>
        </div>
        {searchTerm && (
            <div className="active-filter-display">
                <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                    <span className="material-symbols-outlined">close</span>
                </button>
            </div>
        )}
      </div>
      <div className="card">
        <table className="products-table">
          <thead>
            <tr>
              {canManageProducts && (
                <th className="checkbox-cell">
                    <input 
                        type="checkbox"
                        disabled={paginatedProducts.length === 0}
                        checked={paginatedProducts.length > 0 && paginatedProducts.every(p => selectedProductIds.has(p.id))}
                        onChange={handleToggleSelectAll}
                    />
                </th>
              )}
              <th>Image</th>
              <th>SKU</th>
              <th>Product Name</th>
              <th>Description</th>
              <th className="text-right">Price</th>
              <th className="text-right">Total Stock</th>
              <th className="text-center">Status</th>
              {canManageProducts && <th>Actions</th>}
            </tr>
          </thead>
          <tbody>
            {paginatedProducts.map((product) => {
              const status = getStockStatus(product.stock);
              return (
                <tr key={product.id} className={selectedProductIds.has(product.id) ? 'selected-row' : ''}>
                  {canManageProducts && (
                    <td className="checkbox-cell">
                        <input 
                            type="checkbox"
                            checked={selectedProductIds.has(product.id)}
                            onChange={() => handleToggleSelect(product.id)}
                        />
                    </td>
                  )}
                  <td className="product-image-cell">
                    <img src={product.imageUrl} alt={product.name} className="product-thumbnail" onError={(e) => e.currentTarget.src = 'https://via.placeholder.com/50'} />
                  </td>
                  <td>{product.sku}</td>
                  <td>{product.name}</td>
                  <td className="product-description-cell" title={product.description || ''}>
                    {product.description}
                  </td>
                  <td className="text-right font-mono">{formatCurrency(product.price)}</td>
                  <td className="text-right font-mono">{product.stock}</td>
                  <td className="text-center">
                    <span className={`stock-status ${status.className}`}>
                      {status.text}
                    </span>
                  </td>
                  {canManageProducts && (
                      <td className="actions-cell">
                        <button className="icon-button" aria-label="Edit product" onClick={() => handleOpenEditModal(product)}>
                           <span className="material-symbols-outlined">edit</span>
                        </button>
                        <button className="icon-button icon-button-delete" aria-label="Delete product" onClick={() => handleOpenDeleteConfirm(product)}>
                           <span className="material-symbols-outlined">delete</span>
                        </button>
                      </td>
                  )}
                </tr>
              );
            })}
          </tbody>
        </table>
        <Pagination 
            currentPage={currentPage}
            totalItems={filteredProducts.length}
            itemsPerPage={itemsPerPage}
            onPageChange={setCurrentPage}
        />
      </div>

      {selectedProductIds.size > 0 && canManageProducts && (
        <div className="bulk-action-bar">
            <span>{selectedProductIds.size} selected</span>
            <div className="page-actions">
                <button className="button-secondary" onClick={() => setIsBulkPriceModalOpen(true)}>Update Prices</button>
                <button className="button-danger" onClick={() => { setProductToDelete(null); setIsConfirmOpen(true); }}>Delete Selected</button>
            </div>
        </div>
      )}

      {canManageProducts && (
        <>
            <ProductModal
                isOpen={isModalOpen}
                onClose={handleCloseModals}
                onSave={handleSaveProduct}
                productToEdit={editingProduct}
            />
            <BulkPriceUpdateModal
                isOpen={isBulkPriceModalOpen}
                onClose={handleCloseModals}
                onSave={handleSaveBulkPriceUpdate}
                selectedCount={selectedProductIds.size}
            />
            <ConfirmationModal
                isOpen={isConfirmOpen}
                onClose={handleCloseModals}
                onConfirm={handleConfirmDelete}
                isSaving={isDeleting}
                title="Confirm Deletion"
                message={productToDelete 
                    ? `Are you sure you want to delete "${productToDelete.name}"?`
                    : `Are you sure you want to delete the ${selectedProductIds.size} selected products?`
                }
            />
        </>
      )}
    </>
  );
};


// --- SALES PAGE ---
const SaleModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (sale: Sale, updatedProducts: Product[]) => void;
    products: Product[];
    contacts: Contact[];
    saleToEdit: Sale | null;
}> = ({ isOpen, onClose, onSave, products, contacts, saleToEdit }) => {
    const [customerId, setCustomerId] = useState<number | ''>('');
    const [items, setItems] = useState<SaleItem[]>([]);
    const [amountPaid, setAmountPaid] = useState<number | ''>('');
    const [currentProductId, setCurrentProductId] = useState<number | ''>('');
    const [currentQuantity, setCurrentQuantity] = useState<number | ''>(1);
    const [isSaving, setIsSaving] = useState(false);

    const customers = contacts.filter(c => c.role === 'Customer');

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            if (saleToEdit) {
                setCustomerId(saleToEdit.customerId);
                setItems(saleToEdit.items);
                setAmountPaid(saleToEdit.amountPaid);
            } else {
                setCustomerId('');
                setItems([]);
                setAmountPaid('');
            }
            setCurrentProductId('');
            setCurrentQuantity(1);
        }
    }, [isOpen, saleToEdit]);
    
    const selectedProduct = products.find(p => p.id === currentProductId);
    
    const availableStock = useMemo(() => {
        if (!selectedProduct) return 0;
        const originalItem = saleToEdit?.items.find(item => item.productId === selectedProduct.id);
        const originalQuantity = originalItem ? originalItem.quantity : 0;
        return selectedProduct.stock + originalQuantity;
    }, [selectedProduct, saleToEdit]);

    const handleAddItem = () => {
        if (!currentProductId || !currentQuantity || !selectedProduct) return;
        
        const newQuantity = Number(currentQuantity);
        
        const existingItemIndex = items.findIndex(item => item.productId === currentProductId);
        let newItems = [...items];

        if (existingItemIndex > -1) {
            newItems[existingItemIndex].quantity += newQuantity;
            newItems[existingItemIndex].total = newItems[existingItemIndex].quantity * newItems[existingItemIndex].price;
        } else {
            newItems.push({
                productId: selectedProduct.id,
                name: selectedProduct.name,
                quantity: newQuantity,
                price: selectedProduct.price,
                total: newQuantity * selectedProduct.price,
            });
        }
        setItems(newItems);
        setCurrentProductId('');
        setCurrentQuantity(1);
    };
    
    const handleRemoveItem = (productId: number) => {
        setItems(items.filter(item => item.productId !== productId));
    };

    const totalAmount = items.reduce((sum, item) => sum + item.total, 0);
    const paid = Number(amountPaid) || 0;

    const handleSave = async () => {
        if (!customerId || items.length === 0) return;

        setIsSaving(true);
        try {
            const payload = {
                customerId,
                items: items.map(({ name, total, ...item }) => item), // Sanitize for API
                amountPaid: paid,
                ...(saleToEdit && { id: saleToEdit.id }),
            };

            const action = saleToEdit ? 'update' : 'create';
            const response = await apiCall<{ savedSale: Sale; updatedProducts: Product[] }>('sales.php', 'POST', { action, data: payload });
            
            onSave(response.savedSale, response.updatedProducts);
        } catch (error) {
            console.error("Failed to save sale", error);
            alert(`Error saving sale: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={saleToEdit ? `Edit Sale #${saleToEdit.id}` : "Create New Sale"}
            size="lg"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={!customerId || items.length === 0 || isSaving}>
                    {isSaving ? 'Saving...' : 'Save Sale'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="customer">Customer</label>
                <select id="customer" value={customerId} onChange={(e) => setCustomerId(Number(e.target.value))}>
                    <option value="" disabled>Select a customer</option>
                    {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
            </div>

            <div className="card item-entry-card">
                <h3>Add Products</h3>
                <div className="form-row">
                    <div className="form-group product-select">
                        <label htmlFor="product">Product</label>
                        <select id="product" value={currentProductId} onChange={e => setCurrentProductId(Number(e.target.value))}>
                             <option value="" disabled>Select a product</option>
                             {products.filter(p => p.stock > 0 || saleToEdit?.items.some(i => i.productId === p.id)).map(p => <option key={p.id} value={p.id}>{p.name} (Stock: {p.stock})</option>)}
                        </select>
                    </div>
                    <div className="form-group quantity-select">
                        <label htmlFor="quantity">Quantity</label>
                        <input type="number" id="quantity" value={currentQuantity} min="1" max={availableStock} onChange={e => setCurrentQuantity(Number(e.target.value))} disabled={!currentProductId}/>
                    </div>
                    <button className="button" onClick={handleAddItem} disabled={!currentProductId || !currentQuantity || Number(currentQuantity) > availableStock}>Add Item</button>
                </div>
            </div>

            {items.length > 0 && (
                <table className="modal-items-table">
                    <thead><tr><th>Product</th><th>Qty</th><th>Price</th><th>Total</th><th></th></tr></thead>
                    <tbody>
                        {items.map(item => (
                            <tr key={item.productId}>
                                <td>{item.name}</td>
                                <td>{item.quantity}</td>
                                <td>{formatCurrency(item.price)}</td>
                                <td>{formatCurrency(item.total)}</td>
                                <td><button className="icon-button icon-button-delete" onClick={() => handleRemoveItem(item.productId)}><span className="material-symbols-outlined">delete</span></button></td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            )}
            
            <div className="sale-summary">
               <div className="form-group">
                   <label htmlFor="amount-paid">Amount Paid</label>
                   <input type="number" id="amount-paid" value={amountPaid} placeholder="0.00" onChange={e => setAmountPaid(Number(e.target.value) >= 0 ? Number(e.target.value) : '')} />
               </div>
               <div className="summary-details">
                   <p>Total: <strong>{formatCurrency(totalAmount)}</strong></p>
                   <p>Balance: <strong>{formatCurrency(totalAmount - paid)}</strong></p>
               </div>
            </div>
        </Modal>
    );
};


const SalesPage: React.FC<{
    sales: Sale[],
    products: Product[],
    contacts: Contact[],
    setSales: React.Dispatch<React.SetStateAction<Sale[]>>,
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
}> = ({ sales, products, contacts, setSales, setProducts }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [editingSale, setEditingSale] = useState<Sale | null>(null);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const [startDate, setStartDate] = useState('');
    const [endDate, setEndDate] = useState('');
    const [selectedCustomer, setSelectedCustomer] = useState<number | ''>('');
    const [selectedStatus, setSelectedStatus] = useState<'' | Sale['status']>('');
    const itemsPerPage = 10;

    const customers = useMemo(() => contacts.filter(c => c.role === 'Customer'), [contacts]);

    const filteredSales = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);

        return sales.filter(s => {
            const searchableText = `${s.customerName.toLowerCase()} #${s.id} ${s.status.toLowerCase()}`;
            if (searchKeywords.length > 0 && !searchKeywords.every(keyword => searchableText.includes(keyword))) {
                return false;
            }

            if (startDate && s.date < startDate) return false;
            if (endDate && s.date > endDate) return false;
            if (selectedCustomer && s.customerId !== selectedCustomer) return false;
            if (selectedStatus && s.status !== selectedStatus) return false;

            return true;
        });
    }, [sales, searchTerm, startDate, endDate, selectedCustomer, selectedStatus]);

    const paginatedSales = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredSales.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredSales, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm, startDate, endDate, selectedCustomer, selectedStatus]);

    const handleOpenAddModal = () => {
        setEditingSale(null);
        setIsModalOpen(true);
    };

    const handleOpenEditModal = (sale: Sale) => {
        setEditingSale(sale);
        setIsModalOpen(true);
    };

    const handleSaveSale = (savedSale: Sale, updatedProducts: Product[]) => {
        const updatedProductsMap = new Map(updatedProducts.map(p => [p.id, p]));
        setProducts(prev => prev.map(p => updatedProductsMap.get(p.id) || p));

        if (editingSale) { // Update existing sale
            setSales(sales.map(s => s.id === savedSale.id ? savedSale : s));
        } else { // Create new sale
            setSales(prev => [savedSale, ...prev]);
        }

        setIsModalOpen(false);
    };

    const getStatusClass = (status: Sale['status']) => {
        if (status === 'Paid') return 'status-paid';
        if (status === 'Partially Paid') return 'status-partial';
        if (status === 'Unpaid') return 'status-unpaid';
        return '';
    };

    const handleExport = (format: 'csv' | 'pdf') => {
        const dataToExport = filteredSales;
        if (dataToExport.length === 0) {
            alert("No data to export for the current filters.");
            return;
        }

        const filename = `sales-report-${new Date().toISOString().split('T')[0]}`;

        if (format === 'csv') {
            const headers = ['Invoice ID', 'Customer', 'Date', 'Total Amount', 'Amount Paid', 'Balance', 'Status'];
            const data = dataToExport.map(s => [s.id, s.customerName, s.date, s.totalAmount, s.amountPaid, s.balance, s.status]);
            downloadAsCsv(filename, headers, data);
        } else if (format === 'pdf') {
            const headers = [
                { header: 'Invoice ID', dataKey: 'id' },
                { header: 'Customer', dataKey: 'customerName' },
                { header: 'Date', dataKey: 'date' },
                { header: 'Total', dataKey: 'totalAmount' },
                { header: 'Paid', dataKey: 'amountPaid' },
                { header: 'Balance', dataKey: 'balance' },
                { header: 'Status', dataKey: 'status' },
            ];
            const data = dataToExport.map(s => ({...s, totalAmount: formatCurrency(s.totalAmount), amountPaid: formatCurrency(s.amountPaid), balance: formatCurrency(s.balance)}));
            downloadAsPdf(filename, `Sales Report`, headers, data);
        }
    };
    
    const clearFilters = () => {
        setSearchTerm('');
        setStartDate('');
        setEndDate('');
        setSelectedCustomer('');
        setSelectedStatus('');
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Sales</h1>
                <div className="page-actions">
                    <button className="button" onClick={handleOpenAddModal}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New Sale</span>
                    </button>
                    <div className="button-group">
                        <button className="button-secondary" onClick={() => handleExport('csv')}>
                            <span className="material-symbols-outlined">description</span>
                            <span>CSV</span>
                        </button>
                        <button className="button-secondary" onClick={() => handleExport('pdf')}>
                            <span className="material-symbols-outlined">picture_as_pdf</span>
                            <span>PDF</span>
                        </button>
                    </div>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by customer, ID..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                <div className="filter-bar">
                    <div className="form-group">
                        <label htmlFor="start-date-filter">From</label>
                        <input type="date" id="start-date-filter" value={startDate} onChange={e => setStartDate(e.target.value)} />
                    </div>
                    <div className="form-group">
                        <label htmlFor="end-date-filter">To</label>
                        <input type="date" id="end-date-filter" value={endDate} onChange={e => setEndDate(e.target.value)} />
                    </div>
                    <div className="form-group">
                        <label htmlFor="customer-filter">Customer</label>
                        <select id="customer-filter" value={selectedCustomer} onChange={e => setSelectedCustomer(Number(e.target.value) || '')}>
                            <option value="">All Customers</option>
                            {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                        </select>
                    </div>
                    <div className="form-group">
                        <label htmlFor="status-filter">Status</label>
                        <select id="status-filter" value={selectedStatus} onChange={e => setSelectedStatus(e.target.value as any)}>
                            <option value="">All Statuses</option>
                            <option value="Paid">Paid</option>
                            <option value="Partially Paid">Partially Paid</option>
                            <option value="Unpaid">Unpaid</option>
                        </select>
                    </div>
                    <button className="button-secondary" onClick={clearFilters}>Clear</button>
                </div>
            </div>
            <div className="card">
                 <table className="sales-table">
                    <thead>
                        <tr>
                            <th>Invoice ID</th>
                            <th>Customer</th>
                            <th>Date</th>
                            <th>Total Amount</th>
                            <th>Paid</th>
                            <th>Balance</th>
                            <th>Status</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedSales.map((sale) => (
                            <tr key={sale.id}>
                                <td>#{sale.id}</td>
                                <td>{sale.customerName}</td>
                                <td>{sale.date}</td>
                                <td className="text-right">{formatCurrency(sale.totalAmount)}</td>
                                <td className="text-right">{formatCurrency(sale.amountPaid)}</td>
                                <td className="text-right">{formatCurrency(sale.balance)}</td>
                                <td>
                                    <span className={`status-badge ${getStatusClass(sale.status)}`}>
                                        {sale.status}
                                    </span>
                                </td>
                                <td className="actions-cell">
                                    <button className="icon-button" onClick={() => handleOpenEditModal(sale)}>
                                        <span className="material-symbols-outlined">edit</span>
                                    </button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredSales.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
             <SaleModal 
                isOpen={isModalOpen}
                onClose={() => setIsModalOpen(false)}
                onSave={handleSaveSale}
                products={products}
                contacts={contacts}
                saleToEdit={editingSale}
            />
        </>
    );
};


// --- PURCHASES PAGE ---
const AddPurchaseModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (purchase: Purchase, updatedProducts: Product[]) => void;
    products: Product[];
    contacts: Contact[];
}> = ({ isOpen, onClose, onSave, products, contacts }) => {
    const [vendorId, setVendorId] = useState<number | ''>('');
    const [items, setItems] = useState<Omit<PurchaseItem, 'name' | 'total'>[]>([]);
    const [amountPaid, setAmountPaid] = useState<number | ''>('');
    const [currentProductId, setCurrentProductId] = useState<number | ''>('');
    const [currentQuantity, setCurrentQuantity] = useState<number | ''>(1);
    const [currentCost, setCurrentCost] = useState<number | ''>('');
    const [isSaving, setIsSaving] = useState(false);

    const vendors = contacts.filter(c => c.role === 'Vendor');

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setVendorId('');
            setItems([]);
            setAmountPaid('');
            setCurrentProductId('');
            setCurrentQuantity(1);
            setCurrentCost('');
        }
    }, [isOpen]);
    
    const selectedProduct = products.find(p => p.id === currentProductId);

    const handleAddItem = () => {
        if (!currentProductId || !currentQuantity || !currentCost || !selectedProduct) return;
        
        const newQuantity = Number(currentQuantity);
        const newCost = Number(currentCost);
        
        setItems(prev => [
            ...prev,
            {
                productId: selectedProduct.id,
                quantity: newQuantity,
                cost: newCost,
            }
        ]);
        setCurrentProductId('');
        setCurrentQuantity(1);
        setCurrentCost('');
    };
    
    const handleRemoveItem = (index: number) => {
        setItems(prev => prev.filter((_, i) => i !== index));
    };

    const itemsWithDetails = items.map(item => {
        const product = products.find(p => p.id === item.productId);
        return {
            ...item,
            name: product?.name || 'Unknown',
            total: item.quantity * item.cost,
        }
    });

    const totalAmount = itemsWithDetails.reduce((sum, item) => sum + item.total, 0);
    const paid = Number(amountPaid) || 0;

    const handleSave = async () => {
        if (!vendorId || items.length === 0) return;

        setIsSaving(true);
        try {
            const payload = { vendorId, items, amountPaid: paid };
            const response = await apiCall<{ savedPurchase: Purchase; updatedProducts: Product[] }>('purchases.php', 'POST', { action: 'create', data: payload });
            onSave(response.savedPurchase, response.updatedProducts);
        } catch (error) {
            console.error("Failed to save purchase", error);
            alert(`Error saving purchase: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Create New Purchase"
            size="lg"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={!vendorId || items.length === 0 || isSaving}>
                    {isSaving ? 'Saving...' : 'Save Purchase'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="vendor">Vendor</label>
                <select id="vendor" value={vendorId} onChange={(e) => setVendorId(Number(e.target.value))}>
                    <option value="" disabled>Select a vendor</option>
                    {vendors.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
                </select>
            </div>

            <div className="card item-entry-card">
                <h3>Add Products</h3>
                <div className="form-row">
                    <div className="form-group product-select">
                        <label htmlFor="product">Product</label>
                        <select id="product" value={currentProductId} onChange={e => setCurrentProductId(Number(e.target.value))}>
                             <option value="" disabled>Select a product</option>
                             {products.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                        </select>
                    </div>
                    <div className="form-group quantity-select">
                        <label htmlFor="quantity">Quantity</label>
                        <input type="number" id="quantity" value={currentQuantity} min="1" onChange={e => setCurrentQuantity(Number(e.target.value))} disabled={!currentProductId}/>
                    </div>
                     <div className="form-group quantity-select">
                        <label htmlFor="cost">Cost/Unit</label>
                        <input type="number" id="cost" value={currentCost} min="0" step="0.01" onChange={e => setCurrentCost(Number(e.target.value))} disabled={!currentProductId}/>
                    </div>
                    <button className="button" onClick={handleAddItem} disabled={!currentProductId || !currentQuantity || !currentCost}>Add Item</button>
                </div>
            </div>

            {itemsWithDetails.length > 0 && (
                <table className="modal-items-table">
                    <thead><tr><th>Product</th><th>Qty</th><th>Cost</th><th>Total</th><th></th></tr></thead>
                    <tbody>
                        {itemsWithDetails.map((item, index) => (
                            <tr key={`${item.productId}-${index}`}>
                                <td>{item.name}</td>
                                <td>{item.quantity}</td>
                                <td>{formatCurrency(item.cost)}</td>
                                <td>{formatCurrency(item.total)}</td>
                                <td><button className="icon-button icon-button-delete" onClick={() => handleRemoveItem(index)}><span className="material-symbols-outlined">delete</span></button></td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            )}
            
            <div className="sale-summary">
               <div className="form-group">
                   <label htmlFor="amount-paid">Amount Paid</label>
                   <input type="number" id="amount-paid" value={amountPaid} placeholder="0.00" onChange={e => setAmountPaid(Number(e.target.value) >= 0 ? Number(e.target.value) : '')} />
               </div>
               <div className="summary-details">
                   <p>Total: <strong>{formatCurrency(totalAmount)}</strong></p>
                   <p>Balance: <strong>{formatCurrency(totalAmount - paid)}</strong></p>
               </div>
            </div>
        </Modal>
    );
};

const PurchasesPage: React.FC<{
    purchases: Purchase[],
    products: Product[],
    contacts: Contact[],
    setPurchases: React.Dispatch<React.SetStateAction<Purchase[]>>,
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
}> = ({ purchases, products, contacts, setPurchases, setProducts }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const [startDate, setStartDate] = useState('');
    const [endDate, setEndDate] = useState('');
    const [selectedVendor, setSelectedVendor] = useState<number | ''>('');
    const [selectedStatus, setSelectedStatus] = useState<'' | Purchase['status']>('');
    const itemsPerPage = 10;

    const vendors = useMemo(() => contacts.filter(c => c.role === 'Vendor'), [contacts]);

    const filteredPurchases = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        return purchases.filter(p => {
            const searchableText = `${p.vendorName.toLowerCase()} #${p.id} ${p.status.toLowerCase()}`;
            if (searchKeywords.length > 0 && !searchKeywords.every(keyword => searchableText.includes(keyword))) {
                return false;
            }

            if (startDate && p.date < startDate) return false;
            if (endDate && p.date > endDate) return false;
            if (selectedVendor && p.vendorId !== selectedVendor) return false;
            if (selectedStatus && p.status !== selectedStatus) return false;

            return true;
        });
    }, [purchases, searchTerm, startDate, endDate, selectedVendor, selectedStatus]);
    
    const paginatedPurchases = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredPurchases.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredPurchases, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm, startDate, endDate, selectedVendor, selectedStatus]);

    const handleSavePurchase = (newPurchase: Purchase, updatedProducts: Product[]) => {
        setPurchases(prev => [newPurchase, ...prev]);
        
        const updatedProductsMap = new Map(updatedProducts.map(p => [p.id, p]));
        setProducts(prev => prev.map(p => updatedProductsMap.get(p.id) || p));

        setIsModalOpen(false);
    };
    
    const getStatusClass = (status: Purchase['status']) => {
        if (status === 'Paid') return 'status-paid';
        if (status === 'Partially Paid') return 'status-partial';
        if (status === 'Unpaid') return 'status-unpaid';
        return '';
    };

    const handleExport = (format: 'csv' | 'pdf') => {
        const dataToExport = filteredPurchases;
        if (dataToExport.length === 0) {
            alert("No data to export for the current filters.");
            return;
        }

        const filename = `purchases-report-${new Date().toISOString().split('T')[0]}`;

        if (format === 'csv') {
            const headers = ['Order ID', 'Vendor', 'Date', 'Total Amount', 'Amount Paid', 'Balance', 'Status'];
            const data = dataToExport.map(p => [p.id, p.vendorName, p.date, p.totalAmount, p.amountPaid, p.balance, p.status]);
            downloadAsCsv(filename, headers, data);
        } else if (format === 'pdf') {
             const headers = [
                { header: 'Order ID', dataKey: 'id' },
                { header: 'Vendor', dataKey: 'vendorName' },
                { header: 'Date', dataKey: 'date' },
                { header: 'Total', dataKey: 'totalAmount' },
                { header: 'Paid', dataKey: 'amountPaid' },
                { header: 'Balance', dataKey: 'balance' },
                { header: 'Status', dataKey: 'status' },
            ];
            const data = dataToExport.map(s => ({...s, totalAmount: formatCurrency(s.totalAmount), amountPaid: formatCurrency(s.amountPaid), balance: formatCurrency(s.balance)}));
            downloadAsPdf(filename, `Purchases Report`, headers, data);
        }
    };
    
    const clearFilters = () => {
        setSearchTerm('');
        setStartDate('');
        setEndDate('');
        setSelectedVendor('');
        setSelectedStatus('');
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Purchase Orders</h1>
                <div className="page-actions">
                    <button className="button" onClick={() => setIsModalOpen(true)}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New Purchase</span>
                    </button>
                    <div className="button-group">
                        <button className="button-secondary" onClick={() => handleExport('csv')}>
                            <span className="material-symbols-outlined">description</span>
                            <span>CSV</span>
                        </button>
                        <button className="button-secondary" onClick={() => handleExport('pdf')}>
                            <span className="material-symbols-outlined">picture_as_pdf</span>
                            <span>PDF</span>
                        </button>
                    </div>
                </div>
            </div>
             <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by vendor, ID..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                <div className="filter-bar">
                    <div className="form-group">
                        <label htmlFor="start-date-filter-purchase">From</label>
                        <input type="date" id="start-date-filter-purchase" value={startDate} onChange={e => setStartDate(e.target.value)} />
                    </div>
                    <div className="form-group">
                        <label htmlFor="end-date-filter-purchase">To</label>
                        <input type="date" id="end-date-filter-purchase" value={endDate} onChange={e => setEndDate(e.target.value)} />
                    </div>
                    <div className="form-group">
                        <label htmlFor="vendor-filter">Vendor</label>
                        <select id="vendor-filter" value={selectedVendor} onChange={e => setSelectedVendor(Number(e.target.value) || '')}>
                            <option value="">All Vendors</option>
                            {vendors.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
                        </select>
                    </div>
                    <div className="form-group">
                        <label htmlFor="status-filter-purchase">Status</label>
                        <select id="status-filter-purchase" value={selectedStatus} onChange={e => setSelectedStatus(e.target.value as any)}>
                            <option value="">All Statuses</option>
                            <option value="Paid">Paid</option>
                            <option value="Partially Paid">Partially Paid</option>
                            <option value="Unpaid">Unpaid</option>
                        </select>
                    </div>
                    <button className="button-secondary" onClick={clearFilters}>Clear</button>
                </div>
            </div>
            <div className="card">
                 <table className="purchases-table">
                    <thead>
                        <tr>
                            <th>Order ID</th>
                            <th>Vendor</th>
                            <th>Date</th>
                            <th>Total Amount</th>
                            <th>Paid</th>
                            <th>Balance</th>
                            <th>Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedPurchases.map((purchase) => (
                            <tr key={purchase.id}>
                                <td>#{purchase.id}</td>
                                <td>{purchase.vendorName}</td>
                                <td>{purchase.date}</td>
                                <td className="text-right">{formatCurrency(purchase.totalAmount)}</td>
                                <td className="text-right">{formatCurrency(purchase.amountPaid)}</td>
                                <td className="text-right">{formatCurrency(purchase.balance)}</td>
                                <td>
                                    <span className={`status-badge ${getStatusClass(purchase.status)}`}>
                                        {purchase.status}
                                    </span>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredPurchases.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
             <AddPurchaseModal 
                isOpen={isModalOpen}
                onClose={() => setIsModalOpen(false)}
                onSave={handleSavePurchase}
                products={products}
                contacts={contacts}
            />
        </>
    );
};


// --- ORDERS PAGE ---
const AddOrderModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (order: Order) => void;
    products: Product[];
    contacts: Contact[];
}> = ({ isOpen, onClose, onSave, products, contacts }) => {
    const [customerId, setCustomerId] = useState<number | ''>('');
    const [items, setItems] = useState<SaleItem[]>([]);
    const [currentProductId, setCurrentProductId] = useState<number | ''>('');
    const [currentQuantity, setCurrentQuantity] = useState<number | ''>(1);
    const [isSaving, setIsSaving] = useState(false);

    const customers = contacts.filter(c => c.role === 'Customer');

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setCustomerId('');
            setItems([]);
            setCurrentProductId('');
            setCurrentQuantity(1);
        }
    }, [isOpen]);

    const selectedProduct = products.find(p => p.id === currentProductId);
    const availableStock = selectedProduct ? selectedProduct.stock : 0;

    const handleAddItem = () => {
        if (!currentProductId || !currentQuantity || !selectedProduct) return;

        const existingItemIndex = items.findIndex(item => item.productId === currentProductId);
        const newQuantity = Number(currentQuantity);

        if (newQuantity > availableStock) {
            alert(`Cannot add ${newQuantity} items. Only ${availableStock} in stock.`);
            return;
        }
        
        let newItems = [...items];

        if (existingItemIndex > -1) {
            newItems[existingItemIndex].quantity += newQuantity;
            newItems[existingItemIndex].total = newItems[existingItemIndex].quantity * newItems[existingItemIndex].price;
        } else {
            newItems.push({
                productId: selectedProduct.id,
                name: selectedProduct.name,
                quantity: newQuantity,
                price: selectedProduct.price,
                total: newQuantity * selectedProduct.price,
            });
        }
        setItems(newItems);
        setCurrentProductId('');
        setCurrentQuantity(1);
    };
    
    const handleRemoveItem = (productId: number) => {
        setItems(items.filter(item => item.productId !== productId));
    };

    const totalAmount = items.reduce((sum, item) => sum + item.total, 0);

    const handleSave = async () => {
        if (!customerId || items.length === 0) return;
        
        setIsSaving(true);
        try {
            const payload = {
                customerId,
                items: items.map(({ name, total, ...item}) => item)
            };
            const savedOrder = await apiCall<Order>('orders.php', 'POST', { action: 'create', data: payload });
            onSave(savedOrder);
        } catch (error) {
            console.error("Failed to save order", error);
            alert(`Error saving order: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Create New Order"
            size="lg"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={!customerId || items.length === 0 || isSaving}>
                    {isSaving ? 'Saving...' : 'Save Order'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="customer-order">Customer</label>
                <select id="customer-order" value={customerId} onChange={(e) => setCustomerId(Number(e.target.value))}>
                    <option value="" disabled>Select a customer</option>
                    {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
            </div>

            <div className="card item-entry-card">
                <h3>Add Products</h3>
                <div className="form-row">
                    <div className="form-group product-select">
                        <label htmlFor="product-order">Product</label>
                        <select id="product-order" value={currentProductId} onChange={e => setCurrentProductId(Number(e.target.value))}>
                             <option value="" disabled>Select a product</option>
                             {products.filter(p => p.stock > 0).map(p => <option key={p.id} value={p.id}>{p.name} (In Stock: {p.stock})</option>)}
                        </select>
                    </div>
                    <div className="form-group quantity-select">
                        <label htmlFor="quantity-order">Quantity</label>
                        <input type="number" id="quantity-order" value={currentQuantity} min="1" max={availableStock} onChange={e => setCurrentQuantity(Number(e.target.value))} disabled={!currentProductId}/>
                    </div>
                    <button className="button" onClick={handleAddItem} disabled={!currentProductId || !currentQuantity || Number(currentQuantity) > availableStock}>Add Item</button>
                </div>
            </div>

            {items.length > 0 && (
                <>
                    <table className="modal-items-table">
                        <thead><tr><th>Product</th><th>Qty</th><th>Price</th><th>Total</th><th></th></tr></thead>
                        <tbody>
                            {items.map(item => (
                                <tr key={item.productId}>
                                    <td>{item.name}</td>
                                    <td>{item.quantity}</td>
                                    <td>{formatCurrency(item.price)}</td>
                                    <td>{formatCurrency(item.total)}</td>
                                    <td><button className="icon-button icon-button-delete" onClick={() => handleRemoveItem(item.productId)}><span className="material-symbols-outlined">delete</span></button></td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                     <div className="sale-summary">
                        <div className="summary-details">
                            <p>Total: <strong>{formatCurrency(totalAmount)}</strong></p>
                        </div>
                    </div>
                </>
            )}
        </Modal>
    );
};

const ConvertToSaleModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onConfirm: (sale: Sale, updatedProducts: Product[]) => void;
    order: Order | null;
    products: Product[];
}> = ({ isOpen, onClose, onConfirm, order, products }) => {
    const [amountPaid, setAmountPaid] = useState<number | ''>('');
    const [errors, setErrors] = useState<Map<number, string>>(new Map());
    const [isSaving, setIsSaving] = useState(false);

    useEffect(() => {
        if (isOpen && order) {
            setAmountPaid('');
            setErrors(new Map());
            setIsSaving(false);
        }
    }, [isOpen, order]);
    
    if (!order) return null;

    const handleConfirm = async () => {
        const newErrors = new Map<number, string>();
        let allValid = true;

        const itemsForSale: { productId: number; quantity: number }[] = [];

        for (const item of order.items) {
            const product = products.find(p => p.id === item.productId);
            const stock = product?.stock || 0;
            if (stock < item.quantity) {
                newErrors.set(item.productId, `Not enough stock. Available: ${stock}`);
                allValid = false;
                continue;
            }
            itemsForSale.push({ productId: item.productId, quantity: item.quantity });
        }
        
        setErrors(newErrors);
        
        if (allValid) {
            setIsSaving(true);
            try {
                const payload = {
                    orderId: order.id,
                    amountPaid: Number(amountPaid) || 0,
                    items: itemsForSale,
                };
                const response = await apiCall<{ savedSale: Sale; updatedProducts: Product[] }>('orders.php', 'POST', { action: 'convertToSale', data: payload });
                onConfirm(response.savedSale, response.updatedProducts);
            } catch(error) {
                console.error("Failed to convert order", error);
                alert(`Error converting order: ${(error as Error).message}`);
            } finally {
                setIsSaving(false);
            }
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={`Convert Order #${order.id} to Sale`}
            size="lg"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleConfirm} disabled={isSaving}>
                    {isSaving ? 'Confirming...' : 'Confirm & Create Sale'}
                </button>
            </>}
        >
            <p>Confirm stock availability and enter payment details to convert this order into a formal sale.</p>
            
            <table className="modal-items-table">
                <thead><tr><th>Product</th><th>Qty Ordered</th><th>Stock Available</th></tr></thead>
                <tbody>
                    {order.items.map(item => {
                        const product = products.find(p => p.id === item.productId);
                        const stock = product?.stock || 0;
                        const error = errors.get(item.productId);
                        return (
                            <tr key={item.productId} className={error ? 'row-error' : ''}>
                                <td>{item.name}</td>
                                <td>{item.quantity}</td>
                                <td>
                                    {stock}
                                    {error && <div className="input-error-message">{error}</div>}
                                </td>
                            </tr>
                        )
                    })}
                </tbody>
            </table>

            <div className="summary-details" style={{textAlign: 'left', margin: '1rem 0'}}>
                <p>Customer: <strong>{order.customerName}</strong></p>
                <p>Total Amount: <strong>{formatCurrency(order.totalAmount)}</strong></p>
            </div>
            <div className="form-group">
                <label htmlFor="amount-paid-convert">Amount Paid</label>
                <input 
                    type="number" 
                    id="amount-paid-convert" 
                    value={amountPaid} 
                    placeholder="0.00" 
                    onChange={e => setAmountPaid(Number(e.target.value) >= 0 ? Number(e.target.value) : '')} 
                    min="0"
                    max={order.totalAmount}
                />
            </div>
        </Modal>
    );
};

const OrdersPage: React.FC<{
    orders: Order[];
    setOrders: React.Dispatch<React.SetStateAction<Order[]>>;
    setSales: React.Dispatch<React.SetStateAction<Sale[]>>;
    products: Product[];
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
    contacts: Contact[];
}> = ({ orders, setOrders, setSales, products, setProducts, contacts }) => {
    const [isAddModalOpen, setIsAddModalOpen] = useState(false);
    const [isConvertModalOpen, setIsConvertModalOpen] = useState(false);
    const [orderToConvert, setOrderToConvert] = useState<Order | null>(null);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const itemsPerPage = 10;

    const filteredOrders = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return orders;

        return orders.filter(o => {
            const searchableText = `${o.customerName.toLowerCase()} #${o.id} ${o.status.toLowerCase()}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [orders, searchTerm]);

    const paginatedOrders = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredOrders.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredOrders, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);

    const handleSaveOrder = (newOrder: Order) => {
        setOrders(prev => [newOrder, ...prev]);
        setIsAddModalOpen(false);
    };

    const handleOpenConvertToSale = (order: Order) => {
        setOrderToConvert(order);
        setIsConvertModalOpen(true);
    };
    
    const handleConfirmConversion = async (newSale: Sale, updatedProducts: Product[]) => {
        if (!orderToConvert) return;
        
        setSales(prev => [newSale, ...prev]);

        const updatedProductsMap = new Map(updatedProducts.map(p => [p.id, p]));
        setProducts(prev => prev.map(p => updatedProductsMap.get(p.id) || p));

        setOrders(prev => prev.filter(o => o.id !== orderToConvert.id));

        setIsConvertModalOpen(false);
        setOrderToConvert(null);
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Customer Orders</h1>
                <div className="page-actions">
                    <button className="button" onClick={() => setIsAddModalOpen(true)}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New Order</span>
                    </button>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by customer, ID..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
            </div>
            <div className="card">
                <table className="orders-table">
                    <thead>
                        <tr>
                            <th>Order ID</th>
                            <th>Customer</th>
                            <th>Date</th>
                            <th className="text-right">Total Amount</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedOrders.map((order) => (
                            <tr key={order.id}>
                                <td>#{order.id}</td>
                                <td>{order.customerName}</td>
                                <td>{order.date}</td>
                                <td className="text-right">{formatCurrency(order.totalAmount)}</td>
                                <td>
                                    <button className="button" onClick={() => handleOpenConvertToSale(order)}>
                                        Convert to Sale
                                    </button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredOrders.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <AddOrderModal
                isOpen={isAddModalOpen}
                onClose={() => setIsAddModalOpen(false)}
                onSave={handleSaveOrder}
                products={products}
                contacts={contacts}
            />
            <ConvertToSaleModal
                isOpen={isConvertModalOpen}
                onClose={() => setIsConvertModalOpen(false)}
                onConfirm={handleConfirmConversion}
                order={orderToConvert}
                products={products}
            />
        </>
    );
};


// --- CONTACTS PAGE ---
const ContactModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (contact: Contact) => void;
    contactToEdit: Contact | null;
}> = ({ isOpen, onClose, onSave, contactToEdit }) => {
    const [contact, setContact] = useState<Omit<Contact, 'id'>>({ name: '', email: '', role: 'Customer', creditLimit: 0 });
    const [isSaving, setIsSaving] = useState(false);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setContact(contactToEdit || { name: '', email: '', role: 'Customer', creditLimit: 0 });
        }
    }, [isOpen, contactToEdit]);

    const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
        const { name, value } = e.target;
        if (name === 'creditLimit') {
            setContact(prev => ({ ...prev, [name]: parseFloat(value) || 0 }));
        } else {
            setContact(prev => ({ ...prev, [name]: value as any }));
        }
    };

    const handleSave = async () => {
        setIsSaving(true);
        try {
            const payload = {
                ...contact,
                ...(contactToEdit && { id: contactToEdit.id }),
            };
            const action = contactToEdit ? 'update' : 'create';
            const savedContact = await apiCall<Contact>('contacts.php', 'POST', { action, data: payload });
            onSave(savedContact);
        } catch (error) {
            console.error("Failed to save contact", error);
            alert(`Error saving contact: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={contactToEdit ? 'Edit Contact' : 'Add New Contact'}
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Saving...' : 'Save Contact'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="name">Name</label>
                <input type="text" id="name" name="name" value={contact.name} onChange={handleChange} />
            </div>
            <div className="form-group">
                <label htmlFor="email">Email</label>
                <input type="email" id="email" name="email" value={contact.email} onChange={handleChange} />
            </div>
            <div className="form-group">
                <label htmlFor="role">Role</label>
                <select id="role" name="role" value={contact.role} onChange={handleChange}>
                    <option value="Customer">Customer</option>
                    <option value="Vendor">Vendor</option>
                </select>
            </div>
            {contact.role === 'Customer' && (
                <div className="form-group">
                    <label htmlFor="creditLimit">Credit Limit</label>
                    <input type="number" id="creditLimit" name="creditLimit" value={contact.creditLimit || ''} onChange={handleChange} min="0" />
                </div>
            )}
        </Modal>
    );
};

const ContactsPage: React.FC<{
    contacts: Contact[];
    setContacts: React.Dispatch<React.SetStateAction<Contact[]>>;
    sales: Sale[];
    purchases: Purchase[];
}> = ({ contacts, setContacts, sales, purchases }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [isConfirmOpen, setIsConfirmOpen] = useState(false);
    const [editingContact, setEditingContact] = useState<Contact | null>(null);
    const [contactToDelete, setContactToDelete] = useState<Contact | null>(null);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const [isDeleting, setIsDeleting] = useState(false);
    const itemsPerPage = 10;

    const filteredContacts = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return contacts;
        
        return contacts.filter(c => {
            const searchableText = `${c.name.toLowerCase()} ${c.email.toLowerCase()} ${c.role.toLowerCase()}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [contacts, searchTerm]);

    const paginatedContacts = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredContacts.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredContacts, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);

    const calculateBalance = useCallback((contact: Contact) => {
        if (contact.role === 'Customer') {
            return sales
                .filter(s => s.customerId === contact.id)
                .reduce((total, sale) => total + sale.balance, 0);
        } else {
            return purchases
                .filter(p => p.vendorId === contact.id)
                .reduce((total, purchase) => total + purchase.balance, 0);
        }
    }, [sales, purchases]);

    const getContactStats = useCallback((contact: Contact) => {
        if (contact.role === 'Customer') {
            const customerSales = sales.filter(s => s.customerId === contact.id);
            return {
                totalOrders: customerSales.length,
                pendingOrders: customerSales.filter(s => s.status !== 'Paid').length,
            };
        }
        if (contact.role === 'Vendor') {
            const vendorPurchases = purchases.filter(p => p.vendorId === contact.id);
            return {
                totalOrders: vendorPurchases.length,
                pendingOrders: vendorPurchases.filter(p => p.status !== 'Paid').length,
            };
        }
        return { totalOrders: 0, pendingOrders: 0 };
    }, [sales, purchases]);


    const handleOpenAddModal = () => {
        setEditingContact(null);
        setIsModalOpen(true);
    };

    const handleOpenEditModal = (contact: Contact) => {
        setEditingContact(contact);
        setIsModalOpen(true);
    };

    const handleOpenDeleteConfirm = (contact: Contact) => {
        setContactToDelete(contact);
        setIsConfirmOpen(true);
    };

    const handleCloseModals = () => {
        setIsModalOpen(false);
        setIsConfirmOpen(false);
        setEditingContact(null);
        setContactToDelete(null);
    };

    const handleSaveContact = (savedContact: Contact) => {
        if (editingContact) {
            setContacts(contacts.map(c => c.id === savedContact.id ? savedContact : c));
        } else {
            setContacts([savedContact, ...contacts]);
        }
        handleCloseModals();
    };

    const handleConfirmDelete = async () => {
        if (contactToDelete) {
            setIsDeleting(true);
            try {
                await apiCall('contacts.php', 'POST', { action: 'delete', data: { id: contactToDelete.id } });
                setContacts(contacts.filter(c => c.id !== contactToDelete.id));
            } catch(error) {
                console.error("Failed to delete contact", error);
                alert(`Error deleting contact: ${(error as Error).message}`);
            } finally {
                setIsDeleting(false);
                handleCloseModals();
            }
        }
    };

    const handleExport = (format: 'csv' | 'pdf') => {
        const dataWithStats = contacts.map(c => {
            const { totalOrders, pendingOrders } = getContactStats(c);
            return {
                ...c,
                balance: calculateBalance(c),
                totalOrders,
                pendingOrders,
            }
        });

        if(format === 'csv') {
            const headers = ['Name', 'Email', 'Role', 'Credit Limit', 'Total Orders', 'Pending Orders', 'Outstanding Balance'];
            const data = dataWithStats.map(c => [c.name, c.email, c.role, c.creditLimit || 0, c.totalOrders, c.pendingOrders, c.balance.toFixed(2)]);
            downloadAsCsv('contacts-report', headers, data);
        } else {
            const headers = [
                { header: 'Name', dataKey: 'name' },
                { header: 'Email', dataKey: 'email' },
                { header: 'Role', dataKey: 'role' },
                { header: 'Credit Limit', dataKey: 'creditLimit' },
                { header: 'Total Orders', dataKey: 'totalOrders' },
                { header: 'Pending Orders', dataKey: 'pendingOrders' },
                { header: 'Outstanding Balance', dataKey: 'balance' },
            ];
            const data = dataWithStats.map(c => ({
                ...c,
                creditLimit: formatCurrency(c.creditLimit || 0),
                balance: formatCurrency(c.balance)
            }));
            downloadAsPdf('contacts-report', 'Contacts Report', headers, data);
        }
    }

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Contacts</h1>
                <div className="page-actions">
                    <button className="button" onClick={handleOpenAddModal}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New Contact</span>
                    </button>
                     <div className="button-group">
                        <button className="button-secondary" onClick={() => handleExport('csv')}>
                            <span className="material-symbols-outlined">description</span>
                            <span>CSV</span>
                        </button>
                        <button className="button-secondary" onClick={() => handleExport('pdf')}>
                            <span className="material-symbols-outlined">picture_as_pdf</span>
                            <span>PDF</span>
                        </button>
                    </div>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by name, email, or role..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                {searchTerm && (
                    <div className="active-filter-display">
                        <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                        <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                            <span className="material-symbols-outlined">close</span>
                        </button>
                    </div>
                )}
            </div>
            <div className="card">
                <table className="contacts-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Role</th>
                            <th className="text-right">Credit Limit</th>
                            <th className="text-right">Total Orders</th>
                            <th className="text-right">Pending Orders</th>
                            <th className="text-right">Outstanding Balance</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedContacts.map((contact) => {
                            const { totalOrders, pendingOrders } = getContactStats(contact);
                            return (
                                <tr key={contact.id}>
                                    <td>{contact.name}</td>
                                    <td>{contact.email}</td>
                                    <td>
                                        <span className={`role-badge role-${contact.role.toLowerCase()}`}>
                                            {contact.role}
                                        </span>
                                    </td>
                                    <td className="text-right">{contact.role === 'Customer' ? formatCurrency(contact.creditLimit || 0) : 'N/A'}</td>
                                    <td className="text-right">{totalOrders}</td>
                                    <td className="text-right">{pendingOrders}</td>
                                    <td className="text-right">{formatCurrency(calculateBalance(contact))}</td>
                                    <td className="actions-cell">
                                        <button className="icon-button" aria-label="Edit contact" onClick={() => handleOpenEditModal(contact)}>
                                            <span className="material-symbols-outlined">edit</span>
                                        </button>
                                        <button className="icon-button icon-button-delete" aria-label="Delete contact" onClick={() => handleOpenDeleteConfirm(contact)}>
                                            <span className="material-symbols-outlined">delete</span>
                                        </button>
                                    </td>
                                </tr>
                            );
                        })}
                    </tbody>
                </table>
                <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredContacts.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <ContactModal
                isOpen={isModalOpen}
                onClose={handleCloseModals}
                onSave={handleSaveContact}
                contactToEdit={editingContact}
            />
            <ConfirmationModal
                isOpen={isConfirmOpen}
                onClose={handleCloseModals}
                onConfirm={handleConfirmDelete}
                isSaving={isDeleting}
                title="Confirm Deletion"
                message={`Are you sure you want to delete the contact "${contactToDelete?.name}"? This action cannot be undone.`}
            />
        </>
    );
};

// --- PAYMENTS PAGE ---
const AddPaymentModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (payment: Payment, updatedTransaction: Sale | Purchase) => void;
    sales: Sale[];
    purchases: Purchase[];
}> = ({ isOpen, onClose, onSave, sales, purchases }) => {
    const [type, setType] = useState<'Sale' | 'Purchase'>('Sale');
    const [transactionId, setTransactionId] = useState<number | ''>('');
    const [amount, setAmount] = useState<number | ''>('');
    const [method, setMethod] = useState<Payment['method']>('Cash');
    const [reference, setReference] = useState('');
    const [isSaving, setIsSaving] = useState(false);

    const transactionsWithBalance = useMemo(() => {
        if (type === 'Sale') {
            return sales.filter(s => s.balance > 0).map(s => ({ id: s.id, name: `#${s.id} - ${s.customerName}`, balance: s.balance }));
        } else {
            return purchases.filter(p => p.balance > 0).map(p => ({ id: p.id, name: `#${p.id} - ${p.vendorName}`, balance: p.balance }));
        }
    }, [type, sales, purchases]);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setType('Sale');
            setTransactionId('');
            setAmount('');
            setMethod('Cash');
            setReference('');
        }
    }, [isOpen]);

    useEffect(() => {
        setTransactionId('');
        setAmount('');
    }, [type]);

    useEffect(() => {
        if (transactionId) {
            const selected = transactionsWithBalance.find(t => t.id === transactionId);
            if (selected) {
                setAmount(selected.balance);
            }
        }
    }, [transactionId, transactionsWithBalance]);

    const handleSave = async () => {
        if (!transactionId || !amount || Number(amount) <= 0) {
            alert('Please select a transaction and enter a valid amount.');
            return;
        }

        setIsSaving(true);
        try {
            const payload = {
                type,
                transactionId,
                amount: Number(amount),
                method,
                reference
            };
            const response = await apiCall<{ savedPayment: Payment; updatedTransaction: Sale | Purchase }>('payments.php', 'POST', { action: 'create', data: payload });
            onSave(response.savedPayment, response.updatedTransaction);
        } catch (error) {
            console.error("Failed to save payment", error);
            alert(`Error saving payment: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };
    
    const maxAmount = transactionsWithBalance.find(t => t.id === transactionId)?.balance || 0;

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Record Payment"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Saving...' : 'Save Payment'}
                </button>
            </>}
        >
            <div className="form-toggle">
                <button className={type === 'Sale' ? 'active' : ''} onClick={() => setType('Sale')}>Payment Received (Sale)</button>
                <button className={type === 'Purchase' ? 'active' : ''} onClick={() => setType('Purchase')}>Payment Made (Purchase)</button>
            </div>
            <div className="form-group">
                <label htmlFor="transactionId">{type === 'Sale' ? 'Sales Invoice' : 'Purchase Order'}</label>
                <select id="transactionId" value={transactionId} onChange={e => setTransactionId(Number(e.target.value))}>
                    <option value="" disabled>Select an unpaid transaction</option>
                    {transactionsWithBalance.map(t => <option key={t.id} value={t.id}>{t.name} (Balance: {formatCurrency(t.balance)})</option>)}
                </select>
            </div>
            <div className="form-row">
                <div className="form-group">
                    <label htmlFor="amount">Amount</label>
                    <input type="number" id="amount" value={amount} onChange={e => setAmount(Number(e.target.value))} min="0.01" max={maxAmount} disabled={!transactionId} />
                </div>
                <div className="form-group">
                    <label htmlFor="method">Payment Method</label>
                    <select id="method" value={method} onChange={e => setMethod(e.target.value as any)}>
                        <option>Cash</option>
                        <option>Bank Transfer</option>
                        <option>Credit Card</option>
                        <option>Mobile Wallet</option>
                    </select>
                </div>
            </div>
            <div className="form-group">
                <label htmlFor="reference">Reference # (Optional)</label>
                <input type="text" id="reference" value={reference} onChange={e => setReference(e.target.value)} />
            </div>
        </Modal>
    );
};

const PaymentsPage: React.FC<{
    payments: Payment[];
    setPayments: React.Dispatch<React.SetStateAction<Payment[]>>;
    sales: Sale[];
    setSales: React.Dispatch<React.SetStateAction<Sale[]>>;
    purchases: Purchase[];
    setPurchases: React.Dispatch<React.SetStateAction<Purchase[]>>;
}> = ({ payments, setPayments, sales, setSales, purchases, setPurchases }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const itemsPerPage = 10;

    const filteredPayments = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return payments;

        return payments.filter(p => {
            const searchableText = `${p.contactName.toLowerCase()} #${p.transactionId} ${p.method.toLowerCase()} ${p.reference.toLowerCase()}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [payments, searchTerm]);

    const paginatedPayments = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredPayments.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredPayments, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);
    
    const handleSavePayment = (newPayment: Payment, updatedTransaction: Sale | Purchase) => {
        if (newPayment.type === 'Sale') {
            setSales(prev => prev.map(s => s.id === updatedTransaction.id ? updatedTransaction as Sale : s));
        } else {
            setPurchases(prev => prev.map(p => p.id === updatedTransaction.id ? updatedTransaction as Purchase : p));
        }

        setPayments([newPayment, ...payments]);
        setIsModalOpen(false);
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Payments</h1>
                <div className="page-actions">
                    <button className="button" onClick={() => setIsModalOpen(true)}>
                        <span className="material-symbols-outlined">add_card</span>
                        <span>Record Payment</span>
                    </button>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by contact, ID, method..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                {searchTerm && (
                    <div className="active-filter-display">
                        <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                        <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                            <span className="material-symbols-outlined">close</span>
                        </button>
                    </div>
                )}
            </div>
            <div className="card">
                <table className="payments-table">
                    <thead>
                        <tr>
                            <th>Date</th>
                            <th>Type</th>
                            <th>Transaction ID</th>
                            <th>Contact</th>
                            <th className="text-right">Amount</th>
                            <th>Method</th>
                            <th>Reference</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedPayments.map(p => (
                            <tr key={p.id}>
                                <td>{p.date}</td>
                                <td>{p.type}</td>
                                <td>#{p.transactionId}</td>
                                <td>{p.contactName}</td>
                                <td className="text-right">{formatCurrency(p.amount)}</td>
                                <td>{p.method}</td>
                                <td>{p.reference || 'N/A'}</td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredPayments.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <AddPaymentModal 
                isOpen={isModalOpen}
                onClose={() => setIsModalOpen(false)}
                onSave={handleSavePayment}
                sales={sales}
                purchases={purchases}
            />
        </>
    );
};


// --- USERS PAGE ---
const UserModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (user: User) => void;
    userToEdit: User | null;
}> = ({ isOpen, onClose, onSave, userToEdit }) => {
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [role, setRole] = useState<Role>('Staff');
    const [password, setPassword] = useState('');
    const [confirmPassword, setConfirmPassword] = useState('');
    const [isSaving, setIsSaving] = useState(false);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            if (userToEdit) {
                setName(userToEdit.name);
                setEmail(userToEdit.email);
                setRole(userToEdit.role);
            } else {
                setName('');
                setEmail('');
                setRole('Staff');
            }
            setPassword('');
            setConfirmPassword('');
        }
    }, [isOpen, userToEdit]);

    const handleSave = async () => {
        if (password) {
            if (password !== confirmPassword) {
                alert("Passwords do not match.");
                return;
            }
        } else if (!userToEdit) {
            alert("Password is required for new users.");
            return;
        }
        
        setIsSaving(true);
        try {
            const payload = {
                name, email, role,
                ...(password && { password }),
                ...(userToEdit && { id: userToEdit.id }),
            };
            const action = userToEdit ? 'update' : 'create';
            const savedUser = await apiCall<User>('users.php', 'POST', { action, data: payload });
            onSave(savedUser);
        } catch (error) {
            console.error("Failed to save user", error);
            alert(`Error saving user: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={userToEdit ? 'Edit User' : 'Add New User'}
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Saving...' : 'Save User'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="user-name">Full Name</label>
                <input type="text" id="user-name" value={name} onChange={e => setName(e.target.value)} />
            </div>
            <div className="form-group">
                <label htmlFor="user-email">Email Address</label>
                <input type="email" id="user-email" value={email} onChange={e => setEmail(e.target.value)} />
            </div>
            <div className="form-group">
                <label htmlFor="user-role">Role</label>
                <select id="user-role" name="role" value={role} onChange={e => setRole(e.target.value as Role)}>
                    <option value="Admin">Admin</option>
                    <option value="Manager">Manager</option>
                    <option value="Staff">Staff</option>
                </select>
            </div>
             <hr className="profile-modal-separator" />
             <h3 className="profile-modal-section-title">{userToEdit ? 'Change Password' : 'Set Password'}</h3>
             <div className="form-group">
                <label htmlFor="user-password">New Password</label>
                <input type="password" id="user-password" value={password} onChange={e => setPassword(e.target.value)} placeholder={userToEdit ? 'Leave blank to keep unchanged' : ''} />
            </div>
            <div className="form-group">
                <label htmlFor="user-confirm-password">Confirm New Password</label>
                <input type="password" id="user-confirm-password" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} />
            </div>
        </Modal>
    );
};


const UsersPage: React.FC<{
    users: User[];
    setUsers: React.Dispatch<React.SetStateAction<User[]>>;
    currentUser: User | null;
}> = ({ users, setUsers, currentUser }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [isConfirmOpen, setIsConfirmOpen] = useState(false);
    const [editingUser, setEditingUser] = useState<User | null>(null);
    const [userToDelete, setUserToDelete] = useState<User | null>(null);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const [isDeleting, setIsDeleting] = useState(false);
    const itemsPerPage = 10;

    const filteredUsers = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return users;
        
        return users.filter(u => {
            const searchableText = `${u.name.toLowerCase()} ${u.email.toLowerCase()}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [users, searchTerm]);

    const paginatedUsers = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredUsers.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredUsers, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);

    const handleOpenAddModal = () => {
        setEditingUser(null);
        setIsModalOpen(true);
    };

    const handleOpenEditModal = (user: User) => {
        setEditingUser(user);
        setIsModalOpen(true);
    };

    const handleOpenDeleteConfirm = (user: User) => {
        setUserToDelete(user);
        setIsConfirmOpen(true);
    };

    const handleCloseModals = () => {
        setIsModalOpen(false);
        setIsConfirmOpen(false);
        setEditingUser(null);
        setUserToDelete(null);
    };

    const handleSaveUser = (savedUser: User) => {
        if (editingUser) {
            setUsers(users.map(u => u.id === savedUser.id ? savedUser : u));
        } else {
            setUsers([savedUser, ...users]);
        }
        handleCloseModals();
    };

    const handleConfirmDelete = async () => {
        if (userToDelete) {
            if (userToDelete.id === currentUser?.id) {
                 alert("You cannot delete the currently active user.");
                 handleCloseModals();
                 return;
            }
            setIsDeleting(true);
            try {
                await apiCall('users.php', 'POST', { action: 'delete', data: { id: userToDelete.id } });
                setUsers(users.filter(u => u.id !== userToDelete.id));
            } catch (error) {
                console.error("Failed to delete user", error);
                alert(`Error deleting user: ${(error as Error).message}`);
            } finally {
                setIsDeleting(false);
                handleCloseModals();
            }
        }
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">User Management</h1>
                <div className="page-actions">
                    <button className="button" onClick={handleOpenAddModal}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New User</span>
                    </button>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by name or email..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                {searchTerm && (
                    <div className="active-filter-display">
                        <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                        <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                            <span className="material-symbols-outlined">close</span>
                        </button>
                    </div>
                )}
            </div>
            <div className="card">
                <table className="users-table">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Role</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedUsers.map((user) => (
                            <tr key={user.id}>
                                <td>{user.name}{user.id === currentUser?.id && ' (You)'}</td>
                                <td>{user.email}</td>
                                <td>
                                    <span className={`role-badge role-${user.role.toLowerCase()}`}>
                                        {user.role}
                                    </span>
                                </td>
                                <td className="actions-cell">
                                    <button className="icon-button" aria-label="Edit user" onClick={() => handleOpenEditModal(user)}>
                                        <span className="material-symbols-outlined">edit</span>
                                    </button>
                                    <button 
                                        className="icon-button icon-button-delete" 
                                        aria-label="Delete user" 
                                        onClick={() => handleOpenDeleteConfirm(user)}
                                        disabled={user.id === currentUser?.id}
                                    >
                                        <span className="material-symbols-outlined">delete</span>
                                    </button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredUsers.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <UserModal
                isOpen={isModalOpen}
                onClose={handleCloseModals}
                onSave={handleSaveUser}
                userToEdit={editingUser}
            />
            <ConfirmationModal
                isOpen={isConfirmOpen}
                onClose={handleCloseModals}
                onConfirm={handleConfirmDelete}
                isSaving={isDeleting}
                title="Confirm Deletion"
                message={`Are you sure you want to delete the user "${userToDelete?.name}"? This action cannot be undone.`}
            />
        </>
    );
};

// --- AUDIT TRAIL PAGE ---
const AuditTrailPage: React.FC<{ log: AuditLogEntry[] }> = ({ log }) => {
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const itemsPerPage = 15;

    const filteredLog = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return log;

        return log.filter(entry => {
            const searchableText = `${entry.userName.toLowerCase()} ${entry.action.toLowerCase()} ${entry.details.toLowerCase()}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [log, searchTerm]);

    const paginatedLog = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredLog.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredLog, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Audit Trail</h1>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input
                        type="search"
                        placeholder="Search by user, action, or details..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                 {searchTerm && (
                    <div className="active-filter-display">
                        <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                        <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                            <span className="material-symbols-outlined">close</span>
                        </button>
                    </div>
                )}
            </div>
            <div className="card">
                <table className="audit-table">
                    <thead>
                        <tr>
                            <th>Timestamp</th>
                            <th>User</th>
                            <th>Action</th>
                            <th>Details</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedLog.map((entry) => (
                            <tr key={entry.id}>
                                <td>{new Date(entry.timestamp).toLocaleString()}</td>
                                <td>{entry.userName}</td>
                                <td>{entry.action}</td>
                                <td>{entry.details}</td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                <Pagination
                    currentPage={currentPage}
                    totalItems={filteredLog.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
        </>
    );
};

// --- EXPENSES PAGE ---
const ManageCategoriesModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    categories: ExpenseCategory[];
    setCategories: React.Dispatch<React.SetStateAction<ExpenseCategory[]>>;
    expenses: Expense[];
}> = ({ isOpen, onClose, categories, setCategories, expenses }) => {
    const [newCategoryName, setNewCategoryName] = useState('');
    const [editingCategoryId, setEditingCategoryId] = useState<number | null>(null);
    const [editingCategoryName, setEditingCategoryName] = useState('');
    const [selectedCategoryIds, setSelectedCategoryIds] = useState<Set<number>>(new Set());
    const [isConfirmOpen, setIsConfirmOpen] = useState(false);

    useEffect(() => {
        if (!isOpen) {
            setSelectedCategoryIds(new Set());
            setIsConfirmOpen(false);
        }
    }, [isOpen]);

    const handleAddCategory = async () => {
        if (!newCategoryName.trim()) return;
        
        try {
            const newCategory = await apiCall<ExpenseCategory>('expenses.php', 'POST', { action: 'createCategory', data: { name: newCategoryName.trim() }});
            setCategories(prev => [...prev, newCategory]);
            setNewCategoryName('');
        } catch (error) {
            alert(`Error: ${(error as Error).message}`);
        }
    };

    const handleDeleteCategory = async (categoryId: number) => {
        const isUsed = expenses.some(e => e.categoryId === categoryId);
        if (isUsed) {
            alert('Cannot delete a category that is currently in use.');
            return;
        }
        
        try {
            await apiCall('expenses.php', 'POST', { action: 'deleteCategory', data: { id: categoryId }});
            setCategories(prev => prev.filter(c => c.id !== categoryId));
        } catch (error) {
             alert(`Error: ${(error as Error).message}`);
        }
    };

    const handleStartEdit = (category: ExpenseCategory) => {
        setEditingCategoryId(category.id);
        setEditingCategoryName(category.name);
    };
    
    const handleCancelEdit = () => {
        setEditingCategoryId(null);
        setEditingCategoryName('');
    };

    const handleSaveEdit = async () => {
        if (!editingCategoryId || !editingCategoryName.trim()) return;
        
        try {
            const updatedCategory = await apiCall<ExpenseCategory>('expenses.php', 'POST', { action: 'updateCategory', data: { id: editingCategoryId, name: editingCategoryName.trim() }});
            setCategories(prev => prev.map(c => c.id === editingCategoryId ? updatedCategory : c));
        } catch (error) {
            alert(`Error: ${(error as Error).message}`);
        }
        
        handleCancelEdit();
    };

    const handleToggleSelect = (categoryId: number) => {
        setSelectedCategoryIds(prev => {
            const newSelection = new Set(prev);
            if (newSelection.has(categoryId)) {
                newSelection.delete(categoryId);
            } else {
                newSelection.add(categoryId);
            }
            return newSelection;
        });
    };

    const handleOpenBulkDeleteConfirm = () => {
        if (selectedCategoryIds.size > 0) {
            setIsConfirmOpen(true);
        }
    };

    const handleConfirmBulkDelete = async () => {
        try {
            await apiCall('expenses.php', 'POST', { action: 'bulkDeleteCategories', data: { ids: Array.from(selectedCategoryIds) }});
            setCategories(prev => prev.filter(c => !selectedCategoryIds.has(c.id)));
        } catch (error) {
            alert(`Error: ${(error as Error).message}`);
        } finally {
            setSelectedCategoryIds(new Set());
            setIsConfirmOpen(false);
        }
    };


    return (
        <>
            <Modal 
                isOpen={isOpen} 
                onClose={onClose} 
                title="Manage Expense Categories" 
                size="sm"
                footer={selectedCategoryIds.size > 0 && (
                    <div className="category-bulk-delete-footer">
                        <span>{selectedCategoryIds.size} selected</span>
                        <button className="button button-danger" onClick={handleOpenBulkDeleteConfirm}>Delete Selected</button>
                    </div>
                )}
            >
                <div className="form-group">
                    <label>Add New Category</label>
                    <div className="add-category-form">
                        <input 
                            type="text" 
                            value={newCategoryName}
                            onChange={e => setNewCategoryName(e.target.value)}
                            placeholder="e.g., Utilities"
                        />
                        <button className="button" onClick={handleAddCategory}>Add</button>
                    </div>
                </div>
                <ul className="category-list">
                    {categories.map(category => (
                        <li key={category.id} className="category-item">
                            {editingCategoryId === category.id ? (
                                <>
                                    <input 
                                        type="text"
                                        value={editingCategoryName}
                                        onChange={e => setEditingCategoryName(e.target.value)}
                                        className="category-edit-input"
                                        autoFocus
                                    />
                                    <div className="category-item-actions">
                                        <button className="icon-button" onClick={handleSaveEdit} aria-label="Save"><span className="material-symbols-outlined">check</span></button>
                                        <button className="icon-button" onClick={handleCancelEdit} aria-label="Cancel"><span className="material-symbols-outlined">close</span></button>
                                    </div>
                                </>
                            ) : (
                                <>
                                    <div className="category-item-main">
                                        <input 
                                            type="checkbox" 
                                            checked={selectedCategoryIds.has(category.id)}
                                            onChange={() => handleToggleSelect(category.id)}
                                            aria-label={`Select category ${category.name}`}
                                        />
                                        <span>{category.name}</span>
                                    </div>
                                    <div className="category-item-actions">
                                        <button className="icon-button" onClick={() => handleStartEdit(category)} aria-label="Edit"><span className="material-symbols-outlined">edit</span></button>
                                        <button className="icon-button icon-button-delete" onClick={() => handleDeleteCategory(category.id)} aria-label="Delete"><span className="material-symbols-outlined">delete</span></button>
                                    </div>
                                </>
                            )}
                        </li>
                    ))}
                </ul>
            </Modal>
             <ConfirmationModal
                isOpen={isConfirmOpen}
                onClose={() => setIsConfirmOpen(false)}
                onConfirm={handleConfirmBulkDelete}
                title="Confirm Bulk Deletion"
                message={`Are you sure you want to delete the ${selectedCategoryIds.size} selected categories? Categories currently in use will not be deleted.`}
            />
        </>
    );
};

const ExpenseModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (expense: Expense) => void;
    expenseToEdit: Expense | null;
    categories: ExpenseCategory[];
}> = ({ isOpen, onClose, onSave, expenseToEdit, categories }) => {
    const [expense, setExpense] = useState({ date: '', description: '', categoryId: '', amount: '' });
    const [isSaving, setIsSaving] = useState(false);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            if (expenseToEdit) {
                setExpense({
                    date: expenseToEdit.date,
                    description: expenseToEdit.description,
                    categoryId: String(expenseToEdit.categoryId),
                    amount: String(expenseToEdit.amount),
                });
            } else {
                setExpense({ date: new Date().toISOString().split('T')[0], description: '', categoryId: '', amount: '' });
            }
        }
    }, [isOpen, expenseToEdit]);
    
    const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
        const { name, value } = e.target;
        setExpense(prev => ({ ...prev, [name]: value }));
    };

    const handleSave = async () => {
        if (!expense.date || !expense.description || !expense.categoryId || !expense.amount) {
            alert('Please fill out all fields.');
            return;
        }
        
        setIsSaving(true);
        try {
            const payload = {
                date: expense.date,
                description: expense.description,
                categoryId: Number(expense.categoryId),
                amount: parseFloat(expense.amount),
                ...(expenseToEdit && { id: expenseToEdit.id }),
            };
            const action = expenseToEdit ? 'update' : 'create';
            const savedExpense = await apiCall<Expense>('expenses.php', 'POST', { action, data: payload });
            onSave(savedExpense);
        } catch (error) {
            alert(`Error: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title={expenseToEdit ? 'Edit Expense' : 'Add New Expense'}
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Saving...' : 'Save Expense'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="date">Date</label>
                <input type="date" id="date" name="date" value={expense.date} onChange={handleChange} />
            </div>
            <div className="form-group">
                <label htmlFor="description">Description</label>
                <textarea id="description" name="description" value={expense.description} onChange={handleChange} rows={3}></textarea>
            </div>
            <div className="form-row">
                 <div className="form-group">
                    <label htmlFor="categoryId">Category</label>
                    <select id="categoryId" name="categoryId" value={expense.categoryId} onChange={handleChange}>
                        <option value="" disabled>Select a category</option>
                        {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                    </select>
                </div>
                <div className="form-group">
                    <label htmlFor="amount">Amount</label>
                    <input type="number" id="amount" name="amount" value={expense.amount} onChange={handleChange} min="0" step="0.01" placeholder="0.00" />
                </div>
            </div>
        </Modal>
    );
};

const ExpensesPage: React.FC<{
  expenses: Expense[];
  setExpenses: React.Dispatch<React.SetStateAction<Expense[]>>;
  categories: ExpenseCategory[];
  setCategories: React.Dispatch<React.SetStateAction<ExpenseCategory[]>>;
}> = ({ expenses, setExpenses, categories, setCategories }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false);
    const [isConfirmOpen, setIsConfirmOpen] = useState(false);
    const [editingExpense, setEditingExpense] = useState<Expense | null>(null);
    const [expenseToDelete, setExpenseToDelete] = useState<Expense | null>(null);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const [isDeleting, setIsDeleting] = useState(false);
    const itemsPerPage = 10;
    
    const filteredExpenses = useMemo(() => {
        const searchKeywords = searchTerm.toLowerCase().split(' ').filter(k => k);
        if (searchKeywords.length === 0) return expenses;

        return expenses.filter(e => {
            const searchableText = `${e.description.toLowerCase()} ${e.categoryName.toLowerCase()} ${e.amount}`;
            return searchKeywords.every(keyword => searchableText.includes(keyword));
        });
    }, [expenses, searchTerm]);

    const paginatedExpenses = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredExpenses.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredExpenses, currentPage, itemsPerPage]);

    useEffect(() => {
        setCurrentPage(1);
    }, [searchTerm]);

    const handleOpenAddModal = () => {
        setEditingExpense(null);
        setIsModalOpen(true);
    };
    
    const handleOpenEditModal = (expense: Expense) => {
        setEditingExpense(expense);
        setIsModalOpen(true);
    };

    const handleOpenDeleteConfirm = (expense: Expense) => {
        setExpenseToDelete(expense);
        setIsConfirmOpen(true);
    };

    const handleCloseModals = () => {
        setIsModalOpen(false);
        setIsConfirmOpen(false);
    };

    const handleSaveExpense = (savedExpense: Expense) => {
        if (editingExpense) { // Editing
            setExpenses(expenses.map(e => e.id === savedExpense.id ? savedExpense : e));
        } else { // Adding
            setExpenses([savedExpense, ...expenses]);
        }
        handleCloseModals();
    };
    
    const handleConfirmDelete = async () => {
        if (expenseToDelete) {
            setIsDeleting(true);
            try {
                await apiCall('expenses.php', 'POST', { action: 'delete', data: { id: expenseToDelete.id }});
                setExpenses(expenses.filter(e => e.id !== expenseToDelete.id));
            } catch (error) {
                alert(`Error: ${(error as Error).message}`);
            } finally {
                setIsDeleting(false);
                setIsConfirmOpen(false);
                setExpenseToDelete(null);
            }
        }
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Expenses</h1>
                <div className="page-actions">
                    <button className="button-secondary" onClick={() => setIsCategoryModalOpen(true)}>Manage Categories</button>
                    <button className="button" onClick={handleOpenAddModal}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Add New Expense</span>
                    </button>
                </div>
            </div>
             <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input 
                        type="search" 
                        placeholder="Search by description, category, amount..."
                        value={searchTerm}
                        onChange={e => setSearchTerm(e.target.value)}
                    />
                </div>
                {searchTerm && (
                    <div className="active-filter-display">
                        <span>Filtering by: <strong>"{searchTerm}"</strong></span>
                        <button className="icon-button" onClick={() => setSearchTerm('')} aria-label="Clear filter">
                            <span className="material-symbols-outlined">close</span>
                        </button>
                    </div>
                )}
            </div>
            <div className="card">
                <table className="expenses-table">
                    <thead>
                        <tr>
                            <th>Date</th>
                            <th>Description</th>
                            <th>Category</th>
                            <th className="text-right">Amount</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedExpenses.map((expense) => (
                            <tr key={expense.id}>
                                <td>{expense.date}</td>
                                <td>{expense.description}</td>
                                <td>{expense.categoryName}</td>
                                <td className="text-right">{formatCurrency(expense.amount)}</td>
                                <td className="actions-cell">
                                    <button className="icon-button" aria-label="Edit expense" onClick={() => handleOpenEditModal(expense)}>
                                        <span className="material-symbols-outlined">edit</span>
                                    </button>
                                    <button className="icon-button icon-button-delete" aria-label="Delete expense" onClick={() => handleOpenDeleteConfirm(expense)}>
                                        <span className="material-symbols-outlined">delete</span>
                                    </button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                <Pagination
                    currentPage={currentPage}
                    totalItems={filteredExpenses.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <ExpenseModal
                isOpen={isModalOpen}
                onClose={handleCloseModals}
                onSave={handleSaveExpense}
                expenseToEdit={editingExpense}
                categories={categories}
            />
            <ManageCategoriesModal
                isOpen={isCategoryModalOpen}
                onClose={() => setIsCategoryModalOpen(false)}
                categories={categories}
                setCategories={setCategories}
                expenses={expenses}
            />
            <ConfirmationModal
                isOpen={isConfirmOpen}
                onClose={() => setIsConfirmOpen(false)}
                onConfirm={handleConfirmDelete}
                isSaving={isDeleting}
                title="Confirm Deletion"
                message={`Are you sure you want to delete this expense: "${expenseToDelete?.description}"? This action cannot be undone.`}
            />
        </>
    );
};


// --- RETURNS PAGE ---
const AddReturnModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (newReturn: Return, updatedSale: Sale, updatedProducts: Product[]) => void;
    sales: Sale[];
    returns: Return[];
}> = ({ isOpen, onClose, onSave, sales, returns }) => {
    const [selectedSaleId, setSelectedSaleId] = useState<number | ''>('');
    const [itemsToReturn, setItemsToReturn] = useState<Map<number, number>>(new Map());
    const [isSaving, setIsSaving] = useState(false);

    const sale = useMemo(() => sales.find(s => s.id === selectedSaleId), [selectedSaleId, sales]);
    
    const previouslyReturnedQuantities = useMemo(() => {
        if (!sale) return new Map<number, number>();
        const returnedMap = new Map<number, number>();
        returns
            .filter(r => r.saleId === sale.id)
            .forEach(r => {
                r.items.forEach(item => {
                    returnedMap.set(item.productId, (returnedMap.get(item.productId) || 0) + item.quantity);
                });
            });
        return returnedMap;
    }, [sale, returns]);

    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setSelectedSaleId('');
            setItemsToReturn(new Map());
        }
    }, [isOpen]);

    useEffect(() => {
        setItemsToReturn(new Map());
    }, [selectedSaleId]);

    const handleQuantityChange = (productId: number, quantity: number, maxQuantity: number) => {
        const newQuantity = Math.max(0, Math.min(quantity, maxQuantity));
        setItemsToReturn(prev => new Map(prev).set(productId, newQuantity));
    };
    
    const handleSave = async () => {
        if (!sale) return;

        const returnItemsPayload = Array.from(itemsToReturn.entries())
            .filter(([, quantity]) => quantity > 0)
            .map(([productId, quantity]) => ({ productId, quantity }));

        if (returnItemsPayload.length === 0) {
            alert("No items selected for return.");
            return;
        }

        setIsSaving(true);
        try {
            const payload = {
                saleId: sale.id,
                items: returnItemsPayload,
            };
            const response = await apiCall<{
                newReturn: Return;
                updatedSale: Sale;
                updatedProducts: Product[];
            }>('returns.php', 'POST', { action: 'create', data: payload });
            onSave(response.newReturn, response.updatedSale, response.updatedProducts);
        } catch (error) {
            console.error("Failed to save return", error);
            alert(`Error saving return: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Create New Return"
            size="lg"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving || !sale || itemsToReturn.size === 0}>
                    {isSaving ? 'Logging...' : 'Log Return'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="saleId">Original Sales Invoice</label>
                <select id="saleId" value={selectedSaleId} onChange={e => setSelectedSaleId(Number(e.target.value))}>
                    <option value="" disabled>Select an invoice</option>
                    {sales.map(s => <option key={s.id} value={s.id}>#{s.id} - {s.customerName} ({s.date})</option>)}
                </select>
            </div>
            {sale && (
                <div className="returned-items-list">
                    <h4>Items from Sale #{sale.id}</h4>
                    <table className="modal-items-table">
                        <thead>
                            <tr>
                                <th>Product</th>
                                <th>Qty Sold</th>
                                <th>Price</th>
                                <th>Qty to Return</th>
                            </tr>
                        </thead>
                        <tbody>
                            {sale.items.map(item => {
                                const returnedQty = previouslyReturnedQuantities.get(item.productId) || 0;
                                const availableToReturn = item.quantity - returnedQty;

                                return (
                                <tr key={item.productId}>
                                    <td>{item.name}</td>
                                    <td className="text-right">{item.quantity}</td>
                                    <td className="text-right">{formatCurrency(item.price)}</td>
                                    <td>
                                        <input 
                                            type="number" 
                                            className="return-qty-input"
                                            value={itemsToReturn.get(item.productId) || ''}
                                            onChange={e => handleQuantityChange(item.productId, parseInt(e.target.value) || 0, availableToReturn)}
                                            min="0"
                                            max={availableToReturn}
                                            disabled={availableToReturn <= 0}
                                            placeholder="0"
                                        />
                                        <small> (Max: {availableToReturn})</small>
                                    </td>
                                </tr>
                                )
                            })}
                        </tbody>
                    </table>
                </div>
            )}
        </Modal>
    );
};

const ReturnsPage: React.FC<{
    returns: Return[];
    setReturns: React.Dispatch<React.SetStateAction<Return[]>>;
    sales: Sale[];
    setSales: React.Dispatch<React.SetStateAction<Sale[]>>;
    products: Product[];
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
}> = ({ returns, setReturns, sales, setSales, products, setProducts }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const itemsPerPage = 10;
    
    const filteredReturns = useMemo(() => {
        if (!searchTerm) return returns;
        const searchLower = searchTerm.toLowerCase();
        return returns.filter(r => 
            r.customerName.toLowerCase().includes(searchLower) ||
            String(r.saleId).includes(searchLower)
        );
    }, [returns, searchTerm]);

    const paginatedReturns = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredReturns.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredReturns, currentPage]);

    const handleSaveReturn = (newReturn: Return, updatedSale: Sale, updatedProducts: Product[]) => {
        setReturns(prev => [newReturn, ...prev]);
        
        const updatedProductsMap = new Map(updatedProducts.map(p => [p.id, p]));
        setProducts(prev => prev.map(p => updatedProductsMap.get(p.id) || p));

        setSales(prev => prev.map(s => s.id === updatedSale.id ? updatedSale : s));
        setIsModalOpen(false);
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Sales Returns</h1>
                <div className="page-actions">
                    <button className="button" onClick={() => setIsModalOpen(true)}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Log New Return</span>
                    </button>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input type="search" placeholder="Search by customer or sale ID..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} />
                </div>
            </div>
            <div className="card">
                <table className="returns-table">
                    <thead>
                        <tr>
                            <th>Return ID</th>
                            <th>Date</th>
                            <th>Original Sale ID</th>
                            <th>Customer</th>
                            <th className="text-right">Total Value</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedReturns.map(r => (
                            <tr key={r.id}>
                                <td>#{r.id}</td>
                                <td>{r.date}</td>
                                <td>#{r.saleId}</td>
                                <td>{r.customerName}</td>
                                <td className="text-right">{formatCurrency(r.totalValue)}</td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredReturns.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <AddReturnModal 
                isOpen={isModalOpen}
                onClose={() => setIsModalOpen(false)}
                onSave={handleSaveReturn}
                sales={sales}
                returns={returns}
            />
        </>
    );
};

// --- DAMAGES PAGE ---
const AddDamageModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSave: (damage: Damage, updatedProduct: Product) => void;
    products: Product[];
}> = ({ isOpen, onClose, onSave, products }) => {
    const [productId, setProductId] = useState<number | ''>('');
    const [quantity, setQuantity] = useState<number | ''>('');
    const [reason, setReason] = useState('');
    const [isSaving, setIsSaving] = useState(false);

    const product = useMemo(() => products.find(p => p.id === productId), [productId, products]);
    
    useEffect(() => {
        if (isOpen) {
            setIsSaving(false);
            setProductId('');
            setQuantity('');
            setReason('');
        }
    }, [isOpen]);

    const handleSave = async () => {
        if (!productId || !quantity || !reason.trim() || !product) {
            alert('Please fill all fields.');
            return;
        }
        
        setIsSaving(true);
        try {
            const payload = { productId, quantity: Number(quantity), reason };
            const response = await apiCall<{ savedDamage: Damage; updatedProduct: Product }>('damages.php', 'POST', { action: 'create', data: payload });
            onSave(response.savedDamage, response.updatedProduct);
        } catch(error) {
            console.error("Failed to log damage", error);
            alert(`Error logging damage: ${(error as Error).message}`);
        } finally {
            setIsSaving(false);
        }
    };
    
    const stockAvailable = product?.stock || 0;

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Log Damaged Stock"
            footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isSaving}>Cancel</button>
                <button className="button" onClick={handleSave} disabled={isSaving}>
                    {isSaving ? 'Logging...' : 'Log Damage'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="productId">Product</label>
                <select id="productId" value={productId} onChange={e => setProductId(Number(e.target.value))}>
                    <option value="" disabled>Select a product</option>
                    {products.filter(p => p.stock > 0).map(p => <option key={p.id} value={p.id}>{p.name} (Stock: {p.stock})</option>)}
                </select>
            </div>
            <div className="form-group">
                <label htmlFor="quantity">Quantity Damaged</label>
                <input type="number" id="quantity" value={quantity} onChange={e => setQuantity(Number(e.target.value))} min="1" max={stockAvailable} disabled={!productId} />
            </div>
            <div className="form-group">
                <label htmlFor="reason">Reason for Damage</label>
                <textarea id="reason" value={reason} onChange={e => setReason(e.target.value)} rows={3}></textarea>
            </div>
        </Modal>
    );
};


const DamagesPage: React.FC<{
    damages: Damage[];
    setDamages: React.Dispatch<React.SetStateAction<Damage[]>>;
    products: Product[];
    setProducts: React.Dispatch<React.SetStateAction<Product[]>>;
}> = ({ damages, setDamages, products, setProducts }) => {
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [currentPage, setCurrentPage] = useState(1);
    const itemsPerPage = 10;
    
    const filteredDamages = useMemo(() => {
        if (!searchTerm) return damages;
        const searchLower = searchTerm.toLowerCase();
        return damages.filter(d => 
            d.productName.toLowerCase().includes(searchLower) ||
            d.reason.toLowerCase().includes(searchLower)
        );
    }, [damages, searchTerm]);

    const paginatedDamages = useMemo(() => {
        const startIndex = (currentPage - 1) * itemsPerPage;
        return filteredDamages.slice(startIndex, startIndex + itemsPerPage);
    }, [filteredDamages, currentPage]);

    const handleSaveDamage = (damage: Damage, updatedProduct: Product) => {
        setDamages(prev => [damage, ...prev]);
        setProducts(prev => prev.map(p => p.id === updatedProduct.id ? updatedProduct : p));
        setIsModalOpen(false);
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Damaged Goods</h1>
                <div className="page-actions">
                    <button className="button" onClick={() => setIsModalOpen(true)}>
                        <span className="material-symbols-outlined">add</span>
                        <span>Log Damaged Stock</span>
                    </button>
                </div>
            </div>
            <div className="page-controls">
                <div className="search-container">
                    <span className="material-symbols-outlined">search</span>
                    <input type="search" placeholder="Search by product or reason..." value={searchTerm} onChange={e => setSearchTerm(e.target.value)} />
                </div>
            </div>
            <div className="card">
                <table className="damages-table">
                    <thead>
                        <tr>
                            <th>Log ID</th>
                            <th>Date</th>
                            <th>Product</th>
                            <th className="text-right">Quantity</th>
                            <th>Reason</th>
                        </tr>
                    </thead>
                    <tbody>
                        {paginatedDamages.map(d => (
                            <tr key={d.id}>
                                <td>#{d.id}</td>
                                <td>{d.date}</td>
                                <td>{d.productName}</td>
                                <td className="text-right">{d.quantity}</td>
                                <td>{d.reason}</td>
                            </tr>
                        ))}
                    </tbody>
                </table>
                 <Pagination 
                    currentPage={currentPage}
                    totalItems={filteredDamages.length}
                    itemsPerPage={itemsPerPage}
                    onPageChange={setCurrentPage}
                />
            </div>
            <AddDamageModal 
                isOpen={isModalOpen}
                onClose={() => setIsModalOpen(false)}
                onSave={handleSaveDamage}
                products={products}
            />
        </>
    );
};


// --- REPORTS PAGE / DASHBOARD ---
type DateRangePreset = 'week' | 'month' | 'quarter' | 'year' | 'custom';

const formatDate = (date: Date): string => date.toISOString().split('T')[0];

const getDateRange = (preset: DateRangePreset): { start: string, end: string } => {
    const now = new Date();
    let start = new Date(now);
    const end = new Date(now);

    switch (preset) {
        case 'week':
            const dayOfWeek = now.getDay(); // 0 = Sunday
            start.setDate(now.getDate() - dayOfWeek);
            break;
        case 'month':
            start = new Date(now.getFullYear(), now.getMonth(), 1);
            break;
        case 'quarter':
            const quarter = Math.floor(now.getMonth() / 3);
            start = new Date(now.getFullYear(), quarter * 3, 1);
            break;
        case 'year':
            start = new Date(now.getFullYear(), 0, 1);
            break;
        case 'custom': // Should be handled by custom inputs
            return { start: '', end: '' };
    }
    return { start: formatDate(start), end: formatDate(end) };
};

const DateRangeFilter: React.FC<{
    onDateChange: (startDate: string, endDate: string) => void;
}> = ({ onDateChange }) => {
    const [activePreset, setActivePreset] = useState<DateRangePreset>('month');
    const [customStart, setCustomStart] = useState('');
    const [customEnd, setCustomEnd] = useState('');

    const stableOnDateChange = useCallback(onDateChange, []);

    useEffect(() => {
        const initialRange = getDateRange('month');
        stableOnDateChange(initialRange.start, initialRange.end);
        setCustomStart(initialRange.start);
        setCustomEnd(initialRange.end);
    }, [stableOnDateChange]);

    const handlePresetClick = (preset: DateRangePreset) => {
        setActivePreset(preset);
        if (preset !== 'custom') {
            const { start, end } = getDateRange(preset);
            onDateChange(start, end);
            setCustomStart(start);
            setCustomEnd(end);
        }
    };

    useEffect(() => {
        if (activePreset === 'custom' && customStart && customEnd) {
            onDateChange(customStart, customEnd);
        }
    }, [customStart, customEnd, activePreset, onDateChange]);

    const presets: { id: DateRangePreset, label: string }[] = [
        { id: 'week', label: 'This Week' },
        { id: 'month', label: 'This Month' },
        { id: 'quarter', label: 'This Quarter' },
        { id: 'year', label: 'This Year' },
    ];

    return (
        <div className="date-range-filter">
            <div className="button-group">
                {presets.map(p => (
                    <button
                        key={p.id}
                        className={`button-secondary ${activePreset === p.id ? 'active' : ''}`}
                        onClick={() => handlePresetClick(p.id)}
                    >{p.label}</button>
                ))}
            </div>
            <div className="custom-date-inputs">
                <input type="date" value={customStart} onChange={e => { setCustomStart(e.target.value); setActivePreset('custom'); }} />
                <span>to</span>
                <input type="date" value={customEnd} onChange={e => { setCustomEnd(e.target.value); setActivePreset('custom'); }} />
            </div>
        </div>
    );
};

const SalesByMonthChart: React.FC<{ data: { month: string; totalSales: number }[] }> = ({ data }) => {
    const maxValue = useMemo(() => {
        if (data.length === 0) return 0;
        return Math.max(...data.map(d => d.totalSales));
    }, [data]);
    
    if (data.length === 0) {
        return <p className="no-data-message">No sales data for this period.</p>;
    }

    return (
        <div className="sales-chart-container">
            <div className="chart-bars">
                {data.map(item => (
                    <div key={item.month} className="chart-bar-item" title={formatCurrency(item.totalSales)}>
                        <div className="chart-bar-value">{`Rs.${(item.totalSales / 1000).toFixed(1)}k`}</div>
                        <div 
                            className="chart-bar" 
                            style={{ height: `${maxValue > 0 ? (item.totalSales / maxValue) * 100 : 0}%` }}
                        />
                        <div className="chart-bar-label">{item.month}</div>
                    </div>
                ))}
            </div>
        </div>
    );
};

const TopProductsChart: React.FC<{ data: { name: string; quantity: number }[] }> = ({ data }) => {
    const maxValue = useMemo(() => {
        if (data.length === 0) return 0;
        return Math.max(...data.map(d => d.quantity));
    }, [data]);

    if (data.length === 0) {
        return <p className="no-data-message">No products sold in this period.</p>;
    }

    return (
        <div className="top-products-chart-container">
            {data.map(product => (
                <div key={product.name} className="product-bar-item">
                    <span className="product-bar-label" title={product.name}>{product.name}</span>
                    <div className="product-bar-bg">
                        <div 
                            className="product-bar-fill"
                            style={{ width: `${maxValue > 0 ? (product.quantity / maxValue) * 100 : 0}%` }}
                        />
                    </div>
                     <span className="product-bar-value">{product.quantity.toLocaleString()}</span>
                </div>
            ))}
        </div>
    );
};

const ReportsDashboardPage: React.FC<{
    products: Product[];
    sales: Sale[];
    purchases: Purchase[];
    contacts: Contact[];
    expenses: Expense[];
}> = ({ products, sales, purchases, contacts, expenses }) => {
    const [startDate, setStartDate] = useState('');
    const [endDate, setEndDate] = useState('');
    const [selectedCustomerId, setSelectedCustomerId] = useState<number | ''>('');
    
    const customers = useMemo(() => contacts.filter(c => c.role === 'Customer'), [contacts]);

    const handleDateChange = useCallback((start: string, end: string) => {
        setStartDate(start);
        setEndDate(end);
    }, []);

    const {
        filteredSales,
        filteredPurchases,
        filteredExpenses
    } = useMemo(() => {
        if (!startDate || !endDate) return { filteredSales: [], filteredPurchases: [], filteredExpenses: [] };
        
        const start = startDate;
        const end = endDate;
        
        return {
            filteredSales: sales.filter(s => s.date >= start && s.date <= end),
            filteredPurchases: purchases.filter(p => p.date >= start && p.date <= end),
            filteredExpenses: expenses.filter(e => e.date >= start && e.date <= end),
        };
    }, [startDate, endDate, sales, purchases, expenses]);

    const {
        totalRevenue,
        cogs,
        totalExpenses,
        netProfit,
    } = useMemo(() => {
        const revenue = filteredSales.reduce((sum, s) => sum + s.totalAmount, 0);
        const cost = filteredPurchases.reduce((sum, p) => sum + p.totalAmount, 0);
        const expenseTotal = filteredExpenses.reduce((sum, e) => sum + e.amount, 0);
        const profit = revenue - cost - expenseTotal;
        return { totalRevenue: revenue, cogs: cost, totalExpenses: expenseTotal, netProfit: profit };
    }, [filteredSales, filteredPurchases, filteredExpenses]);
    
    const accountsReceivable = useMemo(() => {
        return contacts
            .filter(c => c.role === 'Customer')
            .map(c => {
                const balance = sales
                    .filter(s => s.customerId === c.id)
                    .reduce((sum, s) => sum + s.balance, 0);
                return { ...c, balance };
            })
            .filter(c => c.balance > 0)
            .sort((a,b) => b.balance - a.balance);
    }, [contacts, sales]);
    
    const salesByCustomer = useMemo(() => {
        if (!selectedCustomerId) return [];
        return filteredSales.filter(s => s.customerId === selectedCustomerId);
    }, [filteredSales, selectedCustomerId]);
    
    const stockAgingData = useMemo(() => {
        const lastActivityMap = new Map<number, string>();

        [...sales, ...purchases].forEach(transaction => {
            const date = transaction.date;
            transaction.items.forEach(item => {
                const existingDate = lastActivityMap.get(item.productId);
                if (!existingDate || date > existingDate) {
                    lastActivityMap.set(item.productId, date);
                }
            });
        });

        const detailedAging = products.map(product => {
            const lastActivityDate = lastActivityMap.get(product.id);
            const today = new Date();
            const daysSinceActivity = lastActivityDate 
                ? Math.floor((today.getTime() - new Date(lastActivityDate).getTime()) / (1000 * 3600 * 24))
                : Infinity;
            
            const totalStock = product.stock;

            let bracket = '90+ days';
            if (daysSinceActivity <= 30) bracket = '0-30 days';
            else if (daysSinceActivity <= 60) bracket = '31-60 days';
            else if (daysSinceActivity <= 90) bracket = '61-90 days';
            
            return {
                ...product,
                value: totalStock * product.price,
                lastActivity: lastActivityDate || 'N/A',
                ageBracket: totalStock > 0 ? bracket : 'N/A',
            };
        });

        const summary = detailedAging.reduce((acc, product) => {
            if (product.stock > 0) {
                 if (!acc[product.ageBracket]) {
                    acc[product.ageBracket] = { quantity: 0, value: 0 };
                }
                acc[product.ageBracket].quantity += product.stock;
                acc[product.ageBracket].value += product.value;
            }
            return acc;
        }, {} as Record<string, { quantity: number; value: number }>);
        
        const summaryArray = ['0-30 days', '31-60 days', '61-90 days', '90+ days'].map(bracket => ({
            bracket,
            ...summary[bracket] || { quantity: 0, value: 0 },
        }));

        return { detailed: detailedAging.filter(p=>p.stock > 0), summary: summaryArray };
    }, [products, sales, purchases]);
    
    const salesByMonthData = useMemo(() => {
        const monthlySales = filteredSales.reduce((acc, sale) => {
            const month = sale.date.substring(0, 7); // YYYY-MM
            acc[month] = (acc[month] || 0) + sale.totalAmount;
            return acc;
        }, {} as Record<string, number>);

        return Object.entries(monthlySales)
            .map(([month, totalSales]) => ({
                month: new Date(month + '-02').toLocaleString('default', { month: 'short', year: 'numeric' }),
                totalSales
            }))
            .sort((a,b) => new Date(a.month).getTime() - new Date(b.month).getTime());
    }, [filteredSales]);

    const topSellingProductsData = useMemo(() => {
        const productQuantities = filteredSales
            .flatMap(sale => sale.items)
            .reduce((acc, item) => {
                acc[item.productId] = (acc[item.productId] || 0) + item.quantity;
                return acc;
            }, {} as Record<number, number>);

        return Object.entries(productQuantities)
            .sort(([, qtyA], [, qtyB]) => qtyB - qtyA)
            .slice(0, 5)
            .map(([productId, quantity]) => ({
                name: products.find(p => p.id === Number(productId))?.name || 'Unknown Product',
                quantity,
            }));
    }, [filteredSales, products]);


    const handleExport = (report: 'salesByCustomer' | 'stockAging' | 'cashFlow' | 'salesByMonth' | 'topSellingProducts', format: 'csv' | 'pdf') => {
        const filename = `${report}-report-${startDate}-to-${endDate}`;
        
        if (report === 'salesByCustomer') {
            if (!selectedCustomerId) return;
            const customer = customers.find(c => c.id === selectedCustomerId);
            if (!customer) return;
            
            const title = `Sales for ${customer.name} (${startDate} to ${endDate})`;
            if (format === 'csv') {
                const headers = ['Invoice ID', 'Date', 'Total Amount', 'Status'];
                const data = salesByCustomer.map(s => [s.id, s.date, s.totalAmount.toFixed(2), s.status]);
                downloadAsCsv(filename, headers, data);
            } else {
                 const headers = [ { header: 'Invoice ID', dataKey: 'id' }, { header: 'Date', dataKey: 'date' }, { header: 'Total Amount', dataKey: 'totalAmount' }, { header: 'Status', dataKey: 'status' } ];
                const data = salesByCustomer.map(s => ({...s, totalAmount: formatCurrency(s.totalAmount)}));
                downloadAsPdf(filename, title, headers, data);
            }
        } else if (report === 'stockAging') {
            const title = 'Stock Aging Report';
            if (format === 'csv') {
                 const headers = ['SKU', 'Product Name', 'Stock', 'Value', 'Last Activity', 'Age Bracket'];
                 const data = stockAgingData.detailed.map(p => [p.sku, p.name, p.stock, p.value.toFixed(2), p.lastActivity, p.ageBracket]);
                 downloadAsCsv('stock-aging-report', headers, data);
            } else {
                const headers = [
                    { header: 'SKU', dataKey: 'sku' }, { header: 'Product Name', dataKey: 'name' }, { header: 'Stock', dataKey: 'stock' },
                    { header: 'Value', dataKey: 'value' }, { header: 'Last Activity', dataKey: 'lastActivity' }, { header: 'Age Bracket', dataKey: 'ageBracket' }
                ];
                const data = stockAgingData.detailed.map(p => ({ ...p, value: formatCurrency(p.value)}));
                downloadAsPdf('stock-aging-report', title, headers, data);
            }
        } else if (report === 'cashFlow') {
             const title = `Cash Flow Overview (${startDate} to ${endDate})`;
             if(format === 'csv') {
                const headers = ['Metric', 'Amount'];
                const data = [['Total Revenue', totalRevenue.toFixed(2)], ['Cost of Goods Sold', cogs.toFixed(2)], ['Net Flow', (totalRevenue - cogs).toFixed(2)]];
                downloadAsCsv(filename, headers, data);
             } else {
                const headers = [{ header: 'Metric', dataKey: 'metric' }, { header: 'Amount', dataKey: 'amount' }];
                const data = [
                    { metric: 'Total Revenue', amount: formatCurrency(totalRevenue)},
                    { metric: 'Cost of Goods Sold', amount: formatCurrency(cogs)},
                    { metric: 'Net Flow', amount: formatCurrency(totalRevenue - cogs)},
                ];
                downloadAsPdf(filename, title, headers, data);
             }
        } else if (report === 'salesByMonth') {
            const title = `Sales by Month (${startDate} to ${endDate})`;
            if (format === 'csv') {
                const headers = ['Month', 'Total Sales'];
                const data = salesByMonthData.map(item => [item.month, item.totalSales.toFixed(2)]);
                downloadAsCsv(filename, headers, data);
            } else {
                const headers = [{ header: 'Month', dataKey: 'month' }, { header: 'Total Sales', dataKey: 'totalSales' }];
                const data = salesByMonthData.map(item => ({ ...item, totalSales: formatCurrency(item.totalSales) }));
                downloadAsPdf(filename, title, headers, data);
            }
        } else if (report === 'topSellingProducts') {
            const title = `Top Selling Products (${startDate} to ${endDate})`;
            if (format === 'csv') {
                const headers = ['Product Name', 'Quantity Sold'];
                const data = topSellingProductsData.map(item => [item.name, item.quantity]);
                downloadAsCsv(filename, headers, data);
            } else {
                const headers = [{ header: 'Product Name', dataKey: 'name' }, { header: 'Quantity Sold', dataKey: 'quantity' }];
                downloadAsPdf(filename, title, headers, topSellingProductsData);
            }
        }
    };


    const getStatusClass = (status: Sale['status']) => {
        if (status === 'Paid') return 'status-paid';
        if (status === 'Partially Paid') return 'status-partial';
        if (status === 'Unpaid') return 'status-unpaid';
        return '';
    };

    return (
        <>
            <div className="page-header">
                <h1 className="page-title">Reports Dashboard</h1>
            </div>
            <DateRangeFilter onDateChange={handleDateChange} />

            <div className="kpi-grid">
                <div className="kpi-card kpi-span-4">
                    <h4>Total Revenue</h4>
                    <p>{formatCurrency(totalRevenue)}</p>
                </div>
                 <div className="kpi-card kpi-span-4">
                    <h4>Cost of Goods Sold</h4>
                    <p>{formatCurrency(cogs)}</p>
                </div>
                 <div className="kpi-card kpi-span-4">
                    <h4>Total Expenses</h4>
                    <p>{formatCurrency(totalExpenses)}</p>
                </div>
                 <div className={`kpi-card kpi-span-4 ${netProfit >= 0 ? 'positive' : 'negative'}`}>
                    <h4>Net Profit</h4>
                    <p>{formatCurrency(netProfit)}</p>
                </div>
            </div>

            <div className="reports-dashboard-grid">
                 <div className="card report-widget widget-md-6 widget-lg-6">
                    <div className="report-widget-header">
                        <h3>Sales by Month</h3>
                        <div className="button-group">
                            <button className="button-secondary" onClick={() => handleExport('salesByMonth', 'csv')} disabled={salesByMonthData.length === 0}>
                                <span className="material-symbols-outlined">description</span>
                            </button>
                            <button className="button-secondary" onClick={() => handleExport('salesByMonth', 'pdf')} disabled={salesByMonthData.length === 0}>
                                <span className="material-symbols-outlined">picture_as_pdf</span>
                            </button>
                        </div>
                    </div>
                    <div className="report-widget-content">
                        <SalesByMonthChart data={salesByMonthData} />
                    </div>
                </div>
                 <div className="card report-widget widget-md-6 widget-lg-6">
                    <div className="report-widget-header">
                        <h3>Top Selling Products</h3>
                        <div className="button-group">
                            <button className="button-secondary" onClick={() => handleExport('topSellingProducts', 'csv')} disabled={topSellingProductsData.length === 0}>
                                <span className="material-symbols-outlined">description</span>
                            </button>
                            <button className="button-secondary" onClick={() => handleExport('topSellingProducts', 'pdf')} disabled={topSellingProductsData.length === 0}>
                                <span className="material-symbols-outlined">picture_as_pdf</span>
                            </button>
                        </div>
                    </div>
                    <div className="report-widget-content">
                        <TopProductsChart data={topSellingProductsData} />
                    </div>
                </div>
                <div className="card report-widget widget-md-12 widget-lg-7">
                    <div className="report-widget-header">
                         <h3>Sales by Customer</h3>
                         <div className="report-widget-controls">
                            <select value={selectedCustomerId} onChange={e => setSelectedCustomerId(Number(e.target.value))}>
                                <option value="">Select a customer</option>
                                {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                            </select>
                            <div className="button-group">
                                <button className="button-secondary" onClick={() => handleExport('salesByCustomer', 'csv')} disabled={!selectedCustomerId}>
                                    <span className="material-symbols-outlined">description</span>
                                </button>
                                <button className="button-secondary" onClick={() => handleExport('salesByCustomer', 'pdf')} disabled={!selectedCustomerId}>
                                    <span className="material-symbols-outlined">picture_as_pdf</span>
                                </button>
                            </div>
                        </div>
                    </div>
                    <div className="report-widget-content">
                        {selectedCustomerId ? (
                             <table className="report-table">
                                <thead>
                                    <tr>
                                        <th>Invoice ID</th>
                                        <th>Date</th>
                                        <th className="text-right">Total Amount</th>
                                        <th>Status</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    {salesByCustomer.length > 0 ? salesByCustomer.map(sale => (
                                        <tr key={sale.id}>
                                            <td>#{sale.id}</td>
                                            <td>{sale.date}</td>
                                            <td className="text-right">{formatCurrency(sale.totalAmount)}</td>
                                            <td><span className={`status-badge ${getStatusClass(sale.status)}`}>{sale.status}</span></td>
                                        </tr>
                                    )) : (
                                        <tr><td colSpan={4} className="no-data-message">No sales for this customer in the selected period.</td></tr>
                                    )}
                                </tbody>
                            </table>
                        ) : (
                            <p className="no-data-message">Select a customer to view their sales report.</p>
                        )}
                    </div>
                </div>
                <div className="card report-widget widget-md-6 widget-lg-5">
                    <div className="report-widget-header">
                        <h3>Accounts Receivable</h3>
                    </div>
                    <div className="report-widget-content">
                        <table className="report-table">
                            <thead><tr><th>Customer</th><th className="text-right">Balance</th></tr></thead>
                            <tbody>
                                {accountsReceivable.length > 0 ? accountsReceivable.map(c => (
                                    <tr key={c.id}>
                                        <td>{c.name}</td>
                                        <td className="text-right">{formatCurrency(c.balance)}</td>
                                    </tr>
                                )) : (
                                    <tr><td colSpan={2} className="no-data-message">No outstanding balances.</td></tr>
                                )}
                            </tbody>
                        </table>
                    </div>
                </div>
                <div className="card report-widget widget-md-6 widget-lg-7">
                    <div className="report-widget-header">
                        <h3>Stock Aging</h3>
                         <div className="button-group">
                            <button className="button-secondary" onClick={() => handleExport('stockAging', 'csv')}>
                                <span className="material-symbols-outlined">description</span>
                            </button>
                            <button className="button-secondary" onClick={() => handleExport('stockAging', 'pdf')}>
                                <span className="material-symbols-outlined">picture_as_pdf</span>
                            </button>
                        </div>
                    </div>
                    <div className="report-widget-content">
                        <table className="report-table">
                            <thead><tr><th>Age Bracket</th><th className="text-right">Quantity</th><th className="text-right">Value</th></tr></thead>
                            <tbody>
                                {stockAgingData.summary.map(item => (
                                    <tr key={item.bracket}>
                                        <td>{item.bracket}</td>
                                        <td className="text-right">{item.quantity.toLocaleString()}</td>
                                        <td className="text-right">{formatCurrency(item.value)}</td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </div>
                 <div className="card report-widget widget-md-12 widget-lg-5">
                    <div className="report-widget-header">
                        <h3>Sales vs. Purchases</h3>
                        <div className="button-group">
                            <button className="button-secondary" onClick={() => handleExport('cashFlow', 'csv')}>
                                <span className="material-symbols-outlined">description</span>
                            </button>
                            <button className="button-secondary" onClick={() => handleExport('cashFlow', 'pdf')}>
                                <span className="material-symbols-outlined">picture_as_pdf</span>
                            </button>
                        </div>
                    </div>
                    <div className="report-widget-content cash-flow-content">
                       <div className="cash-flow-item">
                           <span>Total Revenue</span>
                           <strong className="positive">{formatCurrency(totalRevenue)}</strong>
                       </div>
                       <div className="cash-flow-item">
                           <span>Cost of Goods Sold</span>
                           <strong className="negative">{formatCurrency(cogs)}</strong>
                       </div>
                       <div className="cash-flow-item total">
                           <span>Net Flow</span>
                           <strong className={totalRevenue - cogs >= 0 ? 'positive' : 'negative'}>{formatCurrency(totalRevenue - cogs)}</strong>
                       </div>
                    </div>
                </div>
            </div>
        </>
    );
};


// --- LAYOUT COMPONENTS ---
const Sidebar: React.FC<{
  currentPage: Page;
  setCurrentPage: (page: Page) => void;
  collapsed: boolean;
  currentUser: User | null;
}> = ({ currentPage, setCurrentPage, collapsed, currentUser }) => {
    const visibleNavItems = useMemo(() => {
        if (!currentUser) return [];
        return navItems.filter(item => permissions.canViewPage(currentUser.role, item.id));
    }, [currentUser]);

    return (
      <nav className={`sidebar ${collapsed ? 'collapsed' : ''}`}>
        <div className="sidebar-header">
          <span className="material-symbols-outlined logo-icon">store</span>
          <h1 className="logo-text">Zargoona</h1>
        </div>
        <ul className="nav-list">
          {visibleNavItems.map(item => (
            <li key={item.id} className="nav-item">
              <a
                href="#"
                className={currentPage === item.id ? 'active' : ''}
                onClick={(e) => { e.preventDefault(); setCurrentPage(item.id); }}
                aria-current={currentPage === item.id ? 'page' : undefined}
              >
                <span className="material-symbols-outlined icon">{item.icon}</span>
                <span className="text">{item.label}</span>
              </a>
            </li>
          ))}
        </ul>
      </nav>
    );
};

const Header: React.FC<{
  user: User | null;
  theme: Theme;
  toggleTheme: () => void;
  toggleSidebar: () => void;
  onProfileClick: () => void;
  onLogout: () => void;
}> = ({ user, theme, toggleTheme, toggleSidebar, onProfileClick, onLogout }) => {
    const [isDropdownOpen, setIsDropdownOpen] = useState(false);
    const dropdownRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
          if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
            setIsDropdownOpen(false);
          }
        };
        document.addEventListener("mousedown", handleClickOutside);
        return () => {
          document.removeEventListener("mousedown", handleClickOutside);
        };
    }, [dropdownRef]);

    return (
      <header className="header">
        <div className="header-left">
           <button className="icon-button" onClick={toggleSidebar} aria-label="Toggle sidebar">
            <span className="material-symbols-outlined">menu</span>
          </button>
        </div>
        <div className="header-right">
          <button className="icon-button" onClick={toggleTheme} aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} mode`}>
            <span className="material-symbols-outlined">{theme === 'light' ? 'dark_mode' : 'light_mode'}</span>
          </button>      
          <div className="profile-container" ref={dropdownRef}>
              <button className="profile-button" onClick={() => setIsDropdownOpen(p => !p)} aria-haspopup="true" aria-expanded={isDropdownOpen} aria-label="User profile and settings">
                <span>{user ? user.name : 'Loading...'}</span>
                <span className="material-symbols-outlined">account_circle</span>
              </button>
              {isDropdownOpen && (
                 <div className="profile-dropdown">
                    <button onClick={() => { onProfileClick(); setIsDropdownOpen(false); }}>
                        <span className="material-symbols-outlined">manage_accounts</span>
                        <span>My Profile</span>
                    </button>
                    <button onClick={onLogout}>
                        <span className="material-symbols-outlined">logout</span>
                        <span>Logout</span>
                    </button>
                </div>
              )}
          </div>
        </div>
      </header>
    );
};


// --- AUTHENTICATION COMPONENTS ---
const ForgotPasswordModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSuccess: (token: string) => void;
}> = ({ isOpen, onClose, onSuccess }) => {
    const [email, setEmail] = useState('');
    const [isSent, setIsSent] = useState(false);
    const [token, setToken] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState('');

    useEffect(() => {
        if(isOpen) {
            setEmail('');
            setIsSent(false);
            setToken('');
            setIsLoading(false);
            setError('');
        }
    }, [isOpen]);

    const handleSendLink = async () => {
        if (!email) {
            setError('Please enter your email address.');
            return;
        }
        setIsLoading(true);
        setError('');
        try {
            const response = await apiCall<{success: boolean, token: string}>('password.php', 'POST', { action: 'forgot', email });
            setToken(response.token);
            setIsSent(true);
        } catch (err) {
            setError((err as Error).message);
        } finally {
            setIsLoading(false);
        }
    };
    
    const handleProceed = () => {
        onSuccess(token);
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Forgot Password"
            size="sm"
        >
            {!isSent ? (
                <>
                    <p>Enter your email address and we'll send you a link to reset your password.</p>
                    <div className="form-group">
                        <label htmlFor="forgot-email">Email Address</label>
                        <input type="email" id="forgot-email" value={email} onChange={e => setEmail(e.target.value)} />
                    </div>
                    {error && <p className="error-message">{error}</p>}
                    <div className="modal-footer">
                        <button className="button-secondary" onClick={onClose} disabled={isLoading}>Cancel</button>
                        <button className="button" onClick={handleSendLink} disabled={isLoading}>
                            {isLoading ? 'Sending...' : 'Send Reset Link'}
                        </button>
                    </div>
                </>
            ) : (
                <>
                    <p>For demonstration, your password reset token is below. In a real app, a link would be sent to your email.</p>
                    <div className="token-display">{token}</div>
                    <p>Click "Proceed" to continue to the password reset screen.</p>
                    <div className="modal-footer">
                        <button className="button" onClick={handleProceed}>Proceed to Reset</button>
                    </div>
                </>
            )}
        </Modal>
    );
};

const ResetPasswordModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onSuccess: () => void;
    token: string;
}> = ({ isOpen, onClose, onSuccess, token }) => {
    const [newPassword, setNewPassword] = useState('');
    const [confirmPassword, setConfirmPassword] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState('');

    useEffect(() => {
        if(isOpen) {
            setNewPassword('');
            setConfirmPassword('');
            setIsLoading(false);
            setError('');
        }
    }, [isOpen]);
    
    const handleResetPassword = async () => {
        if (newPassword !== confirmPassword) {
            setError("Passwords do not match.");
            return;
        }
        if (newPassword.length < 8) {
            setError("Password must be at least 8 characters long.");
            return;
        }

        setIsLoading(true);
        setError('');
        try {
            await apiCall('password.php', 'POST', { action: 'reset', token, newPassword });
            onSuccess();
        } catch (err) {
            setError((err as Error).message);
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <Modal
            isOpen={isOpen}
            onClose={onClose}
            title="Reset Your Password"
            size="sm"
             footer={<>
                <button className="button-secondary" onClick={onClose} disabled={isLoading}>Cancel</button>
                <button className="button" onClick={handleResetPassword} disabled={isLoading}>
                    {isLoading ? 'Resetting...' : 'Reset Password'}
                </button>
            </>}
        >
            <div className="form-group">
                <label htmlFor="new-password-reset">New Password</label>
                <input type="password" id="new-password-reset" value={newPassword} onChange={e => setNewPassword(e.target.value)} />
            </div>
            <div className="form-group">
                <label htmlFor="confirm-password-reset">Confirm New Password</label>
                <input type="password" id="confirm-password-reset" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} />
            </div>
             {error && <p className="error-message">{error}</p>}
        </Modal>
    );
};

const LoginPage: React.FC<{ onLogin: (user: User) => void }> = ({ onLogin }) => {
    const [email, setEmail] = useState('admin@zargoona.com');
    const [password, setPassword] = useState('password123');
    const [error, setError] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [isForgotModalOpen, setIsForgotModalOpen] = useState(false);
    const [isResetModalOpen, setIsResetModalOpen] = useState(false);
    const [resetToken, setResetToken] = useState('');
    const [resetSuccessMessage, setResetSuccessMessage] = useState('');

    const handleLogin = async (e: React.FormEvent) => {
        e.preventDefault();
        setIsLoading(true);
        setError('');
        try {
            const user = await apiCall<User>('login.php', 'POST', { email, password });
            onLogin(user);
        } catch (err) {
            setError((err as Error).message);
            setIsLoading(false);
        }
    };
    
    const handleForgotSuccess = (token: string) => {
        setResetToken(token);
        setIsForgotModalOpen(false);
        setIsResetModalOpen(true);
    };

    const handleResetSuccess = () => {
        setIsResetModalOpen(false);
        setResetSuccessMessage('Password has been successfully reset. Please log in.');
        // Clear message after a few seconds
        setTimeout(() => setResetSuccessMessage(''), 5000);
    };

    return (
        <div className="login-container">
            <div className="login-box">
                <div className="login-header">
                    <span className="material-symbols-outlined logo-icon">store</span>
                    <h1>Zargoona</h1>
                    <p>Wholesale Management System</p>
                </div>
                {resetSuccessMessage && <div className="success-message">{resetSuccessMessage}</div>}
                <form onSubmit={handleLogin} className="login-form">
                    <div className="form-group">
                        <label htmlFor="email">Email Address</label>
                        <input type="email" id="email" value={email} onChange={e => setEmail(e.target.value)} required />
                    </div>
                    <div className="form-group">
                        <label htmlFor="password">Password</label>
                        <input type="password" id="password" value={password} onChange={e => setPassword(e.target.value)} required />
                    </div>
                    {error && <p className="error-message">{error}</p>}
                    <div className="login-actions">
                         <a href="#" className="forgot-password-link" onClick={(e) => { e.preventDefault(); setIsForgotModalOpen(true); }}>Forgot Password?</a>
                        <button type="submit" className="button login-button" disabled={isLoading}>
                            {isLoading ? 'Logging in...' : 'Login'}
                        </button>
                    </div>
                </form>
            </div>
             <ForgotPasswordModal
                isOpen={isForgotModalOpen}
                onClose={() => setIsForgotModalOpen(false)}
                onSuccess={handleForgotSuccess}
            />
            <ResetPasswordModal
                isOpen={isResetModalOpen}
                onClose={() => setIsResetModalOpen(false)}
                onSuccess={handleResetSuccess}
                token={resetToken}
            />
        </div>
    );
};


// --- MAIN APP COMPONENT ---
const getInitialTheme = (): Theme => {
    try {
        const savedTheme = localStorage.getItem('zargoonaTheme');
        if (savedTheme === 'dark' || savedTheme === 'light') {
            return savedTheme;
        }
    } catch (error) {
        console.error("Could not access localStorage to get theme.", error);
    }
    return 'light';
};

const App: React.FC = () => {
  const [theme, setTheme] = useState<Theme>(getInitialTheme);
  const [currentPage, setCurrentPage] = useState<Page>('dashboard');
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);

  // App State from server
  const [products, setProducts] = useState<Product[]>([]);
  const [sales, setSales] = useState<Sale[]>([]);
  const [contacts, setContacts] = useState<Contact[]>([]);
  const [purchases, setPurchases] = useState<Purchase[]>([]);
  const [orders, setOrders] = useState<Order[]>([]);
  const [returns, setReturns] = useState<Return[]>([]);
  const [damages, setDamages] = useState<Damage[]>([]);
  const [auditLog, setAuditLog] = useState<AuditLogEntry[]>([]);
  const [expenseCategories, setExpenseCategories] = useState<ExpenseCategory[]>([]);
  const [expenses, setExpenses] = useState<Expense[]>([]);
  const [payments, setPayments] = useState<Payment[]>([]);
  const [users, setUsers] = useState<User[]>([]);
  const [currentUser, setCurrentUser] = useState<User | null>(null);
  
  const [isProfileModalOpen, setIsProfileModalOpen] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Fetch all initial data from the backend
  useEffect(() => {
    // This effect should only run once after a user is logged in.
    // The login flow will set the currentUser, then we can fetch data.
    if (currentUser) {
        const fetchInitialData = async () => {
            setIsLoading(true); // Show loader while fetching data for the logged-in user
            try {
                const data = await apiCall<any>('data.php', 'GET');
                setProducts(data.products || []);
                setSales(data.sales || []);
                setContacts(data.contacts || []);
                setPurchases(data.purchases || []);
                setOrders(data.orders || []);
                setReturns(data.returns || []);
                setDamages(data.damages || []);
                setAuditLog(data.auditLog || []);
                setExpenseCategories(data.expenseCategories || []);
                setExpenses(data.expenses || []);
                setPayments(data.payments || []);
                setUsers(data.users || []);
            } catch (err) {
                console.error("Failed to fetch initial data", err);
                setError((err as Error).message);
            } finally {
                setIsLoading(false);
            }
        };
        fetchInitialData();
    } else {
        // If there's no user, we are on the login page, so we are not "loading" data.
        setIsLoading(false);
    }
  }, [currentUser]);
  
  const handleUpdateCurrentUser = (updatedData: { name: string }) => {
      if (!currentUser) return;
      const updatedUser = { ...currentUser, ...updatedData };
      const newUsers = users.map(u => u.id === currentUser.id ? updatedUser : u);
      
      setUsers(newUsers);
      setCurrentUser(updatedUser);
      setIsProfileModalOpen(false);
  };
  
  const handleSetCurrentPage = (page: Page) => {
      if (!currentUser || !permissions.canViewPage(currentUser.role, page)) {
          console.warn(`Access denied for role ${currentUser?.role} to page ${page}.`);
          setCurrentPage('dashboard');
          return;
      }
      setCurrentPage(page);
  };
  
  const handleLogin = (user: User) => {
      setCurrentUser(user);
      // Reset to dashboard page on login
      setCurrentPage('dashboard');
  };
  
  const handleLogout = () => {
      setCurrentUser(null);
      // Clear all data on logout to ensure fresh data for the next user
      setProducts([]);
      setSales([]);
      setContacts([]);
      setPurchases([]);
      setOrders([]);
      setReturns([]);
      setDamages([]);
      setAuditLog([]);
      setExpenseCategories([]);
      setExpenses([]);
      setPayments([]);
      setUsers([]);
  };

  const renderPage = () => {
    if (!currentUser) return null;

    if (!permissions.canViewPage(currentUser.role, currentPage)) {
        return <DashboardPage />;
    }

    switch (currentPage) {
      case 'dashboard':
        return <DashboardPage />;
      case 'products':
        return <ProductsPage products={products} setProducts={setProducts} currentUser={currentUser} />;
      case 'sales':
        return <SalesPage sales={sales} setSales={setSales} products={products} setProducts={setProducts} contacts={contacts} />;
      case 'purchases':
        return <PurchasesPage purchases={purchases} setPurchases={setPurchases} products={products} setProducts={setProducts} contacts={contacts} />;
      case 'orders':
        return <OrdersPage orders={orders} setOrders={setOrders} setSales={setSales} products={products} setProducts={setProducts} contacts={contacts} />;
      case 'returns':
        return <ReturnsPage returns={returns} setReturns={setReturns} sales={sales} setSales={setSales} products={products} setProducts={setProducts} />;
      case 'damages':
        return <DamagesPage damages={damages} setDamages={setDamages} products={products} setProducts={setProducts} />;
      case 'payments':
        return <PaymentsPage payments={payments} setPayments={setPayments} sales={sales} setSales={setSales} purchases={purchases} setPurchases={setPurchases} />;
      case 'expenses':
        return <ExpensesPage expenses={expenses} setExpenses={setExpenses} categories={expenseCategories} setCategories={setExpenseCategories} />;
      case 'contacts':
        return <ContactsPage contacts={contacts} setContacts={setContacts} sales={sales} purchases={purchases} />;
      case 'reports':
         return <ReportsDashboardPage products={products} sales={sales} purchases={purchases} contacts={contacts} expenses={expenses} />;
      case 'users':
         return <UsersPage users={users} setUsers={setUsers} currentUser={currentUser} />;
      case 'audit':
         return <AuditTrailPage log={auditLog} />;
      default:
        return <DashboardPage />;
    }
  };

  const toggleTheme = () => {
    setTheme(current => {
      const newTheme = current === 'light' ? 'dark' : 'light';
      try {
        localStorage.setItem('zargoonaTheme', newTheme);
      } catch (error) {
        console.error("Failed to save theme to localStorage", error);
      }
      return newTheme;
    });
  };
  
  const toggleSidebar = useCallback(() => {
    setSidebarCollapsed(prev => !prev);
  }, []);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);
  
  useEffect(() => {
    const handleResize = () => {
      const mobile = window.innerWidth <= 768;
      setIsMobile(mobile);
      if (mobile) {
        setSidebarCollapsed(true);
      }
    };
    window.addEventListener('resize', handleResize);
    handleResize(); // initial check
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  if (isLoading && !currentUser) {
      return (
        <div className="full-page-loader">
            <div className="spinner"></div>
            <span>Loading Zargoona...</span>
        </div>
      );
  }

  if (error) {
    return (
        <div className="full-page-error">
            <span className="material-symbols-outlined error-icon">error</span>
            <h2>Connection Error</h2>
            <p>Could not connect to the Zargoona backend.</p>
            <pre><code>{error}</code></pre>
            <small>Please ensure your PHP backend server is running and the API files are in the correct location.</small>
        </div>
    );
  }

  if (!currentUser) {
      return <LoginPage onLogin={handleLogin} />;
  }
  
  return (
    <div className={`app-container ${sidebarCollapsed ? 'sidebar-collapsed' : ''}`}>
      <Sidebar currentPage={currentPage} setCurrentPage={handleSetCurrentPage} collapsed={sidebarCollapsed} currentUser={currentUser} />
      <div className="main-panel">
        <Header user={currentUser} theme={theme} toggleTheme={toggleTheme} toggleSidebar={toggleSidebar} onProfileClick={() => setIsProfileModalOpen(true)} onLogout={handleLogout} />
        <main className="main-content">
            {isLoading ? (
                <div className="full-page-loader">
                    <div className="spinner"></div>
                    <span>Loading data...</span>
                </div>
            ) : renderPage()}
        </main>
      </div>
      {currentUser && <ProfileModal isOpen={isProfileModalOpen} onClose={() => setIsProfileModalOpen(false)} user={currentUser} onSave={handleUpdateCurrentUser} />}
    </div>
  );
};

const container = document.getElementById('root');
if (container) {
  const root = createRoot(container);
  root.render(<App />);
}
