<?php
namespace App\Controllers;

require_once BASE_PATH . '/app/helpers/permissions.php';

require_once BASE_PATH . '/app/helpers/conference_scope.php';

use App\Core\Database;

class AdminUserController
{
    private function startSession(): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    protected function db()
    {
        return Database::getInstance();
    }

    private function role(): string
    {
        return (string)($_SESSION['role'] ?? $_SESSION['user_role'] ?? '');
    }

    private function requireAdmin(): void
    {
        $this->startSession();

  error_log(
        'ADMIN USERS ROLE=' .
        (
            $_SESSION['role']
            ?? $_SESSION['user_role']
            ?? 'NULL'
        )
    );

        if (empty($_SESSION['user_id'])) {
            header("Location: /easychair/login");
            exit;
        }

if (!in_array(strtolower($this->role()), [

    'superadmin',
'superadmin',
    'super admin',
    'org_admin',
    'org admin',
    'admin',
    'organizer',
    'conference_chair',
    'conference chair',
    'track_chair',
    'track chair'

], true)) {        
    http_response_code(403);
            exit("Access denied.");
        }
    }

    private function orgId(): int
    {
        return (int)($_SESSION['org_id'] ?? 0);
    }

    private function conferenceId(): int
    {
        return (int)($_SESSION['conference_id'] ?? $_SESSION['current_conference_id'] ?? 0);
    }

    private function canManageRole(string $targetRole): bool
    {
        $role = $this->role();

        if ($role === 'superadmin') {
            return true;
        }

        if ($targetRole === 'superadmin') {
            return false;
        }

        if ($role === 'org_admin') {
            return in_array($targetRole, [
                'org_admin',
                'admin',
                'organizer',
                'conference_chair',
                'track_chair',
                'reviewer',
                'author'
            ], true);
        }

        return in_array($targetRole, [
            'reviewer',
            'author'
        ], true);
    }

    
    /*
    |--------------------------------------------------------------------------
    | Enterprise Helpers
    |--------------------------------------------------------------------------
    */

    private function requestConferenceId(): int
    {
        if (ec_is_superadmin()) {

            return (int)(
                $_GET['conference_id']
                ??
                $_POST['conference_id']
                ??
                $_SESSION['conference_id']
                ??
                $_SESSION['current_conference_id']
                ??
                0
            );

        }

        return $this->conferenceId();
    }

    private function requestSearch(): string
    {
        return trim(
            (string)(
                $_GET['q']
                ??
                ''
            )
        );
    }

    private function requestRoleFilter(): int
    {
        return (int)(
            $_GET['role_filter']
            ??
            0
        );
    }

    private function requestStatusFilter(): string
    {
        return trim(
            (string)(
                $_GET['status']
                ??
                ''
            )
        );
    }

    private function requestPage(): int
    {
        return max(
            1,
            (int)(
                $_GET['page']
                ??
                1
            )
        );
    }

