<?php
header('Content-Type: application/json');
define('SECURE_ACCESS', true);
require_once __DIR__ . '/../../includes/config.php';
require_once __DIR__ . '/../../includes/db.php';
require_once __DIR__ . '/../../includes/auth.php';

$response = ['success' => false, 'message' => ''];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!verifyCSRFToken($_POST['csrf_token'] ?? '')) {
        $response['message'] = "Security check failed (CSRF). Please try again.";
    } else {
        $token = isset($_POST['token']) ? trim($_POST['token']) : '';
        $ref = isset($_POST['ref']) ? trim($_POST['ref']) : '';
        $password = $_POST['password'] ?? '';

        // Password strength validation (#12)
        if (strlen($password) < 8) {
            $response['message'] = "Password must be at least 8 characters long.";
            echo json_encode($response);
            exit();
        }
        if (!preg_match('/[A-Z]/', $password) || !preg_match('/[a-z]/', $password) || !preg_match('/[0-9]/', $password)) {
            $response['message'] = "Password must contain at least one uppercase letter, one lowercase letter, and one number.";
            echo json_encode($response);
            exit();
        }
        
        $configs = [];
        try {
            $stmt_c = $pdo->query("SELECT key, value FROM system_settings");
            $configs = $stmt_c->fetchAll(PDO::FETCH_KEY_PAIR) ?: [];
        } catch (PDOException $e) { }

        $registration_mode = $configs['registration_mode'] ?? 'invite_only';
        $invitation = null;
        $isValid = false;

        if ($registration_mode === 'open') {
            $isValid = true;
            if (!empty($token)) {
                try {
                    $stmt = $pdo->prepare("SELECT * FROM user_invitations WHERE token = ? AND status = 'pending'");
                    $stmt->execute([$token]);
                    $invitation = $stmt->fetch();
                } catch (PDOException $e) { }
            }
        } else {
            if (!empty($token)) {
                try {
                    $stmt = $pdo->prepare("SELECT * FROM user_invitations WHERE token = ? AND status = 'pending'");
                    $stmt->execute([$token]);
                    $invitation = $stmt->fetch();
                    if ($invitation) {
                        // Check invitation expiry
                        if (!empty($invitation['expires_at']) && strtotime($invitation['expires_at']) < time()) {
                            $response['message'] = "This invitation link has expired. Please request a new one.";
                        } else {
                            $isValid = true;
                        }
                    } else {
                        $response['message'] = "This user registration invitation link is invalid or has already been used.";
                    }
                } catch (PDOException $e) { }
            } else {
                $response['message'] = "Direct registrations are disabled. You must have a valid registration invitation link to onboard.";
            }
        }

        if ($isValid) {
            $email = $invitation ? $invitation['email'] : trim($_POST['email'] ?? '');
            $phone = trim($_POST['phone'] ?? '');
            
            if (empty($password) || empty($email) || empty($phone)) {
                $response['message'] = "Please fill in all required fields marked with *.";
            } else {
                try {
                    // Auto-generate unique username from email prefix
                    $base_username = strstr($email, '@', true);
                    if (!$base_username) {
                        $base_username = 'user';
                    }
                    $username = $base_username;
                    try {
                        $stmt_u = $pdo->prepare("SELECT username FROM users WHERE username = ? OR username LIKE ?");
                        $stmt_u->execute([$base_username, $base_username . '%']);
                        $existing_usernames = $stmt_u->fetchAll(PDO::FETCH_COLUMN) ?: [];
                    } catch (PDOException $e) {
                        $existing_usernames = [];
                    }

                    if (in_array($base_username, $existing_usernames)) {
                        $suffix = 1;
                        while (in_array($base_username . $suffix, $existing_usernames)) {
                            $suffix++;
                        }
                        $username = $base_username . $suffix;
                    }

                    // Check if email already exists
                    $check = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
                    $check->execute([$email]);
                    
                    // Check if phone already exists
                    $check_ph = $pdo->prepare("SELECT COUNT(*) FROM users WHERE phone = ?");
                    $check_ph->execute([$phone]);
                    
                    if ($check->fetchColumn() > 0) {
                        $response['message'] = "An account with this email address already exists. Please login instead.";
                    } else if ($check_ph->fetchColumn() > 0) {
                        $response['message'] = "An account with this phone number already exists. Please login instead.";
                    } else {
                        $referrer_username = trim($_POST['referrer_username'] ?? '');
                        $referrer_id = null;
                        $parent_id = null;

                        if (empty($referrer_username)) {
                            $response['message'] = "Your Team Leader Employee Code is required to register.";
                        } else {
                            $stmt_ref = $pdo->prepare("SELECT id, designation_id FROM users WHERE username = ? OR employee_code = ?");
                            $stmt_ref->execute([$referrer_username, $referrer_username]);
                            $referrer = $stmt_ref->fetch();
                            if (!$referrer) {
                                $response['message'] = "The Team Leader Employee Code or username you entered does not exist.";
                            } else {
                                $referrer_id = $referrer['id'];

                                // Fetch matrix config of the sponsor to calculate parent with spillover
                                $m_width = 4;
                                $m_depth = 4;
                                if ($referrer['designation_id']) {
                                    $stmt_m = $pdo->prepare("SELECT matrix_width, matrix_depth FROM designations WHERE id = ?");
                                    $stmt_m->execute([$referrer['designation_id']]);
                                    $des = $stmt_m->fetch();
                                    if ($des) {
                                        $m_width = (int)$des['matrix_width'];
                                        $m_depth = (int)$des['matrix_depth'];
                                    }
                                }

                                // Run BFS placement algorithm to find parent_id
                                $parent_id = findMatrixPlacement($referrer_id, $m_width, $m_depth);
                                
                                // Fetch default designation rank
                                $stmt_def_desig = $pdo->query("SELECT id FROM designations WHERE is_default = TRUE LIMIT 1");
                                $default_designation_id = $stmt_def_desig->fetchColumn() ?: null;

                                $settings = getSystemSettings();
                                $final_emp_code = '';

                                // Determine custom or auto-generated employee code
                                $employee_code_input = trim($_POST['employee_code'] ?? '');
                                if (!empty($employee_code_input)) {
                                    if (strlen($employee_code_input) < 5 || strlen($employee_code_input) > 30) {
                                        $response['message'] = "Employee code must be between 5 and 30 characters.";
                                    } else {
                                        $check_code = $pdo->prepare("SELECT COUNT(*) FROM users WHERE employee_code = ?");
                                        $check_code->execute([$employee_code_input]);
                                        if ($check_code->fetchColumn() > 0) {
                                            $response['message'] = "The employee code you entered is already in use by another user.";
                                        } else {
                                            $final_emp_code = $employee_code_input;
                                        }
                                    }
                                } else {
                                    $prefix = $settings['emp_code_prefix'] ?? 'REPL';
                                    $length = (int)($settings['emp_code_length'] ?? 15);
                                    $default_type = $settings['emp_code_default_type'] ?? 'generated';
                                    $custom_val = $settings['emp_code_custom_value'] ?? 'EMP-DEFAULT';

                                    if ($default_type === 'generated') {
                                        $unique = false;
                                        $attempts = 0;
                                        while (!$unique && $attempts < 15) {
                                            $temp_code = generateEmployeeCode($prefix, $length);
                                            $check_code = $pdo->prepare("SELECT COUNT(*) FROM users WHERE employee_code = ?");
                                            $check_code->execute([$temp_code]);
                                            if ($check_code->fetchColumn() == 0) {
                                                $final_emp_code = $temp_code;
                                                $unique = true;
                                            }
                                            $attempts++;
                                        }
                                        if (!$unique) {
                                            $response['message'] = "Failed to generate a unique employee code. Please try again or contact support.";
                                        }
                                    } else {
                                        $temp_code = $custom_val;
                                        $check_code = $pdo->prepare("SELECT COUNT(*) FROM users WHERE employee_code = ?");
                                        $check_code->execute([$temp_code]);
                                        
                                        if ($check_code->fetchColumn() == 0) {
                                            $final_emp_code = $temp_code;
                                        } else {
                                            $unique = false;
                                            $suffix = 1;
                                            while (!$unique && $suffix < 100) {
                                                $s_code = $temp_code . '-' . $suffix;
                                                $check_code = $pdo->prepare("SELECT COUNT(*) FROM users WHERE employee_code = ?");
                                                $check_code->execute([$s_code]);
                                                if ($check_code->fetchColumn() == 0) {
                                                    $final_emp_code = $s_code;
                                                    $unique = true;
                                                }
                                                $suffix++;
                                            }
                                        }
                                    }
                                }

                                if (empty($response['message'])) {
                                    $pdo->beginTransaction();

                                    $hashedPass = password_hash($password, PASSWORD_DEFAULT);
                                    
                                    // Insert User Account
                                    $ins_user = $pdo->prepare("
                                        INSERT INTO users (username, email, phone, password, role, status, employee_code, designation_id, referrer_id, parent_id) 
                                        VALUES (?, ?, ?, ?, 'user', 'active', ?, ?, ?, ?)
                                    ");
                                    $ins_user->execute([$username, $email, $phone, $hashedPass, $final_emp_code, $default_designation_id, $referrer_id, $parent_id]);
                                    $new_user_id = $pdo->lastInsertId();

                                    // Award Signup and Referral Bonuses INSIDE the transaction
                                    require_once __DIR__ . '/../../includes/bonus_helper.php';
                                    awardSignupAndReferralBonuses($new_user_id, $referrer_id);

                                    if ($invitation) {
                                        $upd_invite = $pdo->prepare("UPDATE user_invitations SET status = 'accepted' WHERE id = ?");
                                        $upd_invite->execute([$invitation['id']]);
                                    }

                                    $pdo->commit();

                                    // Log in user
                                    $_SESSION['user_id'] = $new_user_id;
                                    $_SESSION['username'] = $username;
                                    $_SESSION['email'] = $email;
                                    $_SESSION['role'] = 'user';
                                    $_SESSION['status'] = 'active';
                                    $_SESSION['flash_success'] = "Registration complete! Welcome, employee $username! Your Employee Code is $final_emp_code.";

                                    $response['success'] = true;
                                    $response['redirect'] = 'dashboard.php';
                                }
                            }
                        }
                    }
                } catch (PDOException $e) {
                    if ($pdo->inTransaction()) {
                        $pdo->rollBack();
                    }
                    $response['message'] = "An unexpected error occurred. Please try again later.";
                    error_log("Registration error: " . $e->getMessage());
                }
            }
        }
    }
} else {
    $response['message'] = "Invalid request method.";
}

echo json_encode($response);
