<?php

namespace App\Controllers;

use App\Utils\Auth;
use App\Utils\Flash;
use App\Config\Database;

class UserController {

    public function index() {
        Auth::requireAdmin();
        $user = Auth::user();
        
        $db = Database::getInstance()->getConnection();
        
        // Branch Filter Logic
        $selectedBranch = $_GET['branch_id'] ?? 'all';
        $branches = [];

        if ($user['role'] === 'admin') {
            $stmt = $db->prepare("SELECT id, name FROM branches WHERE tenant_id = ? ORDER BY name ASC");
            $stmt->execute([$user['tenant_id']]);
            $branches = $stmt->fetchAll();
        }
        
        $branchQuery = "";
        $params = [$user['tenant_id']];
        
        if ($user['role'] !== 'admin' && !empty($user['branch_id'])) {
            $branchQuery = " AND u.branch_id = ?";
            $params[] = $user['branch_id'];
        } elseif ($user['role'] === 'admin' && $selectedBranch !== 'all') {
            $branchQuery = " AND u.branch_id = ?";
            $params[] = $selectedBranch;
        }

        // Pagination
        $perPage = 20;
        $page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
        
        $countStmt = $db->prepare("SELECT COUNT(*) FROM users u WHERE u.tenant_id = ? AND u.role != 'superadmin' $branchQuery");
        $countStmt->execute($params);
        $totalItems = $countStmt->fetchColumn();
        
        $totalPages = max(1, ceil($totalItems / $perPage));
        if ($page > $totalPages) $page = $totalPages;
        $offset = ($page - 1) * $perPage;

        // Fetch paginated users for this tenant
        $stmt = $db->prepare("
            SELECT u.*, b.name as branch_name 
            FROM users u 
            LEFT JOIN branches b ON u.branch_id = b.id 
            WHERE u.tenant_id = ? AND u.role != 'superadmin' $branchQuery
            ORDER BY u.created_at DESC
            LIMIT ? OFFSET ?
        ");
        
        // Add limit and offset to params
        $params[] = $perPage;
        $params[] = $offset;
        
        // Since we use LIMIT with prepared statements in PDO without emulated prepares, we might need to bind params explicitly
        // Or just let execute handle them as strings (mysql converts them), but it's safer to bind.
        // Actually, execute() with array treats all as strings, which fails LIMIT ?,? sometimes.
        // I will use bindValue for all.
        foreach ($params as $key => $val) {
            $stmt->bindValue($key + 1, $val, is_int($val) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
        }
        $stmt->execute();
        $users = $stmt->fetchAll();

        require_once __DIR__ . '/../../views/admin/users/index.php';
    }

    public function create() {
        Auth::requireAdmin();
        $user = Auth::user();
        
        $db = Database::getInstance()->getConnection();
        $stmt = $db->prepare("SELECT * FROM branches WHERE tenant_id = ?");
        $stmt->execute([$user['tenant_id']]);
        $branches = $stmt->fetchAll();

        $stmt = $db->query("SELECT * FROM privileges ORDER BY id ASC");
        $privileges = $stmt->fetchAll();

        require_once __DIR__ . '/../../views/admin/users/create.php';
    }

    public function store() {
        Auth::requireAdmin();
        $user = Auth::user();

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            header("Location: /users");
            exit;
        }

        $name = $_POST['name'] ?? '';
        $email = $_POST['email'] ?? '';
        $password = $_POST['password'] ?? '';
        $role = $_POST['role'] ?? 'cashier';
        $branchId = $_POST['branch_id'] ?? null;
        $privileges = $_POST['privileges'] ?? [];

        if (empty($name) || empty($email) || empty($password)) {
            Flash::set('error', 'All fields are required.');
            header("Location: /users/create");
            exit;
        }
        
        if (empty($branchId) && $role !== 'admin') {
            Flash::set('error', 'Branch is required for cashiers and pharmacists.');
            header("Location: /users/create");
            exit;
        }

        $db = Database::getInstance()->getConnection();
        
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $db->prepare("INSERT INTO users (tenant_id, branch_id, name, email, password_hash, role) VALUES (?, ?, ?, ?, ?, ?)");
        
        try {
            $db->beginTransaction();
            $stmt->execute([$user['tenant_id'], $branchId ?: null, $name, $email, $passwordHash, $role]);
            $newUserId = $db->lastInsertId();

            if ($role !== 'admin' && !empty($privileges)) {
                $privStmt = $db->prepare("INSERT INTO user_privileges (user_id, privilege_id) VALUES (?, ?)");
                foreach ($privileges as $privId) {
                    $privStmt->execute([$newUserId, $privId]);
                }
            }

            $db->commit();
            Flash::set('success', 'User created successfully.');
            header("Location: /users");
            exit;
        } catch (\PDOException $e) {
            $db->rollBack();
            Flash::set('error', 'Error creating user. Email might already exist.');
            header("Location: /users/create");
            exit;
        }
    }

    public function edit($id) {
        Auth::requireAdmin();
        $user = Auth::user();

        $db = Database::getInstance()->getConnection();
        
        $stmt = $db->prepare("SELECT * FROM users WHERE id = ? AND tenant_id = ? AND role != 'superadmin'");
        $stmt->execute([$id, $user['tenant_id']]);
        $editUser = $stmt->fetch();

        if (!$editUser) {
            Flash::set('error', 'User not found.');
            header("Location: /users");
            exit;
        }

        $stmt = $db->prepare("SELECT * FROM branches WHERE tenant_id = ?");
        $stmt->execute([$user['tenant_id']]);
        $branches = $stmt->fetchAll();

        $stmt = $db->query("SELECT * FROM privileges ORDER BY id ASC");
        $privileges = $stmt->fetchAll();
        
        $stmt = $db->prepare("SELECT privilege_id FROM user_privileges WHERE user_id = ?");
        $stmt->execute([$id]);
        $userPrivileges = $stmt->fetchAll(\PDO::FETCH_COLUMN);

        require_once __DIR__ . '/../../views/admin/users/edit.php';
    }

    public function update($id) {
        Auth::requireAdmin();
        $user = Auth::user();

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            header("Location: /users");
            exit;
        }

        $name = $_POST['name'] ?? '';
        $role = $_POST['role'] ?? 'cashier';
        $branchId = $_POST['branch_id'] ?? null;
        $status = $_POST['status'] ?? 'active';
        $privileges = $_POST['privileges'] ?? [];
        $password = $_POST['password'] ?? '';

        if (empty($name)) {
            Flash::set('error', 'Name is required.');
            header("Location: /users/edit/$id");
            exit;
        }

        $db = Database::getInstance()->getConnection();
        
        $stmt = $db->prepare("SELECT id FROM users WHERE id = ? AND tenant_id = ? AND role != 'superadmin'");
        $stmt->execute([$id, $user['tenant_id']]);
        if (!$stmt->fetch()) {
            Flash::set('error', 'User not found or permission denied.');
            header("Location: /users");
            exit;
        }
        
        try {
            $db->beginTransaction();

            $stmt = $db->prepare("UPDATE users SET name = ?, branch_id = ?, role = ?, status = ? WHERE id = ? AND tenant_id = ?");
            $stmt->execute([$name, $branchId ?: null, $role, $status, $id, $user['tenant_id']]);

            if (!empty($password)) {
                $pwStmt = $db->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
                $pwStmt->execute([password_hash($password, PASSWORD_DEFAULT), $id]);
            }

            $db->prepare("DELETE FROM user_privileges WHERE user_id = ?")->execute([$id]);
            
            if ($role !== 'admin' && !empty($privileges)) {
                $privStmt = $db->prepare("INSERT INTO user_privileges (user_id, privilege_id) VALUES (?, ?)");
                foreach ($privileges as $privId) {
                    $privStmt->execute([$id, $privId]);
                }
            }

            $db->commit();
            Flash::set('success', 'User updated successfully.');
            header("Location: /users");
            exit;
        } catch (\PDOException $e) {
            $db->rollBack();
            Flash::set('error', 'Error updating user.');
            header("Location: /users/edit/$id");
            exit;
        }
    }

    public function destroy($id) {
        Auth::requireAdmin();
        $user = Auth::user();

        $db = Database::getInstance()->getConnection();

        if ($id == $user['id']) {
            Flash::set('error', 'You cannot delete your own account.');
            header("Location: /users");
            exit;
        }

        $stmt = $db->prepare("SELECT id FROM users WHERE id = ? AND tenant_id = ? AND role != 'superadmin'");
        $stmt->execute([$id, $user['tenant_id']]);
        if (!$stmt->fetch()) {
            Flash::set('error', 'User not found.');
            header("Location: /users");
            exit;
        }

        $stmt = $db->prepare("DELETE FROM users WHERE id = ? AND tenant_id = ? AND role != 'superadmin'");
        $stmt->execute([$id, $user['tenant_id']]);

        Flash::set('success', 'User deleted successfully.');
        header("Location: /users");
        exit;
    }

    public function profile() {
        Auth::requireLogin();
        $user = Auth::user();
        
        $db = Database::getInstance()->getConnection();
        $stmt = $db->prepare("SELECT email FROM users WHERE id = ?");
        $stmt->execute([$user['id']]);
        $email = $stmt->fetchColumn();

        require_once __DIR__ . '/../../views/admin/users/profile.php';
    }

    public function updateProfile() {
        Auth::requireLogin();
        $user = Auth::user();

        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            header("Location: /users/profile");
            exit;
        }

        $password = $_POST['password'] ?? '';
        $confirmPassword = $_POST['confirm_password'] ?? '';

        if (empty($password) || empty($confirmPassword)) {
            Flash::set('error', 'Both password fields are required.');
            header("Location: /users/profile");
            exit;
        }

        if ($password !== $confirmPassword) {
            Flash::set('error', 'Passwords do not match.');
            header("Location: /users/profile");
            exit;
        }

        $db = Database::getInstance()->getConnection();
        $pwStmt = $db->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
        $pwStmt->execute([password_hash($password, PASSWORD_DEFAULT), $user['id']]);

        Flash::set('success', 'Password updated successfully.');
        header("Location: /users/profile");
        exit;
    }
}
