<?php
class User {
    private $conn;
    private $table_name = "usuarios";

    public $id;
    public $nombre;
    public $email;
    public $password_hash;
    public $rol;
    public $fecha_creacion;
    public $activo;
    public $ultimo_acceso;

    public function __construct($db) {
        $this->conn = $db;
    }

    // Crear nuevo usuario
    public function create() {
        $query = "INSERT INTO " . $this->table_name . " 
                  (nombre, email, password_hash, rol, activo) 
                  VALUES (:nombre, :email, :password_hash, :rol, :activo)";

        $stmt = $this->conn->prepare($query);

        // Sanitizar datos
        $this->nombre = htmlspecialchars(strip_tags($this->nombre));
        $this->email = htmlspecialchars(strip_tags($this->email));
        $this->rol = htmlspecialchars(strip_tags($this->rol));

        // Hash de la contraseña
        $this->password_hash = password_hash($this->password_hash, PASSWORD_BCRYPT);

        // Bind de parámetros
        $stmt->bindParam(":nombre", $this->nombre);
        $stmt->bindParam(":email", $this->email);
        $stmt->bindParam(":password_hash", $this->password_hash);
        $stmt->bindParam(":rol", $this->rol);
        $stmt->bindParam(":activo", $this->activo);

        if ($stmt->execute()) {
            $this->id = $this->conn->lastInsertId();
            return true;
        }

        return false;
    }

    // Buscar usuario por email
    public function findByEmail($email) {
        $query = "SELECT id, nombre, email, password_hash, rol, fecha_creacion, activo, ultimo_acceso 
                  FROM " . $this->table_name . " 
                  WHERE email = :email AND activo = 1 
                  LIMIT 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":email", $email);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            $this->id = $row['id'];
            $this->nombre = $row['nombre'];
            $this->email = $row['email'];
            $this->password_hash = $row['password_hash'];
            $this->rol = $row['rol'];
            $this->fecha_creacion = $row['fecha_creacion'];
            $this->activo = $row['activo'];
            $this->ultimo_acceso = $row['ultimo_acceso'];
            
            return true;
        }

        return false;
    }

    // Buscar usuario por ID
    public function findById($id) {
        $query = "SELECT id, nombre, email, rol, fecha_creacion, activo, ultimo_acceso 
                  FROM " . $this->table_name . " 
                  WHERE id = :id AND activo = 1 
                  LIMIT 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $id);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            
            $this->id = $row['id'];
            $this->nombre = $row['nombre'];
            $this->email = $row['email'];
            $this->rol = $row['rol'];
            $this->fecha_creacion = $row['fecha_creacion'];
            $this->activo = $row['activo'];
            $this->ultimo_acceso = $row['ultimo_acceso'];
            
            return true;
        }

        return false;
    }

    // Verificar contraseña
    public function verifyPassword($password) {
        return password_verify($password, $this->password_hash);
    }

    // Actualizar último acceso
    public function updateLastAccess() {
        $query = "UPDATE " . $this->table_name . " 
                  SET ultimo_acceso = CURRENT_TIMESTAMP 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $this->id);
        
        return $stmt->execute();
    }

    // Obtener todos los usuarios (para administradores)
    public function read() {
        $query = "SELECT id, nombre, email, rol, fecha_creacion, activo, ultimo_acceso 
                  FROM " . $this->table_name . " 
                  ORDER BY fecha_creacion DESC";

        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        return $stmt;
    }

    // Actualizar usuario
    public function update() {
        $query = "UPDATE " . $this->table_name . " 
                  SET nombre = :nombre, email = :email, rol = :rol, activo = :activo 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);

        // Sanitizar datos
        $this->nombre = htmlspecialchars(strip_tags($this->nombre));
        $this->email = htmlspecialchars(strip_tags($this->email));
        $this->rol = htmlspecialchars(strip_tags($this->rol));

        // Bind de parámetros
        $stmt->bindParam(":nombre", $this->nombre);
        $stmt->bindParam(":email", $this->email);
        $stmt->bindParam(":rol", $this->rol);
        $stmt->bindParam(":activo", $this->activo);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Eliminar usuario (desactivar)
    public function delete() {
        $query = "UPDATE " . $this->table_name . " 
                  SET activo = 0 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Validar datos de entrada
    public function validate() {
        $errors = [];

        if (empty($this->nombre)) {
            $errors[] = "El nombre es requerido";
        } elseif (strlen($this->nombre) < 2) {
            $errors[] = "El nombre debe tener al menos 2 caracteres";
        } elseif (strlen($this->nombre) > 100) {
            $errors[] = "El nombre no puede exceder 100 caracteres";
        }

        if (empty($this->email)) {
            $errors[] = "El email es requerido";
        } elseif (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
            $errors[] = "El email no es válido";
        } elseif (strlen($this->email) > 100) {
            $errors[] = "El email no puede exceder 100 caracteres";
        }

        if (!in_array($this->rol, ['Administrador', 'Regente', 'Técnico de Campo'])) {
            $errors[] = "El rol no es válido";
        }

        return $errors;
    }

    // Validar contraseña
    public function validatePassword($password) {
        $errors = [];

        if (empty($password)) {
            $errors[] = "La contraseña es requerida";
        } elseif (strlen($password) < 6) {
            $errors[] = "La contraseña debe tener al menos 6 caracteres";
        } elseif (strlen($password) > 255) {
            $errors[] = "La contraseña es demasiado larga";
        }

        return $errors;
    }

    // Verificar si el email ya existe
    public function emailExists($email, $excludeId = null) {
        $query = "SELECT id FROM " . $this->table_name . " WHERE email = :email";
        
        if ($excludeId) {
            $query .= " AND id != :exclude_id";
        }

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":email", $email);
        
        if ($excludeId) {
            $stmt->bindParam(":exclude_id", $excludeId);
        }
        
        $stmt->execute();

        return $stmt->rowCount() > 0;
    }

    // Validar permisos por rol
    public function hasPermission($action, $resource = null) {
        switch ($this->rol) {
            case 'Administrador':
                return true; // Administradores tienen acceso completo
            
            case 'Regente':
                // Regentes pueden gestionar proyectos y ver reportes
                $allowedActions = ['create_project', 'read_project', 'update_project', 'delete_project', 
                                 'read_rodal', 'create_rodal', 'update_rodal', 'delete_rodal',
                                 'read_reports', 'export_data', 'read_field_data'];
                return in_array($action, $allowedActions);
            
            case 'Técnico de Campo':
                // Técnicos solo pueden usar la aplicación móvil de campo
                $allowedActions = ['read_project', 'read_rodal', 'create_field_data', 
                                 'read_field_data', 'sync_data'];
                return in_array($action, $allowedActions);
            
            default:
                return false;
        }
    }

    // Obtener usuarios por rol
    public function getUsersByRole($rol) {
        $query = "SELECT id, nombre, email, rol, fecha_creacion, activo, ultimo_acceso 
                  FROM " . $this->table_name . " 
                  WHERE rol = :rol AND activo = 1 
                  ORDER BY nombre ASC";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":rol", $rol);
        $stmt->execute();

        return $stmt;
    }

    // Cambiar contraseña
    public function changePassword($newPassword) {
        $query = "UPDATE " . $this->table_name . " 
                  SET password_hash = :password_hash 
                  WHERE id = :id";

        $stmt = $this->conn->prepare($query);
        
        $hashedPassword = password_hash($newPassword, PASSWORD_BCRYPT);
        $stmt->bindParam(":password_hash", $hashedPassword);
        $stmt->bindParam(":id", $this->id);

        return $stmt->execute();
    }

    // Obtener estadísticas de usuarios
    public function getUserStats() {
        $query = "SELECT 
                    rol,
                    COUNT(*) as total,
                    SUM(CASE WHEN activo = 1 THEN 1 ELSE 0 END) as activos,
                    SUM(CASE WHEN ultimo_acceso >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 ELSE 0 END) as activos_mes
                  FROM " . $this->table_name . " 
                  GROUP BY rol";

        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        return $stmt;
    }

    // Métodos estáticos para testing
    public static function validateUserData($data) {
        $errors = [];
        
        if (empty($data['nombre'])) {
            $errors[] = "El nombre es requerido";
        }
        
        if (empty($data['email'])) {
            $errors[] = "El email es requerido";
        } elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            $errors[] = "Email inválido";
        }
        
        if (empty($data['password'])) {
            $errors[] = "La contraseña es requerida";
        } elseif (strlen($data['password']) < 6) {
            $errors[] = "La contraseña debe tener al menos 6 caracteres";
        }
        
        if (empty($data['rol'])) {
            $errors[] = "El rol es requerido";
        } elseif (!in_array($data['rol'], ['Administrador', 'Regente', 'Técnico de Campo'])) {
            $errors[] = "Rol inválido";
        }
        
        return [
            'valid' => empty($errors),
            'errors' => $errors
        ];
    }
    
    public static function hashPassword($password) {
        return password_hash($password, PASSWORD_DEFAULT);
    }
    
    public static function verifyPassword($password, $hash) {
        return password_verify($password, $hash);
    }
    
    public static function getValidRoles() {
        return ['Administrador', 'Regente', 'Técnico de Campo'];
    }
    
    public static function sanitizeUserData($data) {
        return [
            'nombre' => trim($data['nombre'] ?? ''),
            'email' => strtolower(trim($data['email'] ?? '')),
            'rol' => ucwords(strtolower($data['rol'] ?? ''))
        ];
    }
    
    public static function canAccessResource($rol, $resource) {
        $permissions = [
            'Administrador' => ['users', 'projects', 'reports', 'field-data'],
            'Regente' => ['projects', 'reports', 'field-data'],
            'Técnico de Campo' => ['field-data']
        ];
        
        return isset($permissions[$rol]) && in_array($resource, $permissions[$rol]);
    }
    
    public function generateUserToken($userData) {
        // Mock JWT generation for testing
        $header = base64_encode(json_encode(['typ' => 'JWT', 'alg' => 'HS256']));
        $payload = base64_encode(json_encode($userData));
        $signature = base64_encode('mock_signature');
        
        return $header . '.' . $payload . '.' . $signature;
    }
}
?>