    private function requestPerPage(): int
    {
        $n=(int)(
            $_GET['per_page']
            ??
            25
        );

        if(!in_array($n,[10,25,50,100],true)){
            $n=25;
        }

        return $n;
    }


public function index()
    {
  
$this->requireAdmin();

        $db = $this->db();
        $role = $this->role();
        $orgId = $this->orgId();
        $conferenceId = $this->requestConferenceId();

        $q = $this->requestSearch();

        $roleFilter = $this->requestRoleFilter();

        $statusFilter = $this->requestStatusFilter();

        $page = $this->requestPage();

        $perPage = $this->requestPerPage();

        $offset = ($page-1)*$perPage;

        $params = [];
        $where = " WHERE u.is_active IN (0,1) ";

        if ($role === 'superadmin') {
            // all users

            if ($conferenceId > 0) {

                $where .= "

AND EXISTS
(
    SELECT 1
    FROM user_conferences ucx
    WHERE
        ucx.user_id = u.id
    AND
        ucx.conference_id = ?
)

";

                array_unshift($params,$conferenceId);

            }

        } elseif ($role === 'org_admin') {
            $where .= " AND u.org_id = ? ";
            $params[] = $orgId;
        } else {
            if ($conferenceId <= 0) {
                header("Location: /easychair/select-conference");
                exit;
            }

            $where .= "
                AND u.org_id = ?
                AND EXISTS (
                    SELECT 1
                    FROM user_conferences ucx
                    WHERE ucx.user_id = u.id
                      AND ucx.conference_id = ?
                )
            ";
            $params[] = $orgId;
            $params[] = $conferenceId;
        }
        
        $searchSql="";

if($q!==""){

$searchSql.="

AND
(
u.first_name LIKE ?
OR
u.last_name LIKE ?
OR
u.email LIKE ?
OR
u.mobile LIKE ?
OR
u.job_title LIKE ?
)

";

for($i=0;$i<5;$i++){

$params[]="%".$q."%";

}

}

if($roleFilter>0){

$where.=" AND u.role_id=? ";

$params[]=$roleFilter;

}

if($statusFilter!==""){

$where.=" AND u.is_active=? ";

$params[]=
$statusFilter=="active"
?1
:0;

}

        $stmt = $db->prepare("
            SELECT
                u.id,
                u.org_id,
                CONCAT(
                    COALESCE(u.first_name,''),
                    ' ',
                    COALESCE(u.last_name,'')
                ) AS display_name,

                u.first_name,
                u.last_name,
                u.email,
                u.email AS username,
                u.mobile,
                u.job_title,
                u.created_at,
                u.is_active,
                u.role_id,
                r.code AS global_role,
                r.name AS global_role_name,
                GROUP_CONCAT(DISTINCT CONCAT(c.short_name, ':', cr.code) ORDER BY c.id SEPARATOR ', ') AS conference_roles
            FROM users u
            LEFT JOIN roles r ON r.id = u.role_id
            LEFT JOIN user_conferences uc ON uc.user_id = u.id
            LEFT JOIN conferences c ON c.id = uc.conference_id
            LEFT JOIN roles cr ON cr.id = uc.role_id
            {$where}
            {$searchSql}
            GROUP BY
                u.id, u.org_id, u.first_name, u.last_name, u.email, u.mobile,
                u.job_title, u.is_active, u.role_id, r.code, r.name
            ORDER BY u.org_id ASC, u.id DESC
        ");

       $totalStmt=$db->prepare("

SELECT COUNT(DISTINCT u.id)

FROM users u

LEFT JOIN user_conferences uc
ON uc.user_id=u.id

{$where}

{$searchSql}

");

$totalStmt->execute($params);

$totalRows=
(int)$totalStmt->fetchColumn();

$totalPages=max(
1,
(int)ceil(
$totalRows/$perPage
)
);

$sql=$stmt->queryString."

 LIMIT ".$perPage."

 OFFSET ".$offset;

$stmt=$db->prepare($sql);

$stmt->execute($params);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $roles = $db->query("
            SELECT id, name, code
            FROM roles
            ORDER BY id
        ")->fetchAll(\PDO::FETCH_ASSOC);

        $conferences = [];

        if ($role === 'superadmin') {
            $conferences = $db->query("
                SELECT id, org_id, short_name, title_ar, title_en
                FROM conferences
                ORDER BY org_id, id
            ")->fetchAll(\PDO::FETCH_ASSOC);
        } elseif ($role === 'org_admin') {
            $stmt = $db->prepare("
                SELECT id, org_id, short_name, title_ar, title_en
                FROM conferences
                WHERE org_id = ?
                ORDER BY id
            ");
            $stmt->execute([$orgId]);
            $conferences = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        } else {
            $stmt = $db->prepare("
                SELECT id, org_id, short_name, title_ar, title_en
                FROM conferences
                WHERE id = ?
                  AND org_id = ?
                ORDER BY id
            ");
            $stmt->execute([$conferenceId, $orgId]);
            $conferences = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        }

        ob_start();
        $pageTitle="Users";

$currentPage=$page;

$pages=$totalPages;

$totalUsers=$totalRows;

$search=$q;

$roleFilterId=$roleFilter;

$statusFilterValue=$statusFilter;

$selectedConference=$conferenceId;
        require BASE_PATH . '/app/views/admin/users/index.php';
        $content = ob_get_clean();

        require BASE_PATH . '/app/views/layouts/admin_layout.php';
    }

    public function store()
    {
$this->requireAdmin();

        $db = $this->db();

        $first = trim($_POST['first_name'] ?? '');
        $last = trim($_POST['last_name'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $password = (string)($_POST['password'] ?? '');
        $roleId = (int)($_POST['role_id'] ?? 5);
        $conferenceId = (int)($_POST['conference_id'] ?? $this->conferenceId());

        if (!$first || !$last || !$email || !$password || !$roleId) {
            exit("Missing required fields.");
        }

        $stmt = $db->prepare("SELECT code FROM roles WHERE id = ? LIMIT 1");
        $stmt->execute([$roleId]);
        $targetRole = (string)$stmt->fetchColumn();

        if (!$targetRole || !$this->canManageRole($targetRole)) {
            http_response_code(403);
            exit("You cannot assign this role.");
        }

        $orgId = $this->orgId();

        if (ec_is_superadmin()) {
            if ($conferenceId > 0) {
                $stmt = $db->prepare("SELECT org_id FROM conferences WHERE id = ? LIMIT 1");
                $stmt->execute([$conferenceId]);
                $orgId = (int)$stmt->fetchColumn();
            } else {
                $orgId = (int)($_POST['org_id'] ?? 0);
            }
        }

        if ($orgId <= 0) {
            exit("Organization context missing.");
        }

        $stmt = $db->prepare("
            INSERT INTO users
            (org_id, role_id, first_name, last_name, email, password_hash, mobile, job_title, is_active, created_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, NOW())
        ");

        $stmt->execute([
            $orgId,
            $roleId,
            $first,
            $last,
            $email,
            password_hash($password, PASSWORD_BCRYPT),
            trim($_POST['mobile'] ?? ''),
            trim($_POST['job_title'] ?? '')
        ]);

        $userId = (int)$db->lastInsertId();

        if ($conferenceId > 0) {
            $stmt = $db->prepare("
                INSERT INTO user_conferences (user_id, conference_id, role_id)
                VALUES (?, ?, ?)
            ");
            $stmt->execute([$userId, $conferenceId, $roleId]);


if((int)$roleId===4){

try{

$db->prepare("

INSERT IGNORE INTO conference_user_roles
(
conference_id,
user_id,
org_id,
role_code
)

SELECT
?,
?,
c.org_id,
'reviewer'

FROM conferences c
WHERE c.id=?

")->execute([
$conferenceId,
$userId,
$conferenceId
]);

}catch(\Throwable $e){}

try{

$db->prepare("

INSERT IGNORE INTO conference_reviewers
(
conference_id,
user_id,
created_at
)

VALUES
(
?,
?,
NOW()
)

")->execute([
$conferenceId,
$userId
]);

}catch(\Throwable $e){}

}


        }

        header("Location: /easychair/admin/users");
        exit;
    }

    public function update()
{
    $this->requireAdmin();

    $db = $this->db();

    $id = (int)($_POST['id'] ?? 0);
    $roleId = (int)($_POST['role_id'] ?? 0);
    $conferenceId = (int)($_POST['conference_id'] ?? $this->conferenceId());

    if (!$id || !$roleId) {
        exit("Missing data.");
    }

    $stmt = $db->prepare("
        SELECT code 
        FROM roles 
        WHERE id = ? 
        LIMIT 1
    ");
    $stmt->execute([$roleId]);

    $targetRole = (string)$stmt->fetchColumn();

    if (!$targetRole || !$this->canManageRole($targetRole)) {
        http_response_code(403);
        exit("You cannot assign this role.");
    }

    if (!ec_is_superadmin()) {

        $stmt = $db->prepare("
            SELECT id
            FROM users
            WHERE id = ?
              AND org_id = ?
            LIMIT 1
        ");

        $stmt->execute([
            $id,
            $this->orgId()
        ]);

        if (!$stmt->fetchColumn()) {
            http_response_code(403);
            exit("User is outside your organization.");
        }
    }

    /*
    |--------------------------------------------------------------------------
    | Update User Profile
    |--------------------------------------------------------------------------
    */

    $fullName = trim((string)($_POST['name'] ?? ''));

    $parts = preg_split('/\s+/', $fullName, 2);

    $firstName = trim($parts[0] ?? '');

    $lastName = trim($parts[1] ?? '');

    $email = trim((string)($_POST['email'] ?? ''));

    $mobile = trim((string)($_POST['mobile'] ?? ''));

    $jobTitle = trim((string)($_POST['job_title'] ?? ''));

    $status = strtolower(trim((string)($_POST['status'] ?? 'active')));

    $isActive = ($status === 'active') ? 1 : 0;

    $stmt = $db->prepare("
        UPDATE users
        SET
            first_name=?,
            last_name=?,
            email=?,
            mobile=?,
            job_title=?,
            is_active=?,
            role_id=?
        WHERE id=?
    ");

    $stmt->execute([
        $firstName,
        $lastName,
        $email,
        $mobile,
        $jobTitle,
        $isActive,
        $roleId,
        $id
    ]);

    /*
    |--------------------------------------------------------------------------
    | Conference Role Mapping
    |--------------------------------------------------------------------------
    */
    if ($conferenceId > 0) {

        if (!ec_is_superadmin()) {

            $stmt = $db->prepare("
                SELECT id
                FROM conferences
                WHERE id = ?
                  AND org_id = ?
                LIMIT 1
            ");

            $stmt->execute([
                $conferenceId,
                $this->orgId()
            ]);

            if (!$stmt->fetchColumn()) {
                http_response_code(403);
                exit("Conference is outside your organization.");
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Check Existing Mapping
        |--------------------------------------------------------------------------
        */
        $stmt = $db->prepare("
            SELECT id
            FROM user_conferences
            WHERE user_id = ?
              AND conference_id = ?
            LIMIT 1
        ");

        $stmt->execute([
            $id,
            $conferenceId
        ]);

        $exists = $stmt->fetchColumn();

        /*
        |--------------------------------------------------------------------------
        | Insert New Mapping
        |--------------------------------------------------------------------------
        */
        if (!$exists) {

            $stmt = $db->prepare("
                INSERT INTO user_conferences
                (
                    user_id,
                    conference_id,
                    role_id
                )
                VALUES (?, ?, ?)
            ");

            $stmt->execute([
                $id,
                $conferenceId,
                $roleId
            ]);

        } else {

            /*
            |--------------------------------------------------------------------------
            | Update Existing Mapping
            |--------------------------------------------------------------------------
            */
            $stmt = $db->prepare("
                UPDATE user_conferences
                SET role_id = ?
                WHERE user_id = ?
                  AND conference_id = ?
            ");

            $stmt->execute([
                $roleId,
                $id,
                $conferenceId
            ]);
        }
    }

    header("Location: /easychair/admin/users");
    exit;
}

    public function removeRole()
    {
        $this->requireAdmin();

        $db = $this->db();

        $userId =
            (int)($_GET['user_id'] ?? 0);

        $conferenceId =
            (int)($_GET['conference_id'] ?? 0);

        $roleId =
            (int)($_GET['role_id'] ?? 0);

        if (
            !$userId
            || !$conferenceId
            || !$roleId
        ) {

            exit('Missing data.');
        }

        $stmt = $db->prepare("

            DELETE FROM user_conferences

            WHERE user_id = ?
            AND conference_id = ?
            AND role_id = ?

            LIMIT 1

        ");

        $stmt->execute([

            $userId,
            $conferenceId,
            $roleId

        ]);

        header(
            'Location: /easychair/admin/users'
        );

        exit;
    }


    /* PACK188 FIXED — reviewer auto-sync inside class */
    private function syncConferenceReviewer(\PDO $db, int $userId, int $conferenceId): void
    {
        if ($userId <= 0 || $conferenceId <= 0) {
            return;
        }

        try {
            $q = $db->prepare("
                SELECT COUNT(*)
                FROM conference_reviewers
                WHERE conference_id = ?
                AND user_id = ?
            ");
            $q->execute([$conferenceId, $userId]);

            if (!(int)$q->fetchColumn()) {
                $db->prepare("
                    INSERT INTO conference_reviewers
                    (conference_id, user_id, created_at)
                    VALUES (?, ?, NOW())
                ")->execute([$conferenceId, $userId]);

                error_log("PACK188 reviewer synced user={$userId} conf={$conferenceId}");
            }
        } catch (\Throwable $e) {
            error_log("PACK188 sync error=".$e->getMessage());
        }
    }



    /*
    |--------------------------------------------------------------------------
    | PACK1301 - Reset User Password
    |--------------------------------------------------------------------------
    */
    public function resetPassword()
    {
        $this->requireAdmin();

        $db = $this->db();

        $userId = (int)($_POST['id'] ?? $_POST['user_id'] ?? 0);
        $newPassword = trim((string)($_POST['password'] ?? $_POST['new_password'] ?? ''));

        if ($userId <= 0 || strlen($newPassword) < 8) {
            exit("Password must be at least 8 characters.");
        }

        if (!ec_is_superadmin()) {
            $stmt = $db->prepare("
                SELECT id
                FROM users
                WHERE id = ?
                  AND org_id = ?
                LIMIT 1
            ");
            $stmt->execute([$userId, $this->orgId()]);

            if (!$stmt->fetchColumn()) {
                http_response_code(403);
                exit("User is outside your organization.");
            }
        }

        $stmt = $db->prepare("
            UPDATE users
            SET password_hash = ?,
                must_change_password = 1,
                updated_at = NOW()
            WHERE id = ?
            LIMIT 1
        ");

        $stmt->execute([
            password_hash($newPassword, PASSWORD_BCRYPT),
            $userId
        ]);

        header("Location: /easychair/admin/users");
        exit;
    }


    /*
    |--------------------------------------------------------------------------
    | PACK1301 - Delete User
    |--------------------------------------------------------------------------
    */
    public function delete()
    {
        $this->requireAdmin();

        $db = $this->db();

        $userId = (int)($_POST['id'] ?? $_POST['user_id'] ?? 0);
        $currentUserId = (int)($_SESSION['user_id'] ?? 0);

        if ($userId <= 0) {
            exit("Invalid user.");
        }

        if ($userId === $currentUserId) {
            exit("You cannot delete your own account.");
        }

        if (!ec_is_superadmin()) {
            $stmt = $db->prepare("
                SELECT id
                FROM users
                WHERE id = ?
                  AND org_id = ?
                LIMIT 1
            ");
            $stmt->execute([$userId, $this->orgId()]);

            if (!$stmt->fetchColumn()) {
                http_response_code(403);
                exit("User is outside your organization.");
            }
        }

        try {
            $db->beginTransaction();

            foreach ([
                'conference_user_roles',
                'user_conferences',
                'conference_reviewers',
                'track_chair_assignments',
                'business_role_permissions'
            ] as $table) {
                try {
                    $db->prepare("DELETE FROM {$table} WHERE user_id = ?")
                       ->execute([$userId]);
                } catch (\Throwable $e) {
                    // table/column may not exist in all installs
                }
            }

            try {
                $db->prepare("DELETE FROM review_assignments WHERE reviewer_id = ?")
                   ->execute([$userId]);
            } catch (\Throwable $e) {
            }

            $db->prepare("DELETE FROM users WHERE id = ? LIMIT 1")
               ->execute([$userId]);

            $db->commit();

        } catch (\Throwable $e) {
            if ($db->inTransaction()) {
                $db->rollBack();
            }

            exit("Delete failed: " . $e->getMessage());
        }

        header("Location: /easychair/admin/users");
        exit;
    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Conference Membership
    |--------------------------------------------------------------------------
    */

    public function conferenceMembershipStore()
    {
        $this->requireAdmin();

        $db=$this->db();

        $conferenceId=(int)($_POST['conference_id']??0);
        $userId=(int)($_POST['user_id']??0);
        $roleId=(int)($_POST['role_id']??0);

        if(
            !$conferenceId||
            !$userId||
            !$roleId
        ){
            exit("Invalid request.");
        }

        $stmt=$db->prepare("
        SELECT COUNT(*)
        FROM user_conferences
        WHERE
        user_id=?
        AND conference_id=?
        ");

        $stmt->execute([
            $userId,
            $conferenceId
        ]);

        if(!$stmt->fetchColumn()){

            $stmt=$db->prepare("
            INSERT INTO
            user_conferences
            (
            user_id,
            conference_id,
            role_id
            )
            VALUES
            (?,?,?)
            ");

            $stmt->execute([
                $userId,
                $conferenceId,
                $roleId
            ]);

        }else{

            $stmt=$db->prepare("
            UPDATE
            user_conferences
            SET
            role_id=?
            WHERE
            user_id=?
            AND
            conference_id=?
            ");

            $stmt->execute([
                $roleId,
                $userId,
                $conferenceId
            ]);

        }

        try{

        $stmt=$db->prepare("
        SELECT COUNT(*)
        FROM conference_user_roles
        WHERE
        user_id=?
        AND
        conference_id=?
        ");

        $stmt->execute([
            $userId,
            $conferenceId
        ]);

        if(!$stmt->fetchColumn()){

            $stmt=$db->prepare("
            INSERT INTO
            conference_user_roles
            (
            conference_id,
            user_id,
            role_id
            )
            VALUES
            (?,?,?)
            ");

            $stmt->execute([
                $conferenceId,
                $userId,
                $roleId
            ]);

        }else{

            $stmt=$db->prepare("
            UPDATE
            conference_user_roles
            SET
            role_id=?
            WHERE
            conference_id=?
            AND
            user_id=?
            ");

            $stmt->execute([
                $roleId,
                $conferenceId,
                $userId
            ]);

        }

        }catch(\Throwable $e){
        }

        header(
        "Location: /easychair/admin/users?conference_id=".$conferenceId
        );

        exit;

    }


    /*
    |--------------------------------------------------------------------------
    | Remove Membership
    |--------------------------------------------------------------------------
    */

    public function conferenceMembershipDelete()
    {

        $this->requireAdmin();

        $db=$this->db();

        $conferenceId=(int)($_POST['conference_id']??0);

        $userId=(int)($_POST['user_id']??0);

        $db->prepare("
        DELETE
        FROM
        user_conferences
        WHERE
        user_id=?
        AND
        conference_id=?
        ")
        ->execute([
        $userId,
        $conferenceId
        ]);

        try{

        $db->prepare("
        DELETE
        FROM
        conference_user_roles
        WHERE
        user_id=?
        AND
        conference_id=?
        ")
        ->execute([
        $userId,
        $conferenceId
        ]);

        }catch(\Throwable $e){}

        header(
        "Location: /easychair/admin/users?conference_id=".$conferenceId
        );

        exit;

    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise AJAX User Search
    |--------------------------------------------------------------------------
    */

    public function searchUsers()
    {
        $this->requireAdmin();

        $db=$this->db();

        $conferenceId=(int)(
            $_GET['conference_id']
            ??
            0
        );

        $q=trim(
            (string)(
                $_GET['q']
                ??
                ''
            )
        );

        if(strlen($q)<2){

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

            echo json_encode([]);

            exit;

        }

        $sql="

SELECT

u.id,

u.first_name,

u.last_name,

u.email,

u.mobile,

u.job_title,

u.is_active

FROM users u

WHERE

(

u.first_name LIKE ?

OR

u.last_name LIKE ?

OR

u.email LIKE ?

OR

u.mobile LIKE ?

)

";

        $params=[
            "%$q%",
            "%$q%",
            "%$q%",
            "%$q%"
        ];

        if($conferenceId){

            $sql.="

AND NOT EXISTS
(
SELECT 1
FROM user_conferences uc
WHERE
uc.user_id=u.id
AND
uc.conference_id=?
)

";

            $params[]=$conferenceId;

        }

        $sql.="

ORDER BY

u.first_name,
u.last_name

LIMIT 20

";

        $stmt=$db->prepare($sql);

        $stmt->execute($params);

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

        echo json_encode(
            $stmt->fetchAll(\PDO::FETCH_ASSOC)
        );

        exit;

    }



    /*
    |--------------------------------------------------------------------------
    | Enterprise - Update Conference Role
    |--------------------------------------------------------------------------
    */
    public function updateConferenceRole()
    {
        $this->requireAdmin();

        $db = $this->db();

        $userId = (int)($_POST['user_id'] ?? 0);
        $conferenceId = (int)($_POST['conference_id'] ?? 0);
        $roleId = (int)($_POST['role_id'] ?? 0);

        if ($userId <= 0 || $conferenceId <= 0 || $roleId <= 0) {
            exit("Invalid request.");
        }

        $stmt = $db->prepare("
            UPDATE user_conferences
               SET role_id = ?
             WHERE user_id = ?
               AND conference_id = ?
        ");
        $stmt->execute([$roleId, $userId, $conferenceId]);

        try {
            $stmt = $db->prepare("
                UPDATE conference_user_roles
                   SET role_id = ?
                 WHERE user_id = ?
                   AND conference_id = ?
            ");
            $stmt->execute([$roleId, $userId, $conferenceId]);
        } catch (\Throwable $e) {
            // Ignore if table is not used in this installation
        }

        header(
            'Location: /easychair/admin/users?conference_id=' . $conferenceId
        );
        exit;
    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Email Lookup
    |--------------------------------------------------------------------------
    */

    public function lookupUserByEmail()
    {
        $this->requireAdmin();

        $db=$this->db();

        $email=trim(
            strtolower(
                (string)(
                    $_GET['email']
                    ??
                    ''
                )
            )
        );

        if($email==''){

            echo json_encode([]);

            exit;

        }

        $stmt=$db->prepare("

SELECT

id,
first_name,
last_name,
email,
mobile

FROM users

WHERE lower(email)=?

LIMIT 1

");

        $stmt->execute([
            $email
        ]);

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

        echo json_encode(
            $stmt->fetch(
                \PDO::FETCH_ASSOC
            )
        );

        exit;

    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Bulk Activate / Deactivate
    |--------------------------------------------------------------------------
    */
    public function bulkUpdateStatus()
    {
        $this->requireAdmin();

        $db = $this->db();

        $ids = $_POST['users'] ?? [];
        $status = strtolower(trim((string)($_POST['status'] ?? 'active')));

        if (!is_array($ids) || empty($ids)) {
            exit('No users selected.');
        }

        $active = ($status === 'active') ? 1 : 0;

        $placeholders = implode(',', array_fill(0, count($ids), '?'));

        $sql = "UPDATE users
                   SET is_active = ?
                 WHERE id IN ($placeholders)";

        $stmt = $db->prepare($sql);

        $params = array_merge([$active], array_map('intval', $ids));

        $stmt->execute($params);

        header("Location: /easychair/admin/users?bulk=success");
        exit;
    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Audit Helper
    |--------------------------------------------------------------------------
    */
    private function auditLog(
        string $action,
        int $targetUserId,
        array $extra = []
    ): void
    {
        $db = $this->db();

        try {

            $stmt = $db->prepare("
                INSERT INTO audit_logs
                (
                    user_id,
                    action,
                    target_user_id,
                    ip_address,
                    user_agent,
                    details,
                    created_at
                )
                VALUES
                (?, ?, ?, ?, ?, ?, NOW())
            ");

            $stmt->execute([
                $_SESSION['user_id'] ?? 0,
                $action,
                $targetUserId,
                $_SERVER['REMOTE_ADDR'] ?? '',
                $_SERVER['HTTP_USER_AGENT'] ?? '',
                json_encode($extra)
            ]);

        } catch (\Throwable $e) {
            // Ignore if audit_logs does not yet exist
        }
    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Bulk Conference Assignment
    |--------------------------------------------------------------------------
    */

    public function bulkAssignConference()
    {
        $this->requireAdmin();

        $db = $this->db();

        $users = $_POST['users'] ?? [];

        $conferenceId = (int)($_POST['conference_id'] ?? 0);

        $roleId = (int)($_POST['role_id'] ?? 0);

        if (
            empty($users)
            ||
            $conferenceId <= 0
            ||
            $roleId <= 0
        ) {

            header("Location: /easychair/admin/users?bulk=invalid");

            exit;

        }

        try {

            $db->beginTransaction();

            $checkMembership = $db->prepare("
                SELECT id
                FROM user_conferences
                WHERE
                    user_id = ?
                AND conference_id = ?
                LIMIT 1
            ");

            $insertMembership = $db->prepare("
                INSERT INTO user_conferences
                (
                    user_id,
                    conference_id,
                    role_id
                )
                VALUES
                (
                    ?,
                    ?,
                    ?
                )
            ");

            $updateMembership = $db->prepare("
                UPDATE user_conferences
                SET role_id = ?
                WHERE
                    user_id = ?
                AND conference_id = ?
            ");

            foreach ($users as $uid) {

                $uid = (int)$uid;

                if ($uid <= 0) {
                    continue;
                }

                $checkMembership->execute([
                    $uid,
                    $conferenceId
                ]);

                if ($checkMembership->fetch()) {

                    $updateMembership->execute([
                        $roleId,
                        $uid,
                        $conferenceId
                    ]);

                } else {

                    $insertMembership->execute([
                        $uid,
                        $conferenceId,
                        $roleId
                    ]);

                }

                try {

                    $db->prepare("
                        INSERT INTO conference_user_roles
                        (
                            user_id,
                            conference_id,
                            role_id
                        )
                        VALUES
                        (
                            ?,
                            ?,
                            ?
                        )
                        ON DUPLICATE KEY UPDATE
                        role_id = VALUES(role_id)
                    ")->execute([
                        $uid,
                        $conferenceId,
                        $roleId
                    ]);

                } catch (\Throwable $e) {
                }

                try {

                    $r = $db->prepare("
                        SELECT code
                        FROM roles
                        WHERE id = ?
                        LIMIT 1
                    ");

                    $r->execute([$roleId]);

                    $code = strtolower(
                        (string)$r->fetchColumn()
                    );

                    if ($code === 'reviewer') {

                        $db->prepare("
                            INSERT IGNORE INTO conference_reviewers
                            (
                                conference_id,
                                reviewer_id
                            )
                            VALUES
                            (
                                ?,
                                ?
                            )
                        ")->execute([
                            $conferenceId,
                            $uid
                        ]);

                    }

                } catch (\Throwable $e) {
                }

            }

            $db->commit();

        } catch (\Throwable $e) {

            if ($db->inTransaction()) {
                $db->rollBack();
            }

            throw $e;

        }

        header(
            "Location: /easychair/admin/users?conference_id=".$conferenceId."&bulk=assigned"
        );

        exit;

    }




    /*
    |--------------------------------------------------------------------------
    | Enterprise Export Users (CSV)
    |--------------------------------------------------------------------------
    */
    public function exportCsv()
    {
        $this->requireAdmin();

        $db = $this->db();

        $conferenceId = (int)($_GET['conference_id'] ?? 0);

        if (ob_get_length()) {
    ob_end_clean();
}

header('Content-Type: text/csv; charset=UTF-8');
        header('Content-Disposition: attachment; filename="conference_users.csv"');

        $out = fopen('php://output', 'w');

/* UTF-8 BOM for Excel */
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));

        fputcsv($out, [
            'ID',
            'First Name',
            'Last Name',
            'Email',
            'Mobile',
            'Global Role',
            'Conference',
            'Conference Role',
            'Status',
            'Created'
        ], ',', '"', '\\');

        $stmt = $db->prepare("
            SELECT
                u.id,
                u.first_name,
                u.last_name,
                u.email,
                u.mobile,
                r.name AS global_role,
                c.short_name,
                cr.name AS conference_role,
                u.is_active,
                u.created_at
            FROM users u
            INNER JOIN user_conferences uc
                ON uc.user_id = u.id
            INNER JOIN conferences c
                ON c.id = uc.conference_id
            LEFT JOIN roles r
                ON r.id = u.role_id
            LEFT JOIN roles cr
                ON cr.id = uc.role_id
            WHERE (? = 0 OR uc.conference_id = ?)
            ORDER BY u.last_name, u.first_name
        ");

        $stmt->execute([$conferenceId, $conferenceId]);

        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
            fputcsv($out, [
                $row['id'],
                $row['first_name'],
                $row['last_name'],
                $row['email'],
                $row['mobile'],
                $row['global_role'],
                $row['short_name'],
                $row['conference_role'],
                $row['is_active'] ? 'Active' : 'Inactive',
                $row['created_at']
            ], ',', '"', '\\');
        }

        fclose($out);
        exit;
    }


}