Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/portal/modules/membership/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/portal/modules/membership/upload.php

<?php
require_once '../../config/config.php';
require_once '../../classes/MembershipCard.php';
checkLogin();

$pageTitle = "Upload Members - " . APP_NAME;
$db = Database::getInstance()->getConnection();

$successMessage = '';
$errorMessage = '';
$uploadResults = [];

// Get user access parameters
$accessLevel = $_SESSION['access_level'] ?? 'assembly';
$areaId = $_SESSION['area_id'] ?? null;
$districtId = $_SESSION['district_id'] ?? null;
$assemblyId = $_SESSION['assembly_id'] ?? null;

if (!function_exists('generateMembershipId')) {
    function generateMembershipId() {
        // Simple unique member ID: MEM + Year + random 6 digits
        return 'MEM' . date('Y') . str_pad(mt_rand(1, 999999), 6, '0', STR_PAD_LEFT);
    }
}

if (!function_exists('generateTrackingCode')) {
    function generateTrackingCode($type = 'member') {
        $prefix = $type === 'member' ? 'MEM' : 'USR';
        return $prefix . date('Y') . str_pad(mt_rand(1, 999999), 6, '0', STR_PAD_LEFT);
    }
}

if (!function_exists('generateBarcode')) {
    function generateBarcode($code) {
        $width = 200;
        $height = 50;
        $image = imagecreate($width, $height);
        $white = imagecolorallocate($image, 255, 255, 255);
        $black = imagecolorallocate($image, 0, 0, 0);
        imagefill($image, 0, 0, $white);
        $codeLength = strlen($code);
        $x = 10;
        for ($i = 0; $i < $codeLength; $i++) {
            $char = ord($code[$i]);
            $pattern = $char % 4;
            for ($j = 0; $j < 3; $j++) {
                $barWidth = ($pattern & (1 << $j)) ? 3 : 1;
                imagefilledrectangle($image, $x, 5, $x + $barWidth, 35, $black);
                $x += $barWidth + 1;
            }
        }
        imagestring($image, 2, 10, 37, substr($code, 0, 20), $black);
        ob_start();
        imagepng($image);
        $imageData = ob_get_contents();
        ob_end_clean();
        imagedestroy($image);
        return "data:image/png;base64," . base64_encode($imageData);
    }
}

if (!function_exists('generateQRCode')) {
    function generateQRCode($code) {
        $size = 100;
        $image = imagecreate($size, $size);
        $white = imagecolorallocate($image, 255, 255, 255);
        $black = imagecolorallocate($image, 0, 0, 0);
        imagefill($image, 0, 0, $white);
        $codeHash = md5($code);
        $blockSize = 5;
        imagefilledrectangle($image, 5, 5, 30, 30, $black);
        imagefilledrectangle($image, 70, 5, 95, 30, $black);
        imagefilledrectangle($image, 5, 70, 30, 95, $black);
        imagefilledrectangle($image, 10, 10, 25, 25, $white);
        imagefilledrectangle($image, 75, 10, 90, 25, $white);
        imagefilledrectangle($image, 10, 75, 25, 90, $white);
        imagefilledrectangle($image, 15, 15, 20, 20, $black);
        imagefilledrectangle($image, 80, 15, 85, 20, $black);
        imagefilledrectangle($image, 15, 80, 20, 85, $black);
        for ($i = 0; $i < 32; $i++) {
            $hexChar = hexdec($codeHash[$i]);
            for ($bit = 0; $bit < 4; $bit++) {
                if ($hexChar & (1 << $bit)) {
                    $x = 35 + (($i * 2 + $bit) % 6) * $blockSize;
                    $y = 35 + floor(($i * 2 + $bit) / 6) * $blockSize;
                    if ($x < 95 && $y < 95) {
                        imagefilledrectangle($image, $x, $y, $x + $blockSize - 1, $y + $blockSize - 1, $black);
                    }
                }
            }
        }
        ob_start();
        imagepng($image);
        $imageData = ob_get_contents();
        ob_end_clean();
        imagedestroy($image);
        return "data:image/png;base64," . base64_encode($imageData);
    }
}

if (!function_exists('createMemberUserCode')) {
    function createMemberUserCode(PDO $db, $memberId, $createdBy) {
        try {
            // Ensure we have a valid numeric member ID
            $memberId = (int)$memberId;
            if ($memberId <= 0) {
                return;
            }

            // If a code already exists for this member, do not create another
            $existingStmt = $db->prepare("SELECT id FROM memberuser_codes WHERE member_id = :member_id LIMIT 1");
            $existingStmt->execute(['member_id' => $memberId]);
            if ($existingStmt->fetch()) {
                return;
            }

            // Generate unique tracking code
            do {
                $trackingCode = generateTrackingCode('member');
                $checkStmt = $db->prepare("SELECT id FROM memberuser_codes WHERE tracking_code = :code");
                $checkStmt->execute(['code' => $trackingCode]);
            } while ($checkStmt->fetch());

            $code = 'MC' . date('Ymd') . str_pad($memberId, 4, '0', STR_PAD_LEFT) . mt_rand(100, 999);
            $barcode = generateBarcode($trackingCode);
            $qrcode = generateQRCode($trackingCode);

            // Get default Attendance event if available
            $eventStmt = $db->prepare("SELECT id FROM events WHERE name = 'Attendance' AND is_active = 1 LIMIT 1");
            $eventStmt->execute();
            $defaultEvent = $eventStmt->fetch();
            $eventId = $defaultEvent ? $defaultEvent['id'] : null;

            // Insert member tracking code
            $codeStmt = $db->prepare("
                INSERT INTO memberuser_codes (
                    code, description, member_id, event_id, code_type, tracking_code,
                    barcode, qrcode, created_by, is_active
                ) VALUES (
                    :code, :description, :member_id, :event_id, 'member', :tracking_code,
                    :barcode, :qrcode, :created_by, 1
                )
            ");
            $codeStmt->execute([
                'code' => $code,
                'description' => 'Auto-generated member tracking code',
                'member_id' => $memberId,
                'event_id' => $eventId,
                'tracking_code' => $trackingCode,
                'barcode' => $barcode,
                'qrcode' => $qrcode,
                'created_by' => $createdBy
            ]);
        } catch (Exception $e) {
            // Do not break the upload if code generation fails
        }
    }
}

// Handle Reference IDs PDF export
if (isset($_GET['action']) && $_GET['action'] == 'export_reference_ids') {
    require_once '../../vendor/autoload.php';
    
    // Get all areas, districts, assemblies
    $areasStmt = $db->query("SELECT id, area_name, area_code FROM areas WHERE is_active = 1 ORDER BY area_name");
    $allAreas = $areasStmt->fetchAll(PDO::FETCH_ASSOC);
    
    $districtsStmt = $db->query("SELECT d.id, d.district_name, d.district_code, a.area_name FROM districts d JOIN areas a ON d.area_id = a.id ORDER BY a.area_name, d.district_name");
    $allDistricts = $districtsStmt->fetchAll(PDO::FETCH_ASSOC);
    
    $assembliesStmt = $db->query("SELECT asm.id, asm.assembly_name, asm.assembly_code, d.district_name, a.area_name FROM assemblies asm JOIN districts d ON asm.district_id = d.id JOIN areas a ON asm.area_id = a.id ORDER BY a.area_name, d.district_name, asm.assembly_name");
    $allAssemblies = $assembliesStmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Create PDF
    $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor(APP_NAME);
    $pdf->SetTitle('Location Reference IDs');
    $pdf->SetSubject('Complete list of Area, District, and Assembly IDs');
    
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);
    $pdf->SetMargins(15, 15, 15);
    $pdf->SetAutoPageBreak(TRUE, 15);
    $pdf->AddPage();
    
    // Title
    $pdf->SetFont('helvetica', 'B', 16);
    $pdf->Cell(0, 10, APP_NAME, 0, 1, 'C');
    $pdf->SetFont('helvetica', 'B', 14);
    $pdf->Cell(0, 10, 'Location Reference IDs', 0, 1, 'C');
    $pdf->SetFont('helvetica', '', 10);
    $pdf->Cell(0, 5, 'For Member Upload - Generated: ' . date('F d, Y - h:i A'), 0, 1, 'C');
    $pdf->Ln(5);
    
    // Areas Section
    $pdf->SetFont('helvetica', 'B', 12);
    $pdf->SetFillColor(30, 64, 175);
    $pdf->SetTextColor(255, 255, 255);
    $pdf->Cell(0, 8, 'AREAS (' . count($allAreas) . ')', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', 'B', 9);
    $pdf->SetFillColor(220, 220, 220);
    $pdf->SetTextColor(0, 0, 0);
    $pdf->Cell(20, 6, 'ID', 1, 0, 'C', true);
    $pdf->Cell(35, 6, 'Area Code', 1, 0, 'C', true);
    $pdf->Cell(125, 6, 'Area Name', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', '', 8);
    foreach ($allAreas as $area) {
        $pdf->Cell(20, 5, $area['id'], 1, 0, 'C');
        $pdf->Cell(35, 5, $area['area_code'] ?? '-', 1, 0, 'C');
        $pdf->Cell(125, 5, substr($area['area_name'], 0, 60), 1, 1, 'L');
    }
    
    $pdf->Ln(5);
    
    // Districts Section
    $pdf->SetFont('helvetica', 'B', 12);
    $pdf->SetFillColor(247, 147, 22);
    $pdf->SetTextColor(255, 255, 255);
    $pdf->Cell(0, 8, 'DISTRICTS (' . count($allDistricts) . ')', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', 'B', 9);
    $pdf->SetFillColor(220, 220, 220);
    $pdf->SetTextColor(0, 0, 0);
    $pdf->Cell(20, 6, 'ID', 1, 0, 'C', true);
    $pdf->Cell(35, 6, 'District Code', 1, 0, 'C', true);
    $pdf->Cell(65, 6, 'District Name', 1, 0, 'L', true);
    $pdf->Cell(60, 6, 'Area', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', '', 8);
    foreach ($allDistricts as $district) {
        $pdf->Cell(20, 5, $district['id'], 1, 0, 'C');
        $pdf->Cell(35, 5, $district['district_code'] ?? '-', 1, 0, 'C');
        $pdf->Cell(65, 5, substr($district['district_name'], 0, 35), 1, 0, 'L');
        $pdf->Cell(60, 5, substr($district['area_name'], 0, 30), 1, 1, 'L');
    }
    
    $pdf->Ln(5);
    
    // Assemblies Section
    $pdf->SetFont('helvetica', 'B', 12);
    $pdf->SetFillColor(147, 51, 234);
    $pdf->SetTextColor(255, 255, 255);
    $pdf->Cell(0, 8, 'ASSEMBLIES (' . count($allAssemblies) . ')', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', 'B', 9);
    $pdf->SetFillColor(220, 220, 220);
    $pdf->SetTextColor(0, 0, 0);
    $pdf->Cell(20, 6, 'ID', 1, 0, 'C', true);
    $pdf->Cell(35, 6, 'Assembly Code', 1, 0, 'C', true);
    $pdf->Cell(60, 6, 'Assembly Name', 1, 0, 'L', true);
    $pdf->Cell(40, 6, 'District', 1, 0, 'L', true);
    $pdf->Cell(25, 6, 'Area', 1, 1, 'L', true);
    
    $pdf->SetFont('helvetica', '', 7);
    foreach ($allAssemblies as $assembly) {
        $pdf->Cell(20, 5, $assembly['id'], 1, 0, 'C');
        $pdf->Cell(35, 5, $assembly['assembly_code'] ?? '-', 1, 0, 'C');
        $pdf->Cell(60, 5, substr($assembly['assembly_name'], 0, 35), 1, 0, 'L');
        $pdf->Cell(40, 5, substr($assembly['district_name'], 0, 22), 1, 0, 'L');
        $pdf->Cell(25, 5, substr($assembly['area_name'], 0, 15), 1, 1, 'L');
    }
    
    $filename = 'reference_ids_' . date('Ymd_His') . '.pdf';
    $pdf->Output($filename, 'D');
    exit;
}

// Handle PDF export
if (isset($_GET['action']) && $_GET['action'] == 'export_pdf' && isset($_SESSION['upload_results'])) {
    require_once '../../vendor/autoload.php';
    
    $uploadResults = $_SESSION['upload_results'];
    $uploadDate = $_SESSION['upload_date'] ?? date('Y-m-d H:i:s');
    
    // Create new PDF document
    $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    
    // Set document information
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor(APP_NAME);
    $pdf->SetTitle('Member Upload Results');
    $pdf->SetSubject('Member Upload Results with Credentials');
    
    // Remove default header/footer
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);
    
    // Set margins
    $pdf->SetMargins(15, 15, 15);
    $pdf->SetAutoPageBreak(TRUE, 15);
    
    // Add a page
    $pdf->AddPage();
    
    // Set font
    $pdf->SetFont('helvetica', 'B', 16);
    
    // Title
    $pdf->Cell(0, 10, APP_NAME, 0, 1, 'C');
    $pdf->SetFont('helvetica', 'B', 14);
    $pdf->Cell(0, 10, 'Member Upload Results', 0, 1, 'C');
    $pdf->SetFont('helvetica', '', 10);
    $pdf->Cell(0, 5, 'Upload Date: ' . date('F d, Y - h:i A', strtotime($uploadDate)), 0, 1, 'C');
    $pdf->Ln(5);
    
    // Summary
    $successCount = count(array_filter($uploadResults, fn($r) => $r['status'] == 'success'));
    $warningCount = count(array_filter($uploadResults, fn($r) => $r['status'] == 'warning'));
    $errorCount = count(array_filter($uploadResults, fn($r) => $r['status'] == 'error'));
    
    $pdf->SetFont('helvetica', 'B', 11);
    $pdf->Cell(0, 7, 'Summary:', 0, 1);
    $pdf->SetFont('helvetica', '', 10);
    $pdf->Cell(0, 5, 'Total Records: ' . count($uploadResults), 0, 1);
    $pdf->SetTextColor(0, 128, 0);
    $pdf->Cell(0, 5, 'Successful: ' . $successCount, 0, 1);
    $pdf->SetTextColor(255, 140, 0);
    $pdf->Cell(0, 5, 'Warnings: ' . $warningCount, 0, 1);
    $pdf->SetTextColor(255, 0, 0);
    $pdf->Cell(0, 5, 'Errors: ' . $errorCount, 0, 1);
    $pdf->SetTextColor(0, 0, 0);
    $pdf->Ln(5);
    
    // Table header
    $pdf->SetFont('helvetica', 'B', 9);
    $pdf->SetFillColor(30, 64, 175); // Blue color
    $pdf->SetTextColor(255, 255, 255);
    
    $pdf->Cell(15, 7, 'Row', 1, 0, 'C', true);
    $pdf->Cell(40, 7, 'Member Name', 1, 0, 'C', true);
    $pdf->Cell(20, 7, 'Status', 1, 0, 'C', true);
    $pdf->Cell(30, 7, 'Card Number', 1, 0, 'C', true);
    $pdf->Cell(75, 7, 'Message/Credentials', 1, 1, 'C', true);
    
    // Table content
    $pdf->SetFont('helvetica', '', 8);
    $pdf->SetTextColor(0, 0, 0);
    
    foreach ($uploadResults as $result) {
        // Set fill color based on status
        if ($result['status'] == 'success') {
            $pdf->SetFillColor(240, 253, 244); // Light green
        } elseif ($result['status'] == 'warning') {
            $pdf->SetFillColor(254, 252, 232); // Light yellow
        } else {
            $pdf->SetFillColor(254, 242, 242); // Light red
        }
        
        $pdf->Cell(15, 6, $result['row'], 1, 0, 'C', true);
        $pdf->Cell(40, 6, substr($result['name'], 0, 25), 1, 0, 'L', true);
        $pdf->Cell(20, 6, ucfirst($result['status']), 1, 0, 'C', true);
        $pdf->Cell(30, 6, $result['card_number'] ?? '-', 1, 0, 'C', true);
        
        // Message might be long, use MultiCell equivalent
        $message = $result['message'] ?? '-';
        $pdf->Cell(75, 6, substr($message, 0, 50) . (strlen($message) > 50 ? '...' : ''), 1, 1, 'L', true);
    }
    
    // Output PDF
    $filename = 'member_upload_results_' . date('Ymd_His') . '.pdf';
    $pdf->Output($filename, 'D');
    exit;
}

// Handle template download
if (isset($_GET['action']) && in_array($_GET['action'], ['download_template', 'download_excel'])) {
    $isExcel = $_GET['action'] == 'download_excel';
    
    if ($isExcel) {
        // Excel template
        require_once '../../vendor/autoload.php';
        
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        
        // Set headers with styling
        $headers = [
            'title', 'first_name', 'middle_name', 'last_name', 'gender', 'date_of_birth',
            'place_of_birth', 'phone', 'email', 'member_type', 'marital_status',
            'address_line1', 'gps_address', 'street_name', 'city', 'hometown',
            'area_id', 'district_id', 'assembly_id', 'family_id',
            'water_baptism', 'date_of_baptism', 'place_of_baptism', 'officiating_minister_baptism',
            'officiating_ministers_district', 'holyghost_baptism', 'date_of_holyspirit_baptism',
            'communicant', 'dedicated', 'dedication_date', 'name_of_officiating_minister',
            'church_where_dedication_done', 'date_of_conversion', 'date_of_joining',
            'occupation', 'level_of_education', 'parent_name', 'parent_relationship'
        ];
        
        // Write headers
        $col = 'A';
        foreach ($headers as $header) {
            $sheet->setCellValue($col . '1', $header);
            $sheet->getStyle($col . '1')->getFont()->setBold(true);
            $sheet->getStyle($col . '1')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('1E40AF');
            $sheet->getStyle($col . '1')->getFont()->getColor()->setRGB('FFFFFF');
            $col++;
        }
        
        // Add sample row
        $sampleRow = [
            'Mr', 'John', 'Paul', 'Doe', 'Male', '1990-01-15',
            'Accra', '0244123456', 'john.doe@email.com', 'Full Member', 'Single',
            'P.O. Box 123', 'GA-123-4567', 'Main Street', 'Accra', 'Cape Coast',
            '1', '1', '1', '',
            '1', '2020-01-15', 'Church Name', 'Minister Name',
            'District', '1', '2020-02-15',
            '1', '1', '2019-12-25', 'Minister Name',
            'Church Name', '2019-01-01', '2019-06-15',
            'Teacher', 'Tertiary', 'Parent Name', 'Father'
        ];
        
        $col = 'A';
        foreach ($sampleRow as $value) {
            $sheet->setCellValue($col . '2', $value);
            $sheet->getStyle($col . '2')->getFont()->setItalic(true);
            $col++;
        }
        
        // Auto-size columns
        foreach (range('A', $col) as $columnID) {
            $sheet->getColumnDimension($columnID)->setAutoSize(true);
        }
        
        // Output Excel file
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="members_upload_template.xlsx"');
        header('Cache-Control: max-age=0');
        
        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
        exit;
    } else {
        // CSV template
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename=members_upload_template.csv');
        
        $output = fopen('php://output', 'w');
    
    // CSV Headers - matching members table structure
    $headers = [
        'title', 'first_name', 'middle_name', 'last_name', 'gender', 'date_of_birth',
        'place_of_birth', 'phone', 'email', 'member_type', 'marital_status',
        'address_line1', 'gps_address', 'street_name', 'city', 'hometown',
        'area_id', 'district_id', 'assembly_id', 'family_id',
        'water_baptism', 'date_of_baptism', 'place_of_baptism', 'officiating_minister_baptism',
        'officiating_ministers_district', 'holyghost_baptism', 'date_of_holyspirit_baptism',
        'communicant', 'dedicated', 'dedication_date', 'name_of_officiating_minister',
        'church_where_dedication_done', 'date_of_conversion', 'date_of_joining',
        'occupation', 'level_of_education', 'parent_name', 'parent_relationship'
    ];
    
    fputcsv($output, $headers);
    
    // Add sample row with instructions
    $sampleRow = [
        'Mr/Mrs/Miss/Dr/Rev/Pastor/Deacon/Deaconess/Elder/Evangelist/Prophet/Apostle',
        'John', 'Paul', 'Doe', 'Male/Female', '1990-01-15',
        'Accra', '0244123456', 'john.doe@email.com (leave empty to auto-generate)', 'Full Member/Associate Member/Youth/Children', 'Single/Married/Divorced/Widowed',
        'P.O. Box 123', 'GA-123-4567', 'Main Street', 'Accra', 'Cape Coast',
        '1 (Area ID)', '1 (District ID)', '1 (Assembly ID)', 'Optional',
        '1/0 (Yes/No)', '2020-01-15', 'Church Name', 'Minister Name',
        'District', '1/0', '2020-02-15',
        '1/0', '1/0', '2019-12-25', 'Minister Name',
        'Church Name', '2019-01-01', '2019-06-15',
        'Teacher', 'Tertiary', 'Parent Name', 'Father/Mother/Guardian'
    ];
    
        fputcsv($output, $sampleRow);
        
        fclose($output);
        exit;
    }
}

// Handle file upload
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['member_file'])) {
    try {
        $file = $_FILES['member_file'];
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            throw new Exception('File upload error');
        }
        
        $fileExt = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        
        if (!in_array($fileExt, ['csv', 'xlsx', 'xls'])) {
            throw new Exception('Please upload a CSV or Excel file');
        }
        
        // Process file based on type
        if ($fileExt == 'csv') {
            // Process CSV file
            $handle = fopen($file['tmp_name'], 'r');
            
            if ($handle === false) {
                throw new Exception('Could not open file');
            }
            
            // Get headers
            $headers = fgetcsv($handle);
            
            if ($headers === false) {
                throw new Exception('Could not read file headers');
            }
            
            $successCount = 0;
            $errorCount = 0;
            $row = 1;
            
            // Start transaction
            $db->beginTransaction();

            // Membership card ID generator for member IDs
            $memberIdCardGenerator = new MembershipCard();
            
            try {
                while (($data = fgetcsv($handle)) !== false) {
                    $row++;
                    
                    // Skip completely empty rows
                    $isEmptyRow = true;
                    foreach ($data as $value) {
                        if (trim((string)$value) !== '') {
                            $isEmptyRow = false;
                            break;
                        }
                    }
                    if ($isEmptyRow) {
                        continue;
                    }
                    
                    // Skip sample/template row based on title cell content
                    if (isset($data[0]) && stripos((string)$data[0], 'Mr/Mrs') !== false) {
                        continue;
                    }
                    
                    // Map CSV data to array
                    $memberData = array_combine($headers, $data);
                    
                    // Generate email if empty
                    if (empty($memberData['email']) || stripos($memberData['email'], 'leave empty') !== false) {
                        $firstName = strtolower(trim($memberData['first_name']));
                        $lastName = strtolower(trim($memberData['last_name']));
                        $memberData['email'] = $firstName . '.' . $lastName . '@church.auto';
                    }
                    
                    // Use provided area/district/assembly or user's access level.
                    // Be flexible with values like "1 (Area ID)" by extracting the numeric portion.
                    $memberAreaId = null;
                    if (!empty($memberData['area_id'])) {
                        if (is_numeric($memberData['area_id'])) {
                            $memberAreaId = (int)$memberData['area_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['area_id'], $m)) {
                            $memberAreaId = (int)$m[1];
                        }
                    } elseif (!empty($areaId)) {
                        $memberAreaId = $areaId;
                    }

                    $memberDistrictId = null;
                    if (!empty($memberData['district_id'])) {
                        if (is_numeric($memberData['district_id'])) {
                            $memberDistrictId = (int)$memberData['district_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['district_id'], $m)) {
                            $memberDistrictId = (int)$m[1];
                        }
                    } elseif (!empty($districtId)) {
                        $memberDistrictId = $districtId;
                    }

                    $memberAssemblyId = null;
                    if (!empty($memberData['assembly_id'])) {
                        if (is_numeric($memberData['assembly_id'])) {
                            $memberAssemblyId = (int)$memberData['assembly_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['assembly_id'], $m)) {
                            $memberAssemblyId = (int)$m[1];
                        }
                    } elseif (!empty($assemblyId)) {
                        $memberAssemblyId = $assemblyId;
                    }

                    if ($memberAreaId === null || $memberDistrictId === null || $memberAssemblyId === null) {
                        throw new Exception("Row {$row}: Missing or invalid Area/District/Assembly ID. Please provide numeric IDs in the file or set your default location.");
                    }
                    
                    // Generate unique membershipcard_id (member ID) for this member
                    do {
                        $membershipCardId = $memberIdCardGenerator->generateCardNumber();
                        $checkStmt = $db->prepare("SELECT id FROM members WHERE membershipcard_id = :membershipcard_id");
                        $checkStmt->execute(['membershipcard_id' => $membershipCardId]);
                    } while ($checkStmt->fetch());

                    // Generate unique membership_id (member ID) for this member
                    do {
                        $membershipId = generateMembershipId();
                        $checkMidStmt = $db->prepare("SELECT id FROM members WHERE membership_id = :membership_id");
                        $checkMidStmt->execute(['membership_id' => $membershipId]);
                    } while ($checkMidStmt->fetch());
                    
                    // Prepare insert statement including membershipcard_id and membership_id
                    $stmt = $db->prepare("
                        INSERT INTO members (
                            area_id, district_id, assembly_id, membershipcard_id, membership_id, family_id, title,
                            first_name, middle_name, last_name, gender, date_of_birth,
                            place_of_birth, phone, email, member_type, marital_status,
                            address_line1, gps_address, street_name, city, hometown,
                            water_baptism, date_of_baptism, place_of_baptism, officiating_minister_baptism,
                            officiating_ministers_district, holyghost_baptism, date_of_holyspirit_baptism,
                            communicant, dedicated, dedication_date, name_of_officiating_minister,
                            church_where_dedication_done, date_of_conversion, date_of_joining,
                            occupation, level_of_education, parent_name, parent_relationship,
                            created_by, is_active, created_at
                        ) VALUES (
                            :area_id, :district_id, :assembly_id, :membershipcard_id, :membership_id, :family_id, :title,
                            :first_name, :middle_name, :last_name, :gender, :date_of_birth,
                            :place_of_birth, :phone, :email, :member_type, :marital_status,
                            :address_line1, :gps_address, :street_name, :city, :hometown,
                            :water_baptism, :date_of_baptism, :place_of_baptism, :officiating_minister_baptism,
                            :officiating_ministers_district, :holyghost_baptism, :date_of_holyspirit_baptism,
                            :communicant, :dedicated, :dedication_date, :name_of_officiating_minister,
                            :church_where_dedication_done, :date_of_conversion, :date_of_joining,
                            :occupation, :level_of_education, :parent_name, :parent_relationship,
                            :created_by, 1, NOW()
                        )
                    ");
                    
                    // Execute with data
                    $stmt->execute([
                        'area_id' => $memberAreaId,
                        'district_id' => $memberDistrictId,
                        'assembly_id' => $memberAssemblyId,
                        'membershipcard_id' => $membershipCardId,
                        'membership_id' => $membershipId,
                        'family_id' => !empty($memberData['family_id']) ? $memberData['family_id'] : null,
                        'title' => $memberData['title'] ?? null,
                        'first_name' => $memberData['first_name'],
                        'middle_name' => $memberData['middle_name'] ?? null,
                        'last_name' => $memberData['last_name'],
                        'gender' => $memberData['gender'],
                        'date_of_birth' => !empty($memberData['date_of_birth']) ? $memberData['date_of_birth'] : null,
                        'place_of_birth' => $memberData['place_of_birth'] ?? null,
                        'phone' => $memberData['phone'] ?? null,
                        'email' => $memberData['email'],
                        'member_type' => $memberData['member_type'] ?? 'Full Member',
                        'marital_status' => $memberData['marital_status'] ?? null,
                        'address_line1' => $memberData['address_line1'] ?? null,
                        'gps_address' => $memberData['gps_address'] ?? null,
                        'street_name' => $memberData['street_name'] ?? null,
                        'city' => $memberData['city'] ?? null,
                        'hometown' => $memberData['hometown'] ?? null,
                        'water_baptism' => ($memberData['water_baptism'] ?? '0') == '1' ? 1 : 0,
                        'date_of_baptism' => !empty($memberData['date_of_baptism']) ? $memberData['date_of_baptism'] : null,
                        'place_of_baptism' => $memberData['place_of_baptism'] ?? null,
                        'officiating_minister_baptism' => $memberData['officiating_minister_baptism'] ?? null,
                        'officiating_ministers_district' => $memberData['officiating_ministers_district'] ?? null,
                        'holyghost_baptism' => ($memberData['holyghost_baptism'] ?? '0') == '1' ? 1 : 0,
                        'date_of_holyspirit_baptism' => !empty($memberData['date_of_holyspirit_baptism']) ? $memberData['date_of_holyspirit_baptism'] : null,
                        'communicant' => ($memberData['communicant'] ?? '0') == '1' ? 1 : 0,
                        'dedicated' => ($memberData['dedicated'] ?? '0') == '1' ? 1 : 0,
                        'dedication_date' => !empty($memberData['dedication_date']) ? $memberData['dedication_date'] : null,
                        'name_of_officiating_minister' => $memberData['name_of_officiating_minister'] ?? null,
                        'church_where_dedication_done' => $memberData['church_where_dedication_done'] ?? null,
                        'date_of_conversion' => !empty($memberData['date_of_conversion']) ? $memberData['date_of_conversion'] : null,
                        'date_of_joining' => !empty($memberData['date_of_joining']) ? $memberData['date_of_joining'] : null,
                        'occupation' => $memberData['occupation'] ?? null,
                        'level_of_education' => $memberData['level_of_education'] ?? null,
                        'parent_name' => $memberData['parent_name'] ?? null,
                        'parent_relationship' => $memberData['parent_relationship'] ?? null,
                        'created_by' => $_SESSION['user_id']
                    ]);
                    
                    $newMemberId = $db->lastInsertId();

                    // Auto-generate tracking code for uploaded member (same as add member page)
                    createMemberUserCode($db, $newMemberId, $_SESSION['user_id']);

                    // Generate membership card
                    try {
                        $membershipCard = new MembershipCard();
                        $cardNumber = $membershipCard->generateCardNumber();
                        $membershipCard->createCard($newMemberId);
                        
                        // Create member account
                        try {
                            $username = strtolower($memberData['first_name']) . '.' . strtolower($memberData['last_name']);
                            $defaultPassword = 'Member@' . date('Y');
                            $passwordHash = password_hash($defaultPassword, PASSWORD_DEFAULT);
                            $fullName = trim(($memberData['title'] ?? '') . ' ' . $memberData['first_name'] . ' ' . ($memberData['middle_name'] ?? '') . ' ' . $memberData['last_name']);
                            
                            $accountStmt = $db->prepare("
                                INSERT INTO member_accounts (
                                    member_id, username, email, password_hash, full_name, phone,
                                    access_level, area_id, district_id, assembly_id, is_active
                                ) VALUES (
                                    :member_id, :username, :email, :password_hash, :full_name, :phone,
                                    'member', :area_id, :district_id, :assembly_id, 1
                                )
                            ");
                            
                            $accountStmt->execute([
                                'member_id' => $newMemberId,
                                'username' => $username,
                                'email' => $memberData['email'],
                                'password_hash' => $passwordHash,
                                'full_name' => $fullName,
                                'phone' => $memberData['phone'] ?? null,
                                'area_id' => $memberAreaId,
                                'district_id' => $memberDistrictId,
                                'assembly_id' => $memberAssemblyId
                            ]);
                            
                            $uploadResults[] = [
                                'row' => $row,
                                'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                                'status' => 'success',
                                'card_number' => $cardNumber,
                                'message' => 'Member, Card & Account created. Password: ' . $defaultPassword
                            ];
                        } catch (Exception $accountError) {
                            $uploadResults[] = [
                                'row' => $row,
                                'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                                'status' => 'warning',
                                'card_number' => $cardNumber,
                                'message' => 'Member & Card created, but account creation failed: ' . $accountError->getMessage()
                            ];
                        }
                        
                        $successCount++;
                    } catch (Exception $cardError) {
                        $uploadResults[] = [
                            'row' => $row,
                            'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                            'status' => 'warning',
                            'message' => 'Member created but card generation failed: ' . $cardError->getMessage()
                        ];
                        $successCount++;
                    }
                }
                
                // Commit transaction
                $db->commit();
                
                // Store upload results in session for PDF export
                $_SESSION['upload_results'] = $uploadResults;
                $_SESSION['upload_date'] = date('Y-m-d H:i:s');
                
                $successMessage = "Successfully uploaded {$successCount} members with membership cards and accounts!";
                if ($errorCount > 0) {
                    $errorMessage = "{$errorCount} rows had errors and were skipped.";
                }
                
            } catch (Exception $e) {
                $db->rollBack();
                throw $e;
            }
            
            fclose($handle);
        } elseif (in_array($fileExt, ['xlsx', 'xls'])) {
            // Process Excel file
            require_once '../../vendor/autoload.php';
            
            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file['tmp_name']);
            $sheet = $spreadsheet->getActiveSheet();
            $rows = $sheet->toArray();
            
            if (empty($rows)) {
                throw new Exception('Excel file is empty');
            }
            
            // Get headers (first row)
            $headers = array_shift($rows);
            
            $successCount = 0;
            $errorCount = 0;
            $rowNum = 1;
            
            // Start transaction
            $db->beginTransaction();

            // Membership card ID generator for member IDs (Excel)
            $memberIdCardGeneratorExcel = new MembershipCard();
            
            try {
                foreach ($rows as $data) {
                    $rowNum++;
                    
                    // Skip completely empty rows
                    $isEmptyRow = true;
                    foreach ($data as $value) {
                        if (trim((string)$value) !== '') {
                            $isEmptyRow = false;
                            break;
                        }
                    }
                    if ($isEmptyRow) {
                        continue;
                    }
                    
                    // Skip sample/template row based on title cell content
                    if (isset($data[0]) && (stripos((string)$data[0], 'Mr/Mrs') !== false || $data[0] == 'Mr')) {
                        continue;
                    }
                    
                    // Map Excel data to array
                    $memberData = array_combine($headers, $data);
                    
                    // Process member data (same as CSV processing)
                    if (empty($memberData['email']) || stripos($memberData['email'], 'leave empty') !== false || stripos($memberData['email'], '@email.com') !== false) {
                        $firstName = strtolower(trim($memberData['first_name']));
                        $lastName = strtolower(trim($memberData['last_name']));
                        $memberData['email'] = $firstName . '.' . $lastName . '@church.auto';
                    }

                    // Use provided area/district/assembly or user's access level.
                    // Be flexible with values like "1 (Area ID)" by extracting the numeric portion.
                    $memberAreaId = null;
                    if (!empty($memberData['area_id'])) {
                        if (is_numeric($memberData['area_id'])) {
                            $memberAreaId = (int)$memberData['area_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['area_id'], $m)) {
                            $memberAreaId = (int)$m[1];
                        }
                    } elseif (!empty($areaId)) {
                        $memberAreaId = $areaId;
                    }

                    $memberDistrictId = null;
                    if (!empty($memberData['district_id'])) {
                        if (is_numeric($memberData['district_id'])) {
                            $memberDistrictId = (int)$memberData['district_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['district_id'], $m)) {
                            $memberDistrictId = (int)$m[1];
                        }
                    } elseif (!empty($districtId)) {
                        $memberDistrictId = $districtId;
                    }

                    $memberAssemblyId = null;
                    if (!empty($memberData['assembly_id'])) {
                        if (is_numeric($memberData['assembly_id'])) {
                            $memberAssemblyId = (int)$memberData['assembly_id'];
                        } elseif (preg_match('/(\d+)/', $memberData['assembly_id'], $m)) {
                            $memberAssemblyId = (int)$m[1];
                        }
                    } elseif (!empty($assemblyId)) {
                        $memberAssemblyId = $assemblyId;
                    }

                    if ($memberAreaId === null || $memberDistrictId === null || $memberAssemblyId === null) {
                        throw new Exception("Row {$rowNum}: Missing or invalid Area/District/Assembly ID. Please provide numeric IDs in the file or set your default location.");
                    }

                    // Generate unique membershipcard_id (card ID) for this member (Excel)
                    do {
                        $membershipCardIdExcel = $memberIdCardGeneratorExcel->generateCardNumber();
                        $checkStmt = $db->prepare("SELECT id FROM members WHERE membershipcard_id = :membershipcard_id");
                        $checkStmt->execute(['membershipcard_id' => $membershipCardIdExcel]);
                    } while ($checkStmt->fetch());

                    // Generate unique membership_id (member ID) for this member (Excel)
                    do {
                        $membershipIdExcel = generateMembershipId();
                        $checkMidStmt = $db->prepare("SELECT id FROM members WHERE membership_id = :membership_id");
                        $checkMidStmt->execute(['membership_id' => $membershipIdExcel]);
                    } while ($checkMidStmt->fetch());

                    // Insert member (same query as CSV, including membershipcard_id)
                    $stmt = $db->prepare("
                        INSERT INTO members (
                            area_id, district_id, assembly_id, membershipcard_id, membership_id, family_id, title,
                            first_name, middle_name, last_name, gender, date_of_birth,
                            place_of_birth, phone, email, member_type, marital_status,
                            address_line1, gps_address, street_name, city, hometown,
                            water_baptism, date_of_baptism, place_of_baptism, officiating_minister_baptism,
                            officiating_ministers_district, holyghost_baptism, date_of_holyspirit_baptism,
                            communicant, dedicated, dedication_date, name_of_officiating_minister,
                            church_where_dedication_done, date_of_conversion, date_of_joining,
                            occupation, level_of_education, parent_name, parent_relationship,
                            created_by, is_active, created_at
                        ) VALUES (
                            :area_id, :district_id, :assembly_id, :membershipcard_id, :membership_id, :family_id, :title,
                            :first_name, :middle_name, :last_name, :gender, :date_of_birth,
                            :place_of_birth, :phone, :email, :member_type, :marital_status,
                            :address_line1, :gps_address, :street_name, :city, :hometown,
                            :water_baptism, :date_of_baptism, :place_of_baptism, :officiating_minister_baptism,
                            :officiating_ministers_district, :holyghost_baptism, :date_of_holyspirit_baptism,
                            :communicant, :dedicated, :dedication_date, :name_of_officiating_minister,
                            :church_where_dedication_done, :date_of_conversion, :date_of_joining,
                            :occupation, :level_of_education, :parent_name, :parent_relationship,
                            :created_by, 1, NOW()
                        )
                    ");

                    $stmt->execute([
                        'area_id' => $memberAreaId,
                        'district_id' => $memberDistrictId,
                        'assembly_id' => $memberAssemblyId,
                        'membershipcard_id' => $membershipCardIdExcel,
                        'family_id' => !empty($memberData['family_id']) ? $memberData['family_id'] : null,
                        'title' => $memberData['title'] ?? null,
                        'first_name' => $memberData['first_name'],
                        'middle_name' => $memberData['middle_name'] ?? null,
                        'last_name' => $memberData['last_name'],
                        'gender' => $memberData['gender'],
                        'date_of_birth' => !empty($memberData['date_of_birth']) ? $memberData['date_of_birth'] : null,
                        'place_of_birth' => $memberData['place_of_birth'] ?? null,
                        'phone' => $memberData['phone'] ?? null,
                        'email' => $memberData['email'],
                        'member_type' => $memberData['member_type'] ?? 'Full Member',
                        'marital_status' => $memberData['marital_status'] ?? null,
                        'address_line1' => $memberData['address_line1'] ?? null,
                        'gps_address' => $memberData['gps_address'] ?? null,
                        'street_name' => $memberData['street_name'] ?? null,
                        'city' => $memberData['city'] ?? null,
                        'hometown' => $memberData['hometown'] ?? null,
                        'water_baptism' => ($memberData['water_baptism'] ?? '0') == '1' ? 1 : 0,
                        'date_of_baptism' => !empty($memberData['date_of_baptism']) ? $memberData['date_of_baptism'] : null,
                        'place_of_baptism' => $memberData['place_of_baptism'] ?? null,
                        'officiating_minister_baptism' => $memberData['officiating_minister_baptism'] ?? null,
                        'officiating_ministers_district' => $memberData['officiating_ministers_district'] ?? null,
                        'holyghost_baptism' => ($memberData['holyghost_baptism'] ?? '0') == '1' ? 1 : 0,
                        'date_of_holyspirit_baptism' => !empty($memberData['date_of_holyspirit_baptism']) ? $memberData['date_of_holyspirit_baptism'] : null,
                        'communicant' => ($memberData['communicant'] ?? '0') == '1' ? 1 : 0,
                        'dedicated' => ($memberData['dedicated'] ?? '0') == '1' ? 1 : 0,
                        'dedication_date' => !empty($memberData['dedication_date']) ? $memberData['dedication_date'] : null,
                        'name_of_officiating_minister' => $memberData['name_of_officiating_minister'] ?? null,
                        'church_where_dedication_done' => $memberData['church_where_dedication_done'] ?? null,
                        'date_of_conversion' => !empty($memberData['date_of_conversion']) ? $memberData['date_of_conversion'] : null,
                        'date_of_joining' => !empty($memberData['date_of_joining']) ? $memberData['date_of_joining'] : null,
                        'occupation' => $memberData['occupation'] ?? null,
                        'level_of_education' => $memberData['level_of_education'] ?? null,
                        'parent_name' => $memberData['parent_name'] ?? null,
                        'parent_relationship' => $memberData['parent_relationship'] ?? null,
                        'created_by' => $_SESSION['user_id']
                    ]);
                    
                    $newMemberId = $db->lastInsertId();

                    // Auto-generate member tracking code for uploaded member
                    createMemberUserCode($db, $newMemberId, $_SESSION['user_id']);

                    // Generate membership card
                    try {
                        $membershipCard = new MembershipCard();
                        $cardNumber = $membershipCard->generateCardNumber();
                        $membershipCard->createCard($newMemberId);
                        
                        // Create member account
                        try {
                            $username = strtolower($memberData['first_name']) . '.' . strtolower($memberData['last_name']);
                            $defaultPassword = 'Member@' . date('Y');
                            $passwordHash = password_hash($defaultPassword, PASSWORD_DEFAULT);
                            $fullName = trim(($memberData['title'] ?? '') . ' ' . $memberData['first_name'] . ' ' . ($memberData['middle_name'] ?? '') . ' ' . $memberData['last_name']);
                            
                            $accountStmt = $db->prepare("
                                INSERT INTO member_accounts (
                                    member_id, username, email, password_hash, full_name, phone,
                                    access_level, area_id, district_id, assembly_id, is_active
                                ) VALUES (
                                    :member_id, :username, :email, :password_hash, :full_name, :phone,
                                    'member', :area_id, :district_id, :assembly_id, 1
                                )
                            ");
                            
                            $accountStmt->execute([
                                'member_id' => $newMemberId,
                                'username' => $username,
                                'email' => $memberData['email'],
                                'password_hash' => $passwordHash,
                                'full_name' => $fullName,
                                'phone' => $memberData['phone'] ?? null,
                                'area_id' => $memberAreaId,
                                'district_id' => $memberDistrictId,
                                'assembly_id' => $memberAssemblyId
                            ]);
                            
                            $uploadResults[] = [
                                'row' => $rowNum,
                                'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                                'status' => 'success',
                                'card_number' => $cardNumber,
                                'message' => 'Member, Card & Account created. Password: ' . $defaultPassword
                            ];
                        } catch (Exception $accountError) {
                            $uploadResults[] = [
                                'row' => $rowNum,
                                'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                                'status' => 'warning',
                                'card_number' => $cardNumber,
                                'message' => 'Member & Card created, but account creation failed: ' . $accountError->getMessage()
                            ];
                        }
                        
                        $successCount++;
                    } catch (Exception $cardError) {
                        $uploadResults[] = [
                            'row' => $rowNum,
                            'name' => $memberData['first_name'] . ' ' . $memberData['last_name'],
                            'status' => 'warning',
                            'message' => 'Member created but card generation failed: ' . $cardError->getMessage()
                        ];
                        $successCount++;
                    }
                }
                
                // Commit transaction
                $db->commit();
                
                // Store upload results in session for PDF export
                $_SESSION['upload_results'] = $uploadResults;
                $_SESSION['upload_date'] = date('Y-m-d H:i:s');
                
                $successMessage = "Successfully uploaded {$successCount} members with membership cards and accounts!";
                if ($errorCount > 0) {
                    $errorMessage = "{$errorCount} rows had errors and were skipped.";
                }
                
            } catch (Exception $e) {
                $db->rollBack();
                throw $e;
            }
        }
        
    } catch (Exception $e) {
        $errorMessage = "Upload failed: " . $e->getMessage();
    }
}

// Get areas, districts, assemblies for reference
$areasStmt = $db->query("SELECT id, area_name FROM areas WHERE is_active = 1 ORDER BY area_name");
$areas = $areasStmt->fetchAll(PDO::FETCH_ASSOC);

$districtsStmt = $db->query("SELECT id, district_name, area_id FROM districts ORDER BY district_name");
$districts = $districtsStmt->fetchAll(PDO::FETCH_ASSOC);

$assembliesStmt = $db->query("SELECT id, assembly_name, district_id FROM assemblies ORDER BY assembly_name");
$assemblies = $assembliesStmt->fetchAll(PDO::FETCH_ASSOC);

include '../../includes/header.php';
?>

<?php include '../../includes/sidebar.php'; ?>

<!-- Main Content -->
<main class="flex-1 md:ml-64 mt-16 min-h-screen bg-gray-50">
    <div class="container mx-auto px-4 py-8">
        <!-- Page Header -->
        <div class="gradient-bg rounded-2xl shadow-2xl p-8 mb-8 text-white">
            <div class="flex items-center justify-between flex-wrap gap-4">
                <div>
                    <h1 class="text-4xl font-bold mb-2">
                        <i class="fas fa-upload mr-3"></i>Upload Members
                    </h1>
                    <p class="text-white/90 text-lg">Bulk import members from CSV or Excel file</p>
                </div>
                <div class="flex items-center gap-3">
                    <a href="special_upload.php" class="px-6 py-3 bg-white/20 hover:bg-white/30 text-white rounded-full font-semibold transition backdrop-blur-sm">
                        <i class="fas fa-magic mr-2"></i>Special Upload
                    </a>
                    <a href="index.php" class="px-6 py-3 bg-white/20 hover:bg-white/30 text-white rounded-full font-semibold transition backdrop-blur-sm">
                        <i class="fas fa-arrow-left mr-2"></i>Back to Members
                    </a>
                </div>
            </div>
        </div>

        <!-- Success Message -->
        <?php if ($successMessage): ?>
            <div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-6 rounded-lg mb-6 animate-fadeIn">
                <div class="flex items-center">
                    <i class="fas fa-check-circle text-3xl mr-4"></i>
                    <div>
                        <p class="font-bold text-lg"><?php echo $successMessage; ?></p>
                        <?php if (!empty($uploadResults)): ?>
                            <p class="text-sm mt-2">View details below for individual results</p>
                        <?php endif; ?>
                    </div>
                </div>
            </div>
        <?php endif; ?>

        <!-- Error Message -->
        <?php if ($errorMessage): ?>
            <div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-6 rounded-lg mb-6 animate-fadeIn">
                <div class="flex items-center">
                    <i class="fas fa-exclamation-circle text-3xl mr-4"></i>
                    <p class="font-bold text-lg"><?php echo $errorMessage; ?></p>
                </div>
            </div>
        <?php endif; ?>

        <!-- Upload Results -->
        <?php if (!empty($uploadResults)): ?>
            <div class="bg-white rounded-2xl shadow-lg p-6 mb-8">
                <div class="flex items-center justify-between mb-4">
                    <h3 class="text-2xl font-bold text-gray-800">
                        <i class="fas fa-list-check mr-2 text-gradient"></i>Upload Results
                    </h3>
                    <a href="?action=export_pdf" class="btn-gradient text-white px-6 py-3 rounded-lg font-bold hover:shadow-xl transition inline-flex items-center">
                        <i class="fas fa-file-pdf mr-2"></i>Export to PDF
                    </a>
                </div>
                <div class="overflow-x-auto">
                    <table class="w-full">
                        <thead class="bg-gray-100">
                            <tr>
                                <th class="px-4 py-3 text-left text-sm font-semibold text-gray-700">Row</th>
                                <th class="px-4 py-3 text-left text-sm font-semibold text-gray-700">Member Name</th>
                                <th class="px-4 py-3 text-left text-sm font-semibold text-gray-700">Status</th>
                                <th class="px-4 py-3 text-left text-sm font-semibold text-gray-700">Card Number</th>
                                <th class="px-4 py-3 text-left text-sm font-semibold text-gray-700">Message</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-gray-200">
                            <?php foreach ($uploadResults as $result): ?>
                                <tr>
                                    <td class="px-4 py-3 text-sm"><?php echo $result['row']; ?></td>
                                    <td class="px-4 py-3 text-sm font-medium"><?php echo htmlspecialchars($result['name']); ?></td>
                                    <td class="px-4 py-3 text-sm">
                                        <?php if ($result['status'] == 'success'): ?>
                                            <span class="px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800">
                                                <i class="fas fa-check mr-1"></i>Success
                                            </span>
                                        <?php elseif ($result['status'] == 'warning'): ?>
                                            <span class="px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800">
                                                <i class="fas fa-exclamation-triangle mr-1"></i>Warning
                                            </span>
                                        <?php else: ?>
                                            <span class="px-3 py-1 rounded-full text-xs font-semibold bg-red-100 text-red-800">
                                                <i class="fas fa-times mr-1"></i>Error
                                            </span>
                                        <?php endif; ?>
                                    </td>
                                    <td class="px-4 py-3 text-sm font-mono"><?php echo $result['card_number'] ?? '-'; ?></td>
                                    <td class="px-4 py-3 text-sm text-gray-600"><?php echo $result['message'] ?? '-'; ?></td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        <?php endif; ?>

        <!-- Instructions & Upload Form -->
        <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
            <!-- Instructions -->
            <div class="bg-white rounded-2xl shadow-lg p-8">
                <h2 class="text-2xl font-bold text-gray-800 mb-6">
                    <i class="fas fa-info-circle mr-2 text-blue-600"></i>Instructions
                </h2>
                
                <div class="space-y-4 text-gray-700">
                    <div class="flex items-start">
                        <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center font-bold text-white mr-3" style="background: linear-gradient(135deg, #1E40AF 0%, #9333EA 100%);">1</div>
                        <div>
                            <p class="font-semibold mb-1">Download Template</p>
                            <p class="text-sm">Click the button below to download the CSV template with all required fields.</p>
                        </div>
                    </div>
                    
                    <div class="flex items-start">
                        <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center font-bold text-white mr-3" style="background: linear-gradient(135deg, #F97316 0%, #FBBF24 100%);">2</div>
                        <div>
                            <p class="font-semibold mb-1">Fill Member Data</p>
                            <p class="text-sm">Open the file in Excel or Google Sheets and fill in the member information. Delete the sample row.</p>
                        </div>
                    </div>
                    
                    <div class="flex items-start">
                        <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center font-bold text-white mr-3" style="background: linear-gradient(135deg, #9333EA 0%, #F97316 100%);">3</div>
                        <div>
                            <p class="font-semibold mb-1">Upload File</p>
                            <p class="text-sm">Save as CSV and upload the file. The system will automatically generate membership IDs and cards.</p>
                        </div>
                    </div>
                </div>
                
                <div class="mt-8 p-4 bg-blue-50 border-l-4 border-blue-500 rounded">
                    <p class="text-sm font-semibold text-blue-800 mb-2"><i class="fas fa-lightbulb mr-2"></i>Important Notes:</p>
                    <ul class="text-sm text-blue-700 space-y-1 list-disc list-inside">
                        <li><strong>Email:</strong> Leave empty to auto-generate (firstname.lastname@church.auto)</li>
                        <li><strong>Membership Card:</strong> Automatically created for each member</li>
                        <li><strong>Member Account:</strong> Automatically created (Username: firstname.lastname, Password: Member@2025)</li>
                        <li><strong>File Format:</strong> Download CSV or Excel template (both supported for upload)</li>
                        <li><strong>Required fields:</strong> first_name, last_name, gender</li>
                        <li><strong>Dates:</strong> Use format YYYY-MM-DD (e.g., 2024-01-15)</li>
                        <li><strong>Boolean fields:</strong> Use 1 for Yes, 0 for No</li>
                    </ul>
                </div>
                
                <div class="mt-6 flex gap-4 flex-wrap">
                    <a href="?action=download_template" class="btn-gradient-orange text-white px-8 py-4 rounded-full font-bold inline-flex items-center shadow-lg hover:shadow-xl transition">
                        <i class="fas fa-file-csv mr-2"></i>Download CSV Template
                    </a>
                    <a href="?action=download_excel" class="btn-gradient text-white px-8 py-4 rounded-full font-bold inline-flex items-center shadow-lg hover:shadow-xl transition">
                        <i class="fas fa-file-excel mr-2"></i>Download Excel Template
                    </a>
                </div>
            </div>

            <!-- Upload Form -->
            <div class="bg-white rounded-2xl shadow-lg p-8">
                <h2 class="text-2xl font-bold text-gray-800 mb-6">
                    <i class="fas fa-cloud-upload-alt mr-2 text-green-600"></i>Upload File
                </h2>
                
                <form method="POST" enctype="multipart/form-data" class="space-y-6">
                    <div>
                        <label class="block text-sm font-bold text-gray-700 mb-3">Select CSV or Excel File</label>
                        <div class="border-2 border-dashed border-gray-300 rounded-xl p-8 text-center hover:border-blue-500 transition">
                            <i class="fas fa-file-upload text-5xl text-gray-400 mb-4"></i>
                            <input type="file" 
                                   id="member_file_input"
                                   name="member_file" 
                                   accept=".csv,.xlsx,.xls" 
                                   required
                                   class="block w-full text-sm text-gray-500 file:mr-4 file:py-3 file:px-6 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 cursor-pointer">
                            <p class="text-sm text-gray-500 mt-2">CSV, XLSX or XLS (Max 10MB)</p>
                        </div>
                    </div>

                    <!-- File Preview -->
                    <div id="file_preview_container" class="hidden bg-gray-50 border border-gray-200 rounded-xl p-4">
                        <div class="flex items-center justify-between mb-2">
                            <h3 class="text-sm font-semibold text-gray-800 flex items-center">
                                <i class="fas fa-eye mr-2 text-blue-600"></i>File Preview (first 10 rows)
                            </h3>
                            <span id="file_preview_filename" class="text-xs text-gray-500"></span>
                        </div>
                        <div id="file_preview_warning" class="text-xs text-yellow-700 bg-yellow-50 border border-yellow-200 rounded px-3 py-2 mb-2 hidden">
                            Preview is optimized for CSV files. Excel files may not show detailed row preview in the browser.
                        </div>
                        <div class="overflow-x-auto max-h-64">
                            <table class="min-w-full text-xs">
                                <thead id="file_preview_head" class="bg-gray-100 text-gray-700"></thead>
                                <tbody id="file_preview_body" class="divide-y divide-gray-200"></tbody>
                            </table>
                        </div>
                    </div>
                    
                    <div class="bg-gray-50 rounded-lg p-4">
                        <h3 class="font-semibold text-gray-800 mb-3">Your Default Location</h3>
                        <div class="text-sm text-gray-600 space-y-1">
                            <?php if ($accessLevel == 'superuser'): ?>
                                <p><i class="fas fa-info-circle mr-2"></i>You can upload members to any location by specifying IDs in the file</p>
                            <?php elseif ($accessLevel == 'area'): ?>
                                <p><i class="fas fa-map mr-2"></i>Area: <?php 
                                    $areaStmt = $db->prepare("SELECT area_name FROM areas WHERE id = ?");
                                    $areaStmt->execute([$areaId]);
                                    echo htmlspecialchars($areaStmt->fetchColumn());
                                ?></p>
                            <?php elseif ($accessLevel == 'district'): ?>
                                <p><i class="fas fa-map-marked mr-2"></i>District: <?php 
                                    $districtStmt = $db->prepare("SELECT district_name FROM districts WHERE id = ?");
                                    $districtStmt->execute([$districtId]);
                                    echo htmlspecialchars($districtStmt->fetchColumn());
                                ?></p>
                            <?php elseif ($accessLevel == 'assembly'): ?>
                                <p><i class="fas fa-church mr-2"></i>Assembly: <?php 
                                    $assemblyStmt = $db->prepare("SELECT assembly_name FROM assemblies WHERE id = ?");
                                    $assemblyStmt->execute([$assemblyId]);
                                    echo htmlspecialchars($assemblyStmt->fetchColumn());
                                ?></p>
                            <?php endif; ?>
                            <p class="text-xs mt-2"><i class="fas fa-lightbulb mr-1"></i>Members without location IDs will be assigned to your default location</p>
                        </div>
                    </div>
                    
                    <button type="submit" class="btn-gradient w-full text-white px-8 py-4 rounded-full font-bold text-lg shadow-xl hover:shadow-2xl transition">
                        <i class="fas fa-upload mr-2"></i>Upload Members
                    </button>
                </form>
                
                <!-- Reference Tables -->
                <div class="mt-8 p-4 bg-yellow-50 border-l-4 border-yellow-500 rounded">
                    <div class="flex items-center justify-between mb-3">
                        <p class="text-sm font-semibold text-yellow-800"><i class="fas fa-table mr-2"></i>Reference IDs</p>
                        <a href="?action=export_reference_ids" class="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg text-xs font-bold transition inline-flex items-center">
                            <i class="fas fa-file-pdf mr-2"></i>Export Full List
                        </a>
                    </div>
                    <div class="grid grid-cols-3 gap-4 text-xs">
                        <div>
                            <p class="font-semibold text-yellow-900 mb-1">Areas</p>
                            <?php foreach (array_slice($areas, 0, 3) as $area): ?>
                                <p class="text-yellow-700"><?php echo $area['id']; ?>: <?php echo htmlspecialchars($area['area_name']); ?></p>
                            <?php endforeach; ?>
                            <?php if (count($areas) > 3): ?>
                                <p class="text-yellow-600 italic">+<?php echo count($areas) - 3; ?> more...</p>
                            <?php endif; ?>
                        </div>
                        <div>
                            <p class="font-semibold text-yellow-900 mb-1">Districts</p>
                            <?php foreach (array_slice($districts, 0, 3) as $district): ?>
                                <p class="text-yellow-700"><?php echo $district['id']; ?>: <?php echo htmlspecialchars($district['district_name']); ?></p>
                            <?php endforeach; ?>
                            <?php if (count($districts) > 3): ?>
                                <p class="text-yellow-600 italic">+<?php echo count($districts) - 3; ?> more...</p>
                            <?php endif; ?>
                        </div>
                        <div>
                            <p class="font-semibold text-yellow-900 mb-1">Assemblies</p>
                            <?php foreach (array_slice($assemblies, 0, 3) as $assembly): ?>
                                <p class="text-yellow-700"><?php echo $assembly['id']; ?>: <?php echo htmlspecialchars($assembly['assembly_name']); ?></p>
                            <?php endforeach; ?>
                            <?php if (count($assemblies) > 3): ?>
                                <p class="text-yellow-600 italic">+<?php echo count($assemblies) - 3; ?> more...</p>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>

<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
    const fileInput = document.getElementById('member_file_input');
    const previewContainer = document.getElementById('file_preview_container');
    const previewHead = document.getElementById('file_preview_head');
    const previewBody = document.getElementById('file_preview_body');
    const previewFilename = document.getElementById('file_preview_filename');
    const previewWarning = document.getElementById('file_preview_warning');

    if (!fileInput) {
        return;
    }

    fileInput.addEventListener('change', function (event) {
        const file = event.target.files[0];
        previewHead.innerHTML = '';
        previewBody.innerHTML = '';
        previewWarning.classList.add('hidden');

        if (!file) {
            previewContainer.classList.add('hidden');
            previewFilename.textContent = '';
            return;
        }

        const fileName = file.name || '';
        previewFilename.textContent = fileName;
        const lowerName = fileName.toLowerCase();

        const maxRows = 10;
        const reader = new FileReader();

        // Handle CSV files
        if (lowerName.endsWith('.csv')) {
            reader.onload = function (e) {
                const text = e.target.result || '';
                if (!text) {
                    previewContainer.classList.add('hidden');
                    return;
                }

                const lines = text.split(/\r?\n/).filter(line => line.trim() !== '');
                if (lines.length === 0) {
                    previewContainer.classList.add('hidden');
                    return;
                }

                const headerLine = lines[0];
                const headers = headerLine.split(',');

                // Render header
                let headHtml = '<tr>';
                headers.forEach(h => {
                    headHtml += '<th class="px-2 py-1 text-left font-semibold">' + h.replace(/</g, '&lt;').replace(/>/g, '&gt;') + '</th>';
                });
                headHtml += '</tr>';
                previewHead.innerHTML = headHtml;

                // Render body rows
                let bodyHtml = '';
                for (let i = 1; i < Math.min(lines.length, maxRows); i++) {
                    const row = lines[i].split(',');
                    if (row.every(cell => cell.trim() === '')) {
                        continue;
                    }
                    bodyHtml += '<tr>';
                    headers.forEach((_, idx) => {
                        const cell = (row[idx] || '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                        bodyHtml += '<td class="px-2 py-1 text-gray-700">' + cell + '</td>';
                    });
                    bodyHtml += '</tr>';
                }

                previewBody.innerHTML = bodyHtml || '<tr><td class="px-2 py-2 text-gray-500">No data rows found in file.</td></tr>';
                previewContainer.classList.remove('hidden');
            };

            reader.onerror = function () {
                previewContainer.classList.add('hidden');
            };

            reader.readAsText(file);
            previewWarning.classList.add('hidden');
            previewContainer.classList.remove('hidden');
            return;
        }

        // Handle Excel files (.xlsx, .xls) using SheetJS
        if (lowerName.endsWith('.xlsx') || lowerName.endsWith('.xls')) {
            reader.onload = function (e) {
                try {
                    const data = new Uint8Array(e.target.result);
                    const workbook = XLSX.read(data, { type: 'array' });
                    const firstSheetName = workbook.SheetNames[0];
                    const sheet = workbook.Sheets[firstSheetName];
                    const sheetJson = XLSX.utils.sheet_to_json(sheet, { header: 1 }); // array of arrays

                    if (!sheetJson || sheetJson.length === 0) {
                        previewContainer.classList.add('hidden');
                        return;
                    }

                    const headers = sheetJson[0];

                    // Render header
                    let headHtml = '<tr>';
                    headers.forEach(h => {
                        const headerText = (h !== undefined && h !== null ? String(h) : '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                        headHtml += '<th class="px-2 py-1 text-left font-semibold">' + headerText + '</th>';
                    });
                    headHtml += '</tr>';
                    previewHead.innerHTML = headHtml;

                    // Render body rows
                    let bodyHtml = '';
                    for (let i = 1; i < Math.min(sheetJson.length, maxRows); i++) {
                        const row = sheetJson[i] || [];
                        if (row.length === 0 || row.every(cell => String(cell).trim() === '')) {
                            continue;
                        }
                        bodyHtml += '<tr>';
                        headers.forEach((_, idx) => {
                            const cellVal = row[idx] !== undefined && row[idx] !== null ? String(row[idx]) : '';
                            const cell = cellVal.replace(/</g, '&lt;').replace(/>/g, '&gt;');
                            bodyHtml += '<td class="px-2 py-1 text-gray-700">' + cell + '</td>';
                        });
                        bodyHtml += '</tr>';
                    }

                    previewBody.innerHTML = bodyHtml || '<tr><td class="px-2 py-2 text-gray-500">No data rows found in sheet.</td></tr>';
                    previewWarning.classList.add('hidden');
                    previewContainer.classList.remove('hidden');
                } catch (err) {
                    previewWarning.textContent = 'Could not preview Excel file in browser.';
                    previewWarning.classList.remove('hidden');
                    previewContainer.classList.remove('hidden');
                }
            };

            reader.onerror = function () {
                previewWarning.textContent = 'Could not read Excel file for preview.';
                previewWarning.classList.remove('hidden');
                previewContainer.classList.remove('hidden');
            };

            reader.readAsArrayBuffer(file);
            return;
        }

        // Unsupported extension
        previewWarning.textContent = 'Preview is available for CSV and standard Excel files only.';
        previewWarning.classList.remove('hidden');
        previewContainer.classList.remove('hidden');
    });
});
</script>

<?php include '../../includes/footer.php'; ?>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists