<?php
// ajax/import_patients.php
session_start();
require_once '../layouts/dbconn.php';
require_once '../layouts/session.php';

header('Content-Type: application/json');

// Create logs directory if it doesn't exist
$logDir = __DIR__ . '/../logs';
if (!is_dir($logDir)) {
    mkdir($logDir, 0777, true);
}

// Error logging function
function logError($message) {
    $logFile = __DIR__ . '/../logs/import_debug.log';
    $timestamp = date('Y-m-d H:i:s');
    file_put_contents($logFile, "[$timestamp] $message\n", FILE_APPEND);
}

// Catch all errors
set_error_handler(function($errno, $errstr, $errfile, $errline) {
    logError("PHP Error [$errno]: $errstr in $errfile on line $errline");
});

// Catch fatal errors
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        logError("Fatal Error: " . print_r($error, true));
        echo json_encode([
            'success' => false,
            'message' => 'Fatal error occurred: ' . $error['message'],
            'file' => $error['file'],
            'line' => $error['line']
        ]);
    }
});

logError("Import request received");

// Check authorization
if (!isset($_SESSION['user_id'])) {
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit();
}

$allowed_roles = ['SUPER_ADMIN', 'HOSPITAL_ADMIN'];
if (!in_array($_SESSION['role_code'], $allowed_roles)) {
    echo json_encode(['success' => false, 'message' => 'Insufficient permissions']);
    exit();
}

// Get JSON input
$input = json_decode(file_get_contents('php://input'), true);

if (!isset($input['patients']) || !is_array($input['patients'])) {
    echo json_encode(['success' => false, 'message' => 'Invalid input data']);
    exit();
}

$patients = $input['patients'];
$skipDuplicates = isset($input['skipDuplicates']) ? $input['skipDuplicates'] : true;
$updateExisting = isset($input['updateExisting']) ? $input['updateExisting'] : false;

$imported = 0;
$skipped = 0;
$errors = 0;
$errorDetails = [];

// Global counter for ensuring uniqueness across rapid calls
static $importCounter = 0;

try {
    foreach ($patients as $index => $patientData) {
        try {
            $conn->begin_transaction();
            
            $patientInfo = $patientData['patientInfo'];
            $visits = isset($patientData['visits']) ? $patientData['visits'] : [];

            // Validate required fields
            if (empty($patientInfo['patient_number'])) {
                throw new Exception("Missing patient number");
            }
            if (empty($patientInfo['full_name'])) {
                throw new Exception("Missing patient name");
            }

            // Check if patient exists
            $patientNumber = $conn->real_escape_string($patientInfo['patient_number']);
            $checkStmt = $conn->prepare("
                SELECT patient_id, user_id 
                FROM patients 
                WHERE patient_number = ?
            ");
            $checkStmt->bind_param("s", $patientNumber);
            $checkStmt->execute();
            $existingPatient = $checkStmt->get_result()->fetch_assoc();
            $checkStmt->close();

            if ($existingPatient) {
                if ($skipDuplicates && !$updateExisting) {
                    $skipped++;
                    $conn->rollback();
                    continue;
                }

                if ($updateExisting) {
                    updatePatient($conn, $existingPatient['patient_id'], $existingPatient['user_id'], $patientInfo);
                    
                    // Import visits with consultations
                    foreach ($visits as $visit) {
                        $importCounter++;
                        importVisit($conn, $existingPatient['patient_id'], $visit, $importCounter);
                    }
                    
                    $imported++;
                    $conn->commit();
                } else {
                    $skipped++;
                    $conn->rollback();
                }
            } else {
                // Import new patient
                $patientId = importNewPatient($conn, $patientInfo);
                
                if ($patientId) {
                    // Import visits with consultations
                    foreach ($visits as $visit) {
                        $importCounter++;
                        importVisit($conn, $patientId, $visit, $importCounter);
                    }
                    
                    $imported++;
                    $conn->commit();
                } else {
                    throw new Exception("Failed to create patient record");
                }
            }

        } catch (Exception $e) {
            $errors++;
            $errorMsg = "Patient " . ($patientInfo['patient_number'] ?? 'unknown') . ": " . $e->getMessage();
            $errorDetails[] = $errorMsg;
            logError($errorMsg);
            $conn->rollback();
            continue;
        }
    }

    // Log activity - CORRECTED COLUMNS
    $ipAddress = $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
    $logStmt = $conn->prepare("
        INSERT INTO activity_logs (user_id, action, entity_type, entity_id, description, ip_address, created_at)
        VALUES (?, 'IMPORT', 'PATIENT', NULL, ?, ?, NOW())
    ");
    $description = "Imported $imported patients, skipped $skipped, errors $errors out of " . count($patients) . " total records";
    $logStmt->bind_param("iss", $_SESSION['user_id'], $description, $ipAddress);
    $logStmt->execute();
    $logStmt->close();

    echo json_encode([
        'success' => true,
        'imported' => $imported,
        'skipped' => $skipped,
        'errors' => $errors,
        'errorDetails' => array_slice($errorDetails, 0, 10)
    ]);

} catch (Exception $e) {
    logError("Import failed: " . $e->getMessage());
    echo json_encode([
        'success' => false,
        'message' => 'Import failed: ' . $e->getMessage(),
        'imported' => $imported,
        'skipped' => $skipped,
        'errors' => $errors,
        'errorDetails' => $errorDetails
    ]);
}

function importNewPatient($conn, $patientInfo) {
    // Generate username from patient number
    $username = 'patient_' . strtolower(str_replace(['/', ' ', '-'], '_', $patientInfo['patient_number']));
    $username = preg_replace('/[^a-z0-9_]/', '', $username);
    
    // Check if username exists
    $checkUser = $conn->prepare("SELECT user_id FROM users WHERE username = ?");
    $checkUser->bind_param("s", $username);
    $checkUser->execute();
    if ($checkUser->get_result()->num_rows > 0) {
        $username .= '_' . bin2hex(random_bytes(4));
    }
    $checkUser->close();
    
    $defaultPassword = password_hash('Patient@123', PASSWORD_DEFAULT);
    $roleId = 6; // Patient role ID
    
    // Prepare user data
    $fullName = $conn->real_escape_string($patientInfo['full_name']);
    $phoneNumber = isset($patientInfo['phone_number']) ? $conn->real_escape_string($patientInfo['phone_number']) : '';
    
    // Generate unique email
    $email = '';
    if ($phoneNumber) {
        $baseEmail = $phoneNumber . '@imported.patient';
        $checkEmail = $conn->prepare("SELECT user_id FROM users WHERE email = ?");
        $checkEmail->bind_param("s", $baseEmail);
        $checkEmail->execute();
        if ($checkEmail->get_result()->num_rows > 0) {
            $email = $phoneNumber . '_' . bin2hex(random_bytes(4)) . '@imported.patient';
        } else {
            $email = $baseEmail;
        }
        $checkEmail->close();
    } else {
        $email = strtolower(str_replace(['/', ' ', '-'], '_', $patientInfo['patient_number'])) . '_' . bin2hex(random_bytes(4)) . '@imported.patient';
    }
    
    $gender = isset($patientInfo['gender']) ? strtoupper($conn->real_escape_string($patientInfo['gender'])) : 'MALE';
    
    // Standardize gender
    if (in_array($gender, ['M', 'MALE', 'MAN'])) {
        $gender = 'MALE';
    } elseif (in_array($gender, ['F', 'FEMALE', 'WOMAN'])) {
        $gender = 'FEMALE';
    }
    
    // Parse age to date of birth
    $dateOfBirth = null;
    if (isset($patientInfo['age'])) {
        $age = parseAge($patientInfo['age']);
        if ($age) {
            $dateOfBirth = date('Y-m-d', strtotime("-$age years"));
        }
    }
    
    // Insert user
    $userStmt = $conn->prepare("
        INSERT INTO users (
            username, password_hash, full_name, email, phone_primary, 
            gender, date_of_birth, role_id, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
    ");
    
    $userStmt->bind_param("sssssssi", 
        $username, $defaultPassword, $fullName, $email, 
        $phoneNumber, $gender, $dateOfBirth, $roleId
    );
    
    if (!$userStmt->execute()) {
        throw new Exception("Failed to create user: " . $userStmt->error);
    }
    
    $userId = $userStmt->insert_id;
    $userStmt->close();

    // Determine registration type
    $registrationType = 'WALK_IN';
    if (isset($patientInfo['insurance_provider_id']) && !empty($patientInfo['insurance_provider_id'])) {
        $registrationType = 'INSURANCE';
    } elseif (isset($patientInfo['company_name']) && !empty($patientInfo['company_name'])) {
        $registrationType = 'CORPORATE';
    }

    // Get insurance provider ID if exists
    $insuranceProviderId = null;
    if (isset($patientInfo['insurance_provider_id']) && !empty($patientInfo['insurance_provider_id'])) {
        $insuranceCode = $conn->real_escape_string($patientInfo['insurance_provider_id']);
        $insuranceStmt = $conn->prepare("
            SELECT provider_id 
            FROM insurance_providers 
            WHERE provider_code = ? OR provider_name LIKE ?
            LIMIT 1
        ");
        $searchName = "%$insuranceCode%";
        $insuranceStmt->bind_param("ss", $insuranceCode, $searchName);
        $insuranceStmt->execute();
        $insuranceResult = $insuranceStmt->get_result()->fetch_assoc();
        if ($insuranceResult) {
            $insuranceProviderId = $insuranceResult['provider_id'];
        }
        $insuranceStmt->close();
    }

    // Insert patient record
    $patientStmt = $conn->prepare("
        INSERT INTO patients (
            user_id, patient_number, registration_type, 
            insurance_provider_id, insurance_number, policy_number,
            employer, marital_status, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
    ");

    $insuranceNumber = isset($patientInfo['membership_number']) ? $conn->real_escape_string($patientInfo['membership_number']) : null;
    $policyNumber = isset($patientInfo['membership_number']) ? $conn->real_escape_string($patientInfo['membership_number']) : null;
    $employer = isset($patientInfo['company_name']) ? $conn->real_escape_string($patientInfo['company_name']) : null;
    $maritalStatus = isset($patientInfo['marital_status']) ? strtoupper($conn->real_escape_string($patientInfo['marital_status'])) : null;
    
    // Standardize marital status
    if ($maritalStatus && !in_array($maritalStatus, ['SINGLE', 'MARRIED', 'DIVORCED', 'WIDOWED'])) {
        $maritalStatus = null;
    }

    $patientStmt->bind_param(
        "issiisss",
        $userId,
        $patientInfo['patient_number'],
        $registrationType,
        $insuranceProviderId,
        $insuranceNumber,
        $policyNumber,
        $employer,
        $maritalStatus
    );

    if (!$patientStmt->execute()) {
        throw new Exception("Failed to create patient: " . $patientStmt->error);
    }

    $patientId = $patientStmt->insert_id;
    $patientStmt->close();

    return $patientId;
}

function updatePatient($conn, $patientId, $userId, $patientInfo) {
    // Update user full name and phone if provided
    $updates = [];
    $types = "";
    $values = [];
    
    if (isset($patientInfo['full_name'])) {
        $updates[] = "full_name = ?";
        $types .= "s";
        $values[] = $patientInfo['full_name'];
    }
    
    if (isset($patientInfo['phone_number'])) {
        $updates[] = "phone_primary = ?";
        $types .= "s";
        $values[] = $patientInfo['phone_number'];
    }
    
    if (!empty($updates)) {
        $sql = "UPDATE users SET " . implode(", ", $updates) . " WHERE user_id = ?";
        $types .= "i";
        $values[] = $userId;
        
        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$values);
        $stmt->execute();
        $stmt->close();
    }

    // Update patient record
    $updates = [];
    $types = "";
    $values = [];

    if (isset($patientInfo['marital_status'])) {
        $maritalStatus = strtoupper($patientInfo['marital_status']);
        if (in_array($maritalStatus, ['SINGLE', 'MARRIED', 'DIVORCED', 'WIDOWED'])) {
            $updates[] = "marital_status = ?";
            $types .= "s";
            $values[] = $maritalStatus;
        }
    }

    if (isset($patientInfo['membership_number'])) {
        $updates[] = "insurance_number = ?";
        $types .= "s";
        $values[] = $patientInfo['membership_number'];
    }

    if (!empty($updates)) {
        $sql = "UPDATE patients SET " . implode(", ", $updates) . ", updated_at = NOW() WHERE patient_id = ?";
        $types .= "i";
        $values[] = $patientId;

        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$values);
        $stmt->execute();
        $stmt->close();
    }
}

function importVisit($conn, $patientId, $visitData, $counter = 0) {
    if (empty($visitData)) {
        return;
    }

    // Parse service date
    $serviceDate = isset($visitData['service_date']) ? 
                   parseDate($visitData['service_date']) : 
                   (isset($visitData['registration_date']) ? parseDate($visitData['registration_date']) : date('Y-m-d'));

    // Determine visit type
    $visitType = 'CONSULTATION';
    $visitSource = 'WALK_IN';
    
    // Create UNIQUE visit number using microseconds and counter
    $microtime = microtime(true);
    $microseconds = sprintf("%06d", ($microtime - floor($microtime)) * 1000000);
    $visitNumber = 'VST-' . date('Ymd-His', $microtime) . '-' . $microseconds . '-' . str_pad($patientId, 6, '0', STR_PAD_LEFT) . '-' . $counter;

    // Insert patient visit
    $visitStmt = $conn->prepare("
        INSERT INTO patient_visits (
            patient_id, visit_number, visit_type, visit_source,
            registration_date, status, created_at
        ) VALUES (?, ?, ?, ?, ?, 'COMPLETED', NOW())
    ");

    $visitStmt->bind_param(
        "issss",
        $patientId,
        $visitNumber,
        $visitType,
        $visitSource,
        $serviceDate
    );

    if ($visitStmt->execute()) {
        $visitId = $visitStmt->insert_id;
        $visitStmt->close();
        
        // Create consultation record with clinical data
        if (hasConsultationData($visitData)) {
            createConsultationRecord($conn, $visitId, $patientId, $visitData, $serviceDate, $counter);
        }
    } else {
        $visitStmt->close();
        throw new Exception("Failed to create visit: " . $visitStmt->error);
    }
}

function hasConsultationData($visitData) {
    // Check if visit has any clinical/consultation data
    $clinicalFields = [
        'consultation_description', 'diagnosis', 'symptoms', 
        'findings', 'management', 'clinical_hpi', 'clinical_notes',
        'doctor_name'
    ];
    
    foreach ($clinicalFields as $field) {
        if (isset($visitData[$field]) && !empty($visitData[$field])) {
            return true;
        }
    }
    
    return false;
}

function createConsultationRecord($conn, $visitId, $patientId, $visitData, $serviceDate, $counter = 0) {
    // Find or get default doctor
    $doctorId = null;
    if (isset($visitData['doctor_name']) && !empty($visitData['doctor_name'])) {
        $doctorName = $conn->real_escape_string($visitData['doctor_name']);
        
        // Try to find doctor by name
        $doctorStmt = $conn->prepare("
            SELECT u.user_id 
            FROM users u
            INNER JOIN user_roles ur ON u.role_id = ur.role_id
            WHERE u.full_name LIKE ? 
            AND ur.role_code IN ('ENT_DOCTOR', 'ENT_CONSULTANT', 'GENERAL_DOCTOR')
            LIMIT 1
        ");
        $searchName = "%$doctorName%";
        $doctorStmt->bind_param("s", $searchName);
        $doctorStmt->execute();
        $doctorResult = $doctorStmt->get_result()->fetch_assoc();
        if ($doctorResult) {
            $doctorId = $doctorResult['user_id'];
        }
        $doctorStmt->close();
    }
    
    // If no doctor found, use the first available doctor or leave null
    if (!$doctorId) {
        $defaultDoctorStmt = $conn->prepare("
            SELECT u.user_id 
            FROM users u
            INNER JOIN user_roles ur ON u.role_id = ur.role_id
            WHERE ur.role_code IN ('ENT_DOCTOR', 'ENT_CONSULTANT')
            LIMIT 1
        ");
        $defaultDoctorStmt->execute();
        $defaultDoctorResult = $defaultDoctorStmt->get_result()->fetch_assoc();
        if ($defaultDoctorResult) {
            $doctorId = $defaultDoctorResult['user_id'];
        }
        $defaultDoctorStmt->close();
    }

    // Generate UNIQUE consultation number using microseconds and counter
    $microtime = microtime(true);
    $microseconds = sprintf("%06d", ($microtime - floor($microtime)) * 1000000);
    $consultationNumber = 'CONS-' . date('Ymd-His', $microtime) . '-' . $microseconds . '-' . str_pad($patientId, 6, '0', STR_PAD_LEFT) . '-' . $counter;

    // Prepare consultation data - Map to correct schema columns
    $chiefComplaint = isset($visitData['consultation_description']) ? 
                     $visitData['consultation_description'] : 
                     (isset($visitData['symptoms']) ? $visitData['symptoms'] : null);
    
    // Map to diagnosis_primary (schema column)
    $diagnosisPrimary = isset($visitData['diagnosis']) ? $visitData['diagnosis'] : null;
    
    // Build history_present_illness (schema column)
    $historyPresentIllness = '';
    if (isset($visitData['clinical_hpi']) && !empty($visitData['clinical_hpi'])) {
        $historyPresentIllness = $visitData['clinical_hpi'];
    }
    
    // Build general_examination (schema column) from findings and symptoms
    $generalExamination = '';
    if (isset($visitData['findings']) && !empty($visitData['findings'])) {
        $generalExamination .= "Clinical Findings:\n" . $visitData['findings'];
    }
    if (isset($visitData['symptoms']) && !empty($visitData['symptoms'])) {
        if ($generalExamination) $generalExamination .= "\n\n";
        $generalExamination .= "Symptoms:\n" . $visitData['symptoms'];
    }
    $generalExamination = trim($generalExamination);
    
    // Map to treatment_plan (schema column)
    $treatmentPlan = isset($visitData['management']) ? $visitData['management'] : null;
    
    // Build doctor_notes (schema column) from various fields
    $doctorNotes = '';
    if (isset($visitData['clinical_notes']) && !empty($visitData['clinical_notes'])) {
        $doctorNotes .= "Clinical Notes:\n" . $visitData['clinical_notes'] . "\n\n";
    }
    if (isset($visitData['investigation_remarks']) && !empty($visitData['investigation_remarks'])) {
        $doctorNotes .= "Investigation Remarks:\n" . $visitData['investigation_remarks'];
    }
    $doctorNotes = trim($doctorNotes);
    
    // Determine consultation type (schema: INITIAL, FOLLOW_UP, SECOND_OPINION, EMERGENCY)
    $consultationType = 'INITIAL';
    if (isset($visitData['consultation_description'])) {
        $desc = strtoupper($visitData['consultation_description']);
        if (strpos($desc, 'FOLLOW') !== false) {
            $consultationType = 'FOLLOW_UP';
        } elseif (strpos($desc, 'EMERGENCY') !== false || strpos($desc, 'URGENT') !== false) {
            $consultationType = 'EMERGENCY';
        } elseif (strpos($desc, 'SECOND') !== false || strpos($desc, 'OPINION') !== false) {
            $consultationType = 'SECOND_OPINION';
        }
    }

    // Convert service date to datetime for started_at and completed_at
    $startedAt = $serviceDate . ' 00:00:00';
    $completedAt = $serviceDate . ' 23:59:59';

    // Insert consultation record - CORRECTED TO MATCH SCHEMA
    $consultStmt = $conn->prepare("
        INSERT INTO consultations (
            visit_id, patient_id, doctor_id, consultation_number,
            consultation_type, chief_complaint, history_present_illness,
            diagnosis_primary, general_examination, treatment_plan,
            doctor_notes, status, started_at, completed_at, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'COMPLETED', ?, ?, NOW())
    ");

    $consultStmt->bind_param(
        "iiissssssssss",
        $visitId,
        $patientId,
        $doctorId,
        $consultationNumber,
        $consultationType,
        $chiefComplaint,
        $historyPresentIllness,
        $diagnosisPrimary,
        $generalExamination,
        $treatmentPlan,
        $doctorNotes,
        $startedAt,
        $completedAt
    );

    if (!$consultStmt->execute()) {
        throw new Exception("Failed to create consultation: " . $consultStmt->error);
    }

    $consultationId = $consultStmt->insert_id;
    $consultStmt->close();

    return $consultationId;
}

function parseAge($ageString) {
    if (empty($ageString)) {
        return null;
    }
    
    // Extract numeric value from strings like "47 Yr(s)" or "12 Yr(s)"
    if (preg_match('/(\d+)/', $ageString, $matches)) {
        return intval($matches[1]);
    }
    
    return null;
}

function parseDate($dateString) {
    if (empty($dateString)) {
        return date('Y-m-d');
    }

    // Try various date formats
    $formats = ['d/m/Y', 'Y-m-d', 'm/d/Y', 'd-m-Y', 'Y/m/d'];
    
    foreach ($formats as $format) {
        $date = DateTime::createFromFormat($format, $dateString);
        if ($date) {
            return $date->format('Y-m-d');
        }
    }

    // Try strtotime as fallback
    $timestamp = strtotime($dateString);
    if ($timestamp !== false) {
        return date('Y-m-d', $timestamp);
    }

    return date('Y-m-d');
}
?>