import bcrypt
import secrets
from datetime import datetime, timedelta
from models.database import execute_query, execute_single_query, execute_update_query

class UserModel:
    @staticmethod
    def get_all_users():
        query = "SELECT * FROM users ORDER BY created_at DESC"
        return execute_query(query)
    
    @staticmethod
    def get_user_by_id(user_id):
        query = "SELECT * FROM users WHERE id = %s"
        return execute_single_query(query, (user_id,))
    
    @staticmethod
    def get_user_by_email(email):
        query = "SELECT * FROM users WHERE email = %s"
        return execute_single_query(query, (email,))
    
    @staticmethod
    def create_user(name, email, password, role='user'):
        hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
        query = "INSERT INTO users (name, email, password, role) VALUES (%s, %s, %s, %s)"
        return execute_update_query(query, (name, email, hashed_password.decode('utf-8'), role))
    
    @staticmethod
    def update_user(user_id, name, email, role):
        query = "UPDATE users SET name = %s, email = %s, role = %s WHERE id = %s"
        return execute_update_query(query, (name, email, role, user_id))

    @staticmethod
    def update_user_lang(user_id, lang):
        query = "UPDATE users SET lang = %s WHERE id = %s"
        return execute_update_query(query, (lang, user_id))
    
    @staticmethod
    def update_user_password(user_id, password):
        hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
        query = "UPDATE users SET password = %s WHERE id = %s"
        return execute_update_query(query, (hashed_password.decode('utf-8'), user_id))
    
    @staticmethod
    def delete_user(user_id):
        query = "DELETE FROM users WHERE id = %s"
        return execute_update_query(query, (user_id,))
    
    @staticmethod
    def verify_password(password, hashed_password):
        return bcrypt.checkpw(password.encode('utf-8'), hashed_password.encode('utf-8'))
    
    @staticmethod
    def get_users_count():
        query = "SELECT COUNT(*) as count FROM users"
        result = execute_single_query(query)
        return result['count'] if result else 0

    @staticmethod
    def create_password_reset_token(user_id, expiration_hours=1):
        """Create a password reset token for a user"""
        # Generate secure random token
        token = secrets.token_urlsafe(32)
        expires_at = datetime.now() + timedelta(hours=expiration_hours)

        # Delete any existing unused tokens for this user
        delete_query = "DELETE FROM password_reset_tokens WHERE user_id = %s AND used = FALSE"
        execute_update_query(delete_query, (user_id,))

        # Insert new token
        insert_query = """
            INSERT INTO password_reset_tokens (user_id, token, expires_at)
            VALUES (%s, %s, %s)
        """
        execute_update_query(insert_query, (user_id, token, expires_at))

        return token

    @staticmethod
    def verify_reset_token(token):
        """Verify if a reset token is valid and not expired"""
        query = """
            SELECT prt.*, u.id as user_id, u.email, u.name
            FROM password_reset_tokens prt
            JOIN users u ON prt.user_id = u.id
            WHERE prt.token = %s
            AND prt.used = FALSE
            AND prt.expires_at > NOW()
        """
        return execute_single_query(query, (token,))

    @staticmethod
    def use_reset_token(token):
        """Mark a reset token as used"""
        query = "UPDATE password_reset_tokens SET used = TRUE WHERE token = %s"
        return execute_update_query(query, (token,))

    @staticmethod
    def reset_password_with_token(token, new_password):
        """Reset user password using a valid token"""
        # Verify token
        token_data = UserModel.verify_reset_token(token)
        if not token_data:
            return False

        # Update password
        user_id = token_data['user_id']
        UserModel.update_user_password(user_id, new_password)

        # Mark token as used
        UserModel.use_reset_token(token)

        return True
