from app import db  # Add this if not already there
from sqlalchemy import func  # Add this
from flask import Blueprint, request, jsonify, send_from_directory
from app.services.services import MachineService, UserService, ProductService, serial_service, TransactionService, RoleService
from app.models.models import Machine, User, Transaction, Product, VendingSlot, Role 
import os
import hashlib
import time
import uuid
import json
from dotenv import load_dotenv
from functools import wraps
import jwt  # Added for JWT token generation
from datetime import datetime, timedelta  # Added for token expiration

load_dotenv()  # Load environment variables

bp = Blueprint('api', __name__)

@bp.route('/login', methods=['POST'])
def login():
    data = request.json
    machine_id = data.get('machine_id')
    password = data.get('password')

    if not machine_id or not password:
        return jsonify({"error": "machine_id and password are required"}), 400

    machine = Machine.query.filter_by(machine_id=machine_id).first()
    print(f"Debug - Machine found: {machine}")
    print(f"Debug - Machine ID from DB: {machine.machine_id if machine else 'None'}")
    print(f"Debug - Password from DB: {machine.password if machine else 'None'}")
    print(f"Debug - Input Password: {password}")
    if not machine or machine.password != password:
        return jsonify({"error": "Invalid machine_id or password"}), 401

    return jsonify({
        'message': 'Login successful',
        'machine_id': machine.machine_id,
        'id': machine.id
    }), 200

@bp.route('/machine-slots/<machine_id>', methods=['GET'])
def get_machine_slots(machine_id):
    slots = MachineService.get_machine_slots(machine_id)
    if slots is None:
        return jsonify({"error": "Machine not found"}), 404
    return jsonify(slots)

@bp.route('/machine-slots/update-inventory', methods=['POST'])
def update_machine_slots_inventory():
    """Update inventory after successful purchase"""
    try:
        print("\n" + "=" * 60)
        print("INVENTORY UPDATE REQUEST")
        print("=" * 60)
        
        data = request.json
        machine_id = data.get('machineId')
        inventory_updates = data.get('inventoryUpdates', [])
        
        if not machine_id or not inventory_updates:
            return jsonify({'error': 'Missing machineId or inventoryUpdates'}), 400
        
        print(f"Machine ID: {machine_id}")
        print(f"Updates: {len(inventory_updates)} items")
        
        # Update each slot
        for update in inventory_updates:
            slot_id = update.get('slotId')
            quantity_dispensed = update.get('quantityDispensed')
            
            # Extract row and column from slotId (e.g., "A1" -> row="A", column=1)
            row_id = slot_id[0]
            column = int(slot_id[1:])
            
            print(f"  - Updating slot {slot_id}: reducing {quantity_dispensed} units")
            
            # Find and update the slot
            slot = VendingSlot.query.filter_by(
                machine_id=machine_id,
                row_id=row_id,
                slot_name=slot_id
            ).first()
            
            if slot:
                # Reduce units
                new_units = max(0, slot.units - quantity_dispensed)
                slot.units = new_units
                
                # Disable slot if units reach 0
                if new_units <= 0:
                    slot.enabled = False
                    print(f"    ✓ Slot {slot_id}: {slot.units} -> {new_units} units (DISABLED)")
                else:
                    print(f"    ✓ Slot {slot_id}: {slot.units + quantity_dispensed} -> {new_units} units")
            else:
                print(f"    ✗ Slot {slot_id} not found!")
        
        # Commit all changes
        db.session.commit()
        
        print(f"✓ Inventory updated successfully")
        print("=" * 60 + "\n")
        
        return jsonify({
            'success': True,
            'message': 'Inventory updated successfully',
            'updated_slots': len(inventory_updates)
        }), 200
        
    except Exception as e:
        db.session.rollback()
        print(f"\n✗ INVENTORY UPDATE ERROR")
        print(f"Error: {str(e)}")
        
        import traceback
        traceback.print_exc()
        print("=" * 60 + "\n")
        
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@bp.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(os.path.join(bp.root_path, '..', 'Uploads'), filename)

@bp.route('/machines', methods=['GET'])
def get_machines():
    try:
        machines = MachineService.get_all_machines()
        return jsonify([machine.to_dict() for machine in machines])
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/machines', methods=['POST'])
def add_machine():
    data = request.json
    
    # Get current user from token
    current_user = get_current_user_from_token()
    
    if not current_user:
        return jsonify({"error": "Authentication required"}), 401
    
    try:
        # FORCE client_id for Clients
        if current_user.roles == 'Client':
            data['client_id'] = current_user.id
            print(f"✓ Client {current_user.username} (ID: {current_user.id}) creating machine")
        else:
            # Admin/Management must provide client_id
            if 'client_id' not in data:
                return jsonify({"error": "client_id is required"}), 400
            print(f"✓ Admin creating machine for client_id: {data['client_id']}")
        
        new_machine = MachineService.create_machine(data)
        print(f"✓ Machine created: {new_machine.machine_id} for client_id: {new_machine.client_id}")
        
        return jsonify(new_machine.to_dict()), 201
        
    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({"error": str(e)}), 500

@bp.route('/machines/<int:id>', methods=['PUT'])
def update_machine(id):
    data = request.json
    try:
        updated_machine = MachineService.update_machine(id, data)
        return jsonify(updated_machine.to_dict())
    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/machines/<int:id>', methods=['DELETE'])
def delete_machine(id):
    try:
        MachineService.delete_machine(id)
        return jsonify({"message": "Machine deleted successfully"}), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 500

# Updated User Routes in routes.py

# In your routes.py file

@bp.route('/users', methods=['GET'])
def get_users():
    try:
        users = UserService.get_all_users()
        return jsonify([user.to_dict() for user in users])
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/users', methods=['POST'])
def add_users():
    print("\n" + "=" * 60)
    print("CREATE USER REQUEST")
    print("=" * 60)
    
    try:
        # Get form data
        data = request.form.to_dict()
        print("Form data keys:", list(data.keys()))
        print("Form values:", data)
        
        # Get files
        photo_file = request.files.get('photo')
        logo_file = request.files.get('company_logo')
        document_files = request.files.getlist('documents')
        documents_metadata = request.form.get('documents_metadata')
        
        print(f"\nFiles received:")
        print(f"  Photo: {photo_file.filename if photo_file else None}")
        print(f"  Logo: {logo_file.filename if logo_file else None}")
        print(f"  Documents: {len(document_files)} files")
        if document_files:
            for i, f in enumerate(document_files):
                print(f"    {i+1}. {f.filename}")
        print(f"  Metadata: {documents_metadata}")
        
        # Call service
        print("\nCalling UserService.create_user...")
        new_user = UserService.create_user(
            data, 
            photo_file, 
            logo_file, 
            document_files if document_files else None,
            documents_metadata
        )
        
        print("✓ User created successfully!")
        print("=" * 60 + "\n")
        
        return jsonify(new_user.to_dict()), 201
        
    except ValueError as e:
        print(f"\n✗ Validation Error: {str(e)}")
        print("=" * 60 + "\n")
        return jsonify({"error": str(e)}), 400
        
    except Exception as e:
        print(f"\n✗ SERVER ERROR")
        print(f"Error type: {type(e).__name__}")
        print(f"Error message: {str(e)}")
        
        import traceback
        print("\nFull traceback:")
        traceback.print_exc()
        print("=" * 60 + "\n")
        
        return jsonify({"error": f"Server error: {str(e)}"}), 500

@bp.route('/users/<int:id>', methods=['PUT'])
def update_user(id):
    try:
        data = request.form.to_dict()
        
        # Get uploaded files
        photo_file = request.files.get('photo')
        logo_file = request.files.get('company_logo')
        document_files = request.files.getlist('documents')
        
        # Get document metadata - THIS IS NEW
        documents_metadata = request.form.get('documents_metadata')
        
        # Pass metadata to service - UPDATED PARAMETER LIST
        updated_user = UserService.update_user(
            id, 
            data, 
            photo_file, 
            logo_file, 
            document_files,
            documents_metadata  # NEW PARAMETER
        )
        return jsonify(updated_user.to_dict())
    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/users/<int:id>', methods=['DELETE'])
def delete_user(id):
    try:
        UserService.delete_user(id)
        return jsonify({"message": "User deleted successfully"}), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/users/<int:user_id>/documents/<path:document_path>', methods=['DELETE'])
def delete_user_document(user_id, document_path):
    """Delete a specific document from a user"""
    try:
        # Decode the document path (in case it was URL encoded)
        document_path = '/' + document_path
        success = UserService.delete_user_document(user_id, document_path)
        
        if success:
            return jsonify({"message": "Document deleted successfully"}), 200
        else:
            return jsonify({"error": "Document not found"}), 404
    except Exception as e:
        return jsonify({"error": str(e)}), 500



# Serve uploaded files
@bp.route('/uploads/user_photos/<filename>')
def serve_user_photo(filename):
    return send_from_directory(os.path.join(bp.root_path, '..', 'Uploads', 'user_photos'), filename)

@bp.route('/uploads/company_logos/<filename>')
def serve_company_logo(filename):
    return send_from_directory(os.path.join(bp.root_path, '..', 'Uploads', 'company_logos'), filename)

@bp.route('/uploads/user_documents/<filename>')
def serve_user_document(filename):
    return send_from_directory(os.path.join(bp.root_path, '..', 'Uploads', 'user_documents'), filename)

@bp.route('/products', methods=['GET'])
def get_products():
    try:
        products = ProductService.get_all_products()
        return jsonify([product.to_dict() for product in products])
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/products', methods=['POST'])
def add_product():
    try:
        data = request.form
        file = request.files.get('product_image')
        new_product = ProductService.create_product(data, file)
        return jsonify(new_product.to_dict()), 201
    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/products/<int:id>', methods=['PUT'])
def update_product(id):
    try:
        data = request.form
        file = request.files.get('product_image') if 'product_image' in request.files else None
        updated_product = ProductService.update_product(id, data, file)
        return jsonify(updated_product.to_dict())
    except ValueError as e:
        return jsonify({"error": str(e)}), 400
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/products/<int:id>', methods=['DELETE'])
def delete_product(id):
    try:
        ProductService.delete_product(id)
        return jsonify({"message": "Product deleted successfully"}), 200
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/machines/<int:id>', methods=['GET'])
def get_machine(id):
    try:
        machine = MachineService.get_machine_by_id(id)
        return jsonify(machine.to_dict())
    except Exception as e:
        return jsonify({"error": str(e)}), 404

@bp.route('/machines/<machine_id>', methods=['GET'])
def get_vending_state(machine_id):
    try:
        state = MachineService.get_vending_state(machine_id)
        return jsonify(state)
    except Exception as e:
        return jsonify({"error": str(e)}), 404

@bp.route('/machines/<machine_id>/vending-state', methods=['PUT'])
def update_vending_state(machine_id):
    try:
        data = request.get_json()
        if not data or 'vendingRows' not in data:
            return jsonify({'error': 'Invalid data'}), 400
        result = MachineService.update_vending_state(machine_id, data['vendingRows'])
        return jsonify(result)
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/create-payu-order', methods=['POST'])
def create_payu_order():
    data = request.json or {}

    machine_id = data.get('machineId')
    total_amount = data.get('totalAmount')
    product_info = data.get('productInfo')
    cart_data = data.get('cartData', '[]')
    user_details = data.get('userDetails', {})

    if not machine_id or not total_amount or not product_info:
        return jsonify({"error": "Missing required fields"}), 400

    txnid = f"txn_{int(time.time())}_{uuid.uuid4().hex[:5]}"

    payu_key = os.getenv('PAYU_MERCHANT_KEY')
    payu_salt = os.getenv('PAYU_MERCHANT_SALT')
    
    if not payu_key or not payu_salt:
        return jsonify({"error": "PayU credentials not configured"}), 500

    payu_data = {
        "key": payu_key,
        "txnid": txnid,
        "amount": f"{float(total_amount):.2f}",
        "productinfo": product_info,
        "firstname": user_details.get("firstname", "Customer"),
        "email": user_details.get("email", "customer@example.com"),
        "phone": user_details.get("phone", "9999999999"),
        "surl": f"{os.getenv('BASE_URL', 'http://localhost:5000')}/payment-success",
        "furl": f"{os.getenv('BASE_URL', 'http://localhost:5000')}/payment-failure",
        "service_provider": "payu_paisa",
        "udf1": machine_id or "",
        "udf2": cart_data or "",
        "udf3": "",
        "udf4": "",
        "udf5": ""
    }

    # Correct PayU hash string
    hash_string = (
        f"{payu_data['key']}|{payu_data['txnid']}|{payu_data['amount']}|"
        f"{payu_data['productinfo']}|{payu_data['firstname']}|{payu_data['email']}|"
        f"{payu_data['udf1']}|{payu_data['udf2']}|{payu_data['udf3']}|"
        f"{payu_data['udf4']}|{payu_data['udf5']}||||||{payu_salt}"
    )

    # Calculate hash as a simple string (NOT an object)
    calculated_hash = hashlib.sha512(hash_string.encode('utf-8')).hexdigest()
    payu_data["hash"] = calculated_hash  # Just the string, not an object

    # Debug logging
    print("=== PayU Hash Debug ===")
    print(f"Hash string: {hash_string}")
    print(f"Calculated hash: {calculated_hash}")
    print(f"PayU data: {payu_data}")
    print("======================")

    return jsonify(payu_data), 200
@bp.route('/create-payu-order-v2', methods=['POST'])
def create_payu_order_v2():
    """Alternative PayU order endpoint with JSON hash format"""
    data = request.json
    if not data:
        return jsonify({"error": "No data received"}), 400

    machine_id = data.get('machineId')
    total_amount = data.get('totalAmount')
    product_info = data.get('productInfo')
    cart_data = data.get('cartData', '[]')
    user_details = data.get('userDetails', {})

    if not machine_id or not total_amount or not product_info:
        return jsonify({"error": "Missing required fields"}), 400

    machine = Machine.query.filter_by(machine_id=machine_id).first()
    if not machine:
        return jsonify({"error": "Machine not found"}), 404

    txnid = f"txn_{int(time.time())}_{uuid.uuid4().hex[:5]}"
    
    payu_key = os.getenv('PAYU_MERCHANT_KEY')
    payu_salt = os.getenv('PAYU_MERCHANT_SALT')
    
    if not payu_key or not payu_salt:
        return jsonify({"error": "PayU credentials not configured"}), 500

    payu_data = {
        "key": payu_key,
        "txnid": txnid,
        "amount": f"{float(total_amount):.2f}",
        "productinfo": product_info,
        "firstname": "mukesh",  # Consistent with error message
        "email": "customer@example.com",
        "phone": "9999999999",
        "surl": "https://savannah-syntypic-synchronously.ngrok-free.dev/payment-success",
        "furl": "https://savannah-syntypic-synchronously.ngrok-free.dev/payment-failure",
        "service_provider": "payu_paisa",
        "udf1": machine_id,
        "udf2": cart_data,
        "udf3": "",
        "udf4": "",
        "udf5": ""
    }

    hash_string = f"{payu_data['key']}|{payu_data['txnid']}|{payu_data['amount']}|{payu_data['productinfo']}|{payu_data['firstname']}|{payu_data['email']}|{payu_data['udf1']}|{payu_data['udf2']}|{payu_data['udf3']}|{payu_data['udf4']}|{payu_data['udf5']}||||||{payu_salt}"
    
    calculated_hash = hashlib.sha512(hash_string.encode()).hexdigest()
    
    # Return hash in JSON format as shown in PayU error message
    hash_json = json.dumps({
        "v1": calculated_hash,
        "v2": calculated_hash
    })
    
    payu_data["hash"] = hash_json
    
    print("=" * 50)
    print("PayU V2 Order Creation (JSON Hash Format)")
    print("=" * 50)
    print(f"Hash string: {hash_string}")
    print(f"Calculated hash: {calculated_hash}")
    print(f"JSON hash format: {hash_json}")
    print("=" * 50)
    
    return jsonify(payu_data), 200

@bp.route('/success', methods=['POST'])
def payment_success():
    """Handle PayU success callback with proper verification"""
    data = request.form
    
    # Extract all PayU response parameters
    status = data.get('status')
    txnid = data.get('txnid')
    amount = data.get('amount')
    productinfo = data.get('productinfo')
    firstname = data.get('firstname')
    email = data.get('email')
    phone = data.get('phone')
    udf1 = data.get('udf1', '')  # machine_id
    udf2 = data.get('udf2', '')  # cart_data
    udf3 = data.get('udf3', '')
    udf4 = data.get('udf4', '')
    udf5 = data.get('udf5', '')
    hash_received = data.get('hash')
    payuMoneyId = data.get('payuMoneyId')
    
    print("=" * 50)
    print("Payment Success Callback")
    print("=" * 50)
    print(f"Status: {status}")
    print(f"Transaction ID: {txnid}")
    print(f"Amount: {amount}")
    print(f"Machine ID (UDF1): {udf1}")
    print(f"Cart Data (UDF2): {udf2}")
    print(f"PayU Money ID: {payuMoneyId}")
    print("=" * 50)
    
    # Verify hash for security (PayU response hash verification)
    payu_salt = os.getenv('PAYU_MERCHANT_SALT')
    payu_key = os.getenv('PAYU_MERCHANT_KEY')
    
    if payu_salt and payu_key:
        # Response hash formula: sha512(SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key)
        response_hash_string = f"{payu_salt}|{status}||||||{udf5}|{udf4}|{udf3}|{udf2}|{udf1}|{email}|{firstname}|{productinfo}|{amount}|{txnid}|{payu_key}"
        expected_hash = hashlib.sha512(response_hash_string.encode()).hexdigest()
        
        print(f"Response Hash String: {response_hash_string}")
        print(f"Expected Hash: {expected_hash}")
        print(f"Received Hash: {hash_received}")
        
        if hash_received != expected_hash:
            print("WARNING: Hash verification failed!")
            # In production, you might want to reject this transaction
            # For now, we'll log the warning but continue
    
    # Process successful payment
    if status == 'success':
        try:
            # Parse cart data for dispensing instructions
            if udf2:
                cart_items = json.loads(udf2)
                print(f"Cart items to dispense: {cart_items}")
                
                # TODO: Here you would typically:
                # 1. Save transaction to database
                # 2. Send dispensing commands to vending machine
                # 3. Update inventory
                # 4. Send confirmation notifications
                
                # Example dispensing logic (implement according to your machine interface)
                for item in cart_items:
                    slot_id = item.get('slotId')
                    quantity = item.get('quantity', 1)
                    product_name = item.get('productName')
                    print(f"Dispensing: {quantity}x {product_name} from slot {slot_id}")
                    
                    # Call your machine service to dispense
                    # MachineService.dispense_product(udf1, slot_id, quantity)
                
        except json.JSONDecodeError as e:
            print(f"Error parsing cart data: {e}")
        except Exception as e:
            print(f"Error processing dispensing: {e}")
    
    # Return response
    return jsonify({
        "message": "Payment processed successfully" if status == 'success' else "Payment completed",
        "txnid": txnid,
        "status": status,
        "amount": amount,
        "payuMoneyId": payuMoneyId
    }), 200

@bp.route('/failure', methods=['POST'])
def payment_failure():
    """Handle PayU failure callback"""
    data = request.form
    
    txnid = data.get('txnid')
    status = data.get('status')
    error_message = data.get('error', 'Payment failed')
    amount = data.get('amount')
    udf1 = data.get('udf1', '')  # machine_id
    
    print("=" * 50)
    print("Payment Failure Callback")
    print("=" * 50)
    print(f"Transaction ID: {txnid}")
    print(f"Status: {status}")
    print(f"Error: {error_message}")
    print(f"Amount: {amount}")
    print(f"Machine ID: {udf1}")
    print("=" * 50)
    
    # TODO: Here you would typically:
    # 1. Log the failed transaction
    # 2. Send failure notification
    # 3. Release any reserved inventory
    
    return jsonify({
        "error": "Payment failed",
        "txnid": txnid,
        "status": status,
        "message": error_message,
        "amount": amount
    }), 400

@bp.route('/api/verify-token', methods=['POST'])
def verify_token():
    """
    Verify JWT token endpoint
    """
    try:
        data = request.json
        token = data.get('token')
        
        if not token:
            return jsonify({"error": "Token required"}), 400
        
        secret_key = os.getenv('SECRET_KEY')
        if not secret_key:
            return jsonify({"error": "Server configuration error"}), 500
        
        try:
            payload = jwt.decode(token, secret_key, algorithms=['HS256'])
            user_id = payload.get('user_id')
            
            user = User.query.get(user_id)
            if not user:
                return jsonify({"error": "User not found"}), 404
            
            return jsonify({
                'valid': True,
                'user': {
                    'id': user.id,
                    'user_id': user.user_id,
                    'username': user.username,
                    'email': user.email,
                    'roles': user.roles,
                    'user_status': user.user_status,
                    'photo': user.photo,
                    'company_logo': user.company_logo
                }
            }), 200
            
        except jwt.ExpiredSignatureError:
            return jsonify({"error": "Token expired"}), 401
        except jwt.InvalidTokenError:
            return jsonify({"error": "Invalid token"}), 401
            
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@bp.route('/api/user-login', methods=['POST'])
def user_login():
    """
    User login endpoint with proper password hashing validation
    Accepts email OR username along with password
    """
    try:
        data = request.json
        
        if not data:
            return jsonify({"error": "No data provided"}), 400
        
        identifier = data.get('email')  # Can be username or email
        password = data.get('password')

        # Validate required fields
        if not identifier or not password:
            return jsonify({"error": "Email/Username and password are required"}), 400

        # Query user by email OR username
        user = User.query.filter(
            (User.email == identifier) | (User.username == identifier)
        ).first()

        # Debug logging
        print(f"\n{'='*60}")
        print(f"LOGIN ATTEMPT")
        print(f"{'='*60}")
        print(f"Identifier provided: {identifier}")
        print(f"User found: {user is not None}")
        if user:
            print(f"User ID: {user.id}")
            print(f"Username: {user.username}")
            print(f"Email: {user.email}")
            print(f"Password hash exists: {bool(user.password)}")
            print(f"Password hash length: {len(user.password) if user.password else 0}")
        print(f"{'='*60}\n")

        # Check if user exists and password is correct
        if not user:
            print("Login failed: User not found")
            return jsonify({"error": "Invalid email/username or password"}), 401
        
        if not user.check_password(password):
            print("Login failed: Incorrect password")
            return jsonify({"error": "Invalid email/username or password"}), 401

        # Generate JWT access token
        secret_key = os.getenv('SECRET_KEY')
        if not secret_key:
            print("ERROR: SECRET_KEY not configured in .env")
            return jsonify({"error": "Server configuration error"}), 500

        try:
            token = jwt.encode({
                'user_id': user.id,
                'username': user.username,
                'email': user.email,
                'exp': datetime.utcnow() + timedelta(days=7)
            }, secret_key, algorithm='HS256')
        except Exception as e:
            print(f"JWT generation error: {e}")
            return jsonify({"error": "Token generation failed"}), 500

        print(f"✓ Login successful for user: {user.username}")
        print(f"✓ Token generated successfully\n")

        # Return successful response
        return jsonify({
            'message': 'Login successful',
            'accessToken': token,
            'user': {
                'id': user.id,
                'user_id': user.user_id,
                'username': user.username,
                'email': user.email,
                'contact': user.contact,
                'roles': user.roles,
                'user_status': user.user_status,
                'photo': user.photo,
                'company_logo': user.company_logo
            }
        }), 200

    except Exception as e:
        print(f"\n{'='*60}")
        print(f"LOGIN ERROR")
        print(f"{'='*60}")
        print(f"Error type: {type(e).__name__}")
        print(f"Error message: {str(e)}")
        
        import traceback
        print("\nFull traceback:")
        traceback.print_exc()
        print(f"{'='*60}\n")
        
        return jsonify({"error": f"Server error: {str(e)}"}), 500


@bp.route('/change-password', methods=['POST'])
def change_password():
    """
    Change user password endpoint
    Requires current password for verification
    """
    try:
        data = request.json
        user_id = data.get('user_id')
        current_password = data.get('current_password')
        new_password = data.get('new_password')
        
        if not all([user_id, current_password, new_password]):
            return jsonify({"error": "All fields required"}), 400
        
        user = User.query.get(user_id)
        if not user:
            return jsonify({"error": "User not found"}), 404
        
        # Verify current password
        if not user.check_password(current_password):
            return jsonify({"error": "Current password is incorrect"}), 401
        
        # Validate new password
        if len(new_password) < 6:
            return jsonify({"error": "New password must be at least 6 characters"}), 400
        
        # Set new password (automatically hashed)
        user.set_password(new_password)
        user.updated_at = datetime.utcnow()
        
        from app import db
        db.session.commit()
        
        print(f"Password changed successfully for user: {user.username}")
        
        return jsonify({
            'message': 'Password changed successfully'
        }), 200
        
    except Exception as e:
        print(f"Password change error: {e}")
        return jsonify({"error": str(e)}), 500


def get_current_user_from_token():
    """Extract user from Authorization header token"""
    token = None
    
    if 'Authorization' in request.headers:
        auth_header = request.headers['Authorization']
        try:
            token = auth_header.split(" ")[1]  # Bearer <token>
        except IndexError:
            return None
    
    if not token:
        return None
    
    try:
        secret_key = os.getenv('SECRET_KEY')
        data = jwt.decode(token, secret_key, algorithms=['HS256'])
        current_user = User.query.get(data['user_id'])
        return current_user
    except:
        return None


@bp.route('/dashboard-metrics', methods=['GET'])
def get_dashboard_metrics_role_based():
    """Get dashboard metrics filtered by user role"""
    try:
        # Get current user from token
        current_user = get_current_user_from_token()
        
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        user_role = current_user.roles
        filter_type = request.args.get('machine_filter', 'all')
        
        print(f"\n{'='*60}")
        print(f"DASHBOARD METRICS REQUEST")
        print(f"{'='*60}")
        print(f"User: {current_user.username}")
        print(f"Role: {user_role}")
        print(f"User ID: {current_user.id}")
        print(f"Filter: {filter_type}")
        print(f"{'='*60}\n")
        
        # ROLE-BASED FILTERING
        if user_role in ['Management', 'SuperAdmin', 'Admin']:
            # Show overall system stats
            response = get_admin_dashboard_metrics(filter_type)
        elif user_role == 'Client':
            # Show only this client's data
            response = get_Client_dashboard_metrics(current_user.id, filter_type)
        elif user_role == 'Refiller':
            # Show product/warehouse related stats
            response = get_refiller_dashboard_metrics(filter_type)
        elif user_role == 'Servicer':
            # Show machine maintenance stats
            response = get_servicer_dashboard_metrics(filter_type)
        else:
            return jsonify({'error': 'Invalid role'}), 403
        
        return jsonify(response), 200
        
    except Exception as e:
        import traceback
        print(f"\n✗ DASHBOARD ERROR")
        print(f"Error: {str(e)}")
        traceback.print_exc()
        return jsonify({'error': f'Internal server error: {str(e)}'}), 500


def get_admin_dashboard_metrics(filter_type):
    """Get metrics for Management/SuperAdmin/Admin - Overall system stats"""
    # Machine counts based on filter
    if filter_type == 'active':
        machine_count = Machine.query.filter_by(operation_status='active').count()
        machine_title = 'Active Machines'
    elif filter_type == 'inactive':
        machine_count = Machine.query.filter_by(operation_status='inactive').count()
        machine_title = 'Inactive Machines'
    else:  # 'all'
        machine_count = Machine.query.count()
        machine_title = 'All Machines'

    # Client count (users with role 'Client')
    clients = User.query.filter_by(roles='Client').count()
    
    # Company users (Admin, SuperAdmin, Management, Refiller, Servicer)
    company_users = User.query.filter(
        User.roles.in_(['Management', 'SuperAdmin', 'Admin', 'Refiller', 'Servicer'])
    ).count()

    # COUNT TRANSACTIONS AND CALCULATE SALES
    transactions_count = Transaction.query.count()
    
    # Calculate total sales (sum of all successful transaction amounts)
    from sqlalchemy import func
    total_sales = db.session.query(func.sum(Transaction.amount))\
        .filter(Transaction.status == 'Success')\
        .scalar() or 0.0

    return {
        'machine_title': machine_title,
        'machine_count': machine_count,
        'clients': clients,
        'company_users': company_users,
        'client_users': clients,
        'transactions': transactions_count,
        'sales': f'{total_sales:.2f}',
        'user_role': 'admin',
        'user_type': 'Overall System'
    }


def get_Client_dashboard_metrics(user_id, filter_type):
    """Get metrics for Client/Client - Only their own data"""
    # Get only machines belonging to this client
    if filter_type == 'active':
        machine_count = Machine.query.filter_by(
            client_id=user_id, 
            operation_status='active'
        ).count()
        machine_title = 'My Active Machines'
    elif filter_type == 'inactive':
        machine_count = Machine.query.filter_by(
            client_id=user_id, 
            operation_status='inactive'
        ).count()
        machine_title = 'My Inactive Machines'
    else:  # 'all'
        machine_count = Machine.query.filter_by(client_id=user_id).count()
        machine_title = 'My Machines'

    # For Client, clients = 1 (themselves)
    clients = 1
    
    # Company users not relevant for Client
    company_users = 0

    # GET THIS CLIENT'S TRANSACTIONS AND SALES
    # Get machine IDs for this client
    client_machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=user_id).all()]
    
    # Count transactions for this client's machines
    transactions_count = Transaction.query.filter(
        Transaction.machine_id.in_(client_machine_ids)
    ).count() if client_machine_ids else 0
    
    # Calculate sales for this client's machines
    from sqlalchemy import func
    total_sales = db.session.query(func.sum(Transaction.amount))\
        .filter(Transaction.machine_id.in_(client_machine_ids))\
        .filter(Transaction.status == 'Success')\
        .scalar() or 0.0 if client_machine_ids else 0.0

    return {
        'machine_title': machine_title,
        'machine_count': machine_count,
        'clients': clients,
        'company_users': company_users,
        'client_users': clients,
        'transactions': transactions_count,
        'sales': f'{total_sales:.2f}',
        'user_role': 'Client',
        'user_type': 'My Business'
    }


def get_refiller_dashboard_metrics(filter_type):
    """Get metrics for Refiller - Product/warehouse focused"""
    # Machines they need to service
    machine_count = Machine.query.count()
    
    # Products in warehouse
    product_count = Product.query.count()
    
    # Transaction count (all)
    transactions_count = Transaction.query.count()
    
    # Total sales
    from sqlalchemy import func
    total_sales = db.session.query(func.sum(Transaction.amount))\
        .filter(Transaction.status == 'Success')\
        .scalar() or 0.0

    return {
        'machine_title': 'Machines to Service',
        'machine_count': machine_count,
        'clients': 0,
        'company_users': 0,
        'client_users': 0,
        'transactions': transactions_count,
        'sales': f'{total_sales:.2f}',
        'product_count': product_count,
        'user_role': 'refiller',
        'user_type': 'Inventory Management'
    }


def get_servicer_dashboard_metrics(filter_type):
    """Get metrics for Servicer - Machine maintenance focused"""
    # All machines they can service
    if filter_type == 'active':
        machine_count = Machine.query.filter_by(operation_status='active').count()
        machine_title = 'Active Machines'
    elif filter_type == 'inactive':
        machine_count = Machine.query.filter_by(operation_status='inactive').count()
        machine_title = 'Machines Needing Service'
    else:
        machine_count = Machine.query.count()
        machine_title = 'Total Machines'

    # Machines needing maintenance
    maintenance_count = Machine.query.filter_by(operation_status='maintenance').count()
    
    # Transaction count (all)
    transactions_count = Transaction.query.count()
    
    # Total sales
    from sqlalchemy import func
    total_sales = db.session.query(func.sum(Transaction.amount))\
        .filter(Transaction.status == 'Success')\
        .scalar() or 0.0

    return {
        'machine_title': machine_title,
        'machine_count': machine_count,
        'clients': 0,
        'company_users': 0,
        'client_users': 0,
        'transactions': transactions_count,
        'sales': f'{total_sales:.2f}',
        'maintenance_count': maintenance_count,
        'user_role': 'servicer',
        'user_type': 'Machine Maintenance'
    }

# Additional utility routes for PayU integration

@bp.route('/verify-payu-hash', methods=['POST'])
def verify_payu_hash():
    """Utility endpoint to verify PayU hash calculation"""
    data = request.json
    
    if not data:
        return jsonify({"error": "No data provided"}), 400
    
    required_fields = ['key', 'txnid', 'amount', 'productinfo', 'firstname', 'email']
    for field in required_fields:
        if field not in data:
            return jsonify({"error": f"Missing required field: {field}"}), 400
    
    # Get UDF fields (optional)
    udf1 = data.get('udf1', '')
    udf2 = data.get('udf2', '')
    udf3 = data.get('udf3', '')
    udf4 = data.get('udf4', '')
    udf5 = data.get('udf5', '')
    
    payu_salt = os.getenv('PAYU_MERCHANT_SALT')
    if not payu_salt:
        return jsonify({"error": "PAYU_MERCHANT_SALT not configured"}), 500
    
    # Create hash string
    hash_string = f"{data['key']}|{data['txnid']}|{data['amount']}|{data['productinfo']}|{data['firstname']}|{data['email']}|{udf1}|{udf2}|{udf3}|{udf4}|{udf5}||||||{payu_salt}"
    
    # Generate hash
    calculated_hash = hashlib.sha512(hash_string.encode()).hexdigest()
    
    return jsonify({
        "hash_string": hash_string,
        "calculated_hash": calculated_hash,
        "hash_length": len(calculated_hash)
    }), 200

@bp.route('/payu-test', methods=['GET'])
def payu_test():
    """Test endpoint to verify PayU configuration"""
    payu_key = os.getenv('PAYU_MERCHANT_KEY')
    payu_salt = os.getenv('PAYU_MERCHANT_SALT')
    success_url = os.getenv('PAYU_SUCCESS_URL')
    failure_url = os.getenv('PAYU_FAILURE_URL')
    
    return jsonify({
        "payu_key": payu_key[:10] + "..." if payu_key else "Not configured",
        "payu_salt": payu_salt[:10] + "..." if payu_salt else "Not configured",
        "success_url": success_url or "Not configured",
        "failure_url": failure_url or "Not configured",
        "configuration_status": "OK" if all([payu_key, payu_salt]) else "Incomplete"
    }), 200

@bp.route('/payment-success', methods=['GET', 'POST'])
def payment_success_redirect():
    """Redirect successful payments to Android app"""
    # Get query parameters from PayU
    txnid = request.args.get('txnid') or request.form.get('txnid')
    status = request.args.get('status') or request.form.get('status')
    amount = request.args.get('amount') or request.form.get('amount')
    # ... get other parameters        
    # Create redirect URL to your Android app
    redirect_url = f"vendingmachine://payment/success?txnid={txnid}&status={status}&amount={amount}"    
    # Return HTML that automatically redirects
    return f'''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Payment Success</title>
        <script>
            window.location.href = "{redirect_url}";
            setTimeout(function() {{
                document.getElementById('fallback').style.display = 'block';
            }}, 3000);
        </script>
    </head>
    <body>
        <div style="text-align: center; padding: 50px;">
            <h2>Payment Successful!</h2>
            <p>Redirecting to app...</p>
            <div id="fallback" style="display: none;">
                <p>If app doesn't open automatically:</p>
                <a href="{redirect_url}">Open App</a>
            </div>
        </div>
    </body>
    </html>
    '''

@bp.route('/payment-failure', methods=['GET', 'POST'])
def payment_failure_redirect():
    """Redirect failed payments to Android app"""
    # Get query parameters from PayU
    txnid = request.args.get('txnid') or request.form.get('txnid')
    status = request.args.get('status') or request.form.get('status')
    error = request.args.get('error') or request.form.get('error')    
    # Create redirect URL to your Android app
    redirect_url = f"vendingmachine://payment/failure?txnid={txnid}&status={status}&error={error}"        
    return f'''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Payment Failed</title>
        <script>
        window.location.href = "{redirect_url}";
            setTimeout(function() {{
                document.getElementById('fallback').style.display = 'block';
            }}, 3000);
        </script>
    </head>
    <body>
        <div style="text-align: center; padding: 50px;">
            <h2>Payment Failed</h2>
            <p>Redirecting to app...</p>
            <div id="fallback" style="display: none;">
                <p>If app doesn't open automatically:</p>
                <a href="{redirect_url}">Open App</a>
            </div>
        </div>
    </body>
    </html>
    '''

@bp.route('/machine/connect', methods=['POST'])
def connect_machine():
    """Connect to vending machine hardware"""
    data = request.json or {}
    port = data.get('port', '/dev/ttyUSB0')  # Default Linux USB port
    baudrate = data.get('baudrate', 9600)
    
    try:
        success = serial_service.connect_to_machine(port, baudrate)
        
        if success:
            return jsonify({
                'success': True,
                'message': f'Connected to machine on {port}',
                'port': port,
                'baudrate': baudrate
            }), 200
        else:
            return jsonify({
                'success': False,
                'error': 'Failed to connect to machine',
                'message': 'Check if machine is connected and port is correct'
            }), 400
            
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'Connection error'
        }), 500

@bp.route('/machine/status', methods=['GET'])
def get_machine_status():
    """Check machine hardware status"""
    try:
        status = serial_service.check_machine_status()
        return jsonify(status), 200
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'error': str(e),
            'message': 'Failed to check machine status'
        }), 500

@bp.route('/machine/dispense', methods=['POST'])
def dispense_product():
    """Dispense product from specific slot"""
    data = request.json
    
    if not data or 'slotId' not in data:
        return jsonify({'error': 'Missing slotId parameter'}), 400
    
    slot_id = data.get('slotId')
    machine_id = data.get('machineId')
    
    print(f"=== DISPENSING REQUEST ===")
    print(f"Machine ID: {machine_id}")
    print(f"Slot ID: {slot_id}")
    print("==========================")
    
    try:
        # Send command to actual hardware
        result = serial_service.send_dispense_command(slot_id)
        
        print(f"Dispensing result: {result}")
        
        if result['success']:
            return jsonify({
                'success': True,
                'message': result['message'],
                'slot_id': slot_id,
                'hardware_response': result['response']
            }), 200
        else:
            return jsonify({
                'success': False,
                'error': result.get('error', 'Dispensing failed'),
                'message': result['message'],
                'slot_id': slot_id,
                'hardware_response': result['response']
            }), 400
            
    except Exception as e:
        print(f"Dispensing error: {e}")
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'System error during dispensing'
        }), 500

@bp.route('/machine/dispense-multiple', methods=['POST'])
def dispense_multiple_products():
    """Dispense multiple products sequentially"""
    data = request.json
    
    if not data or 'items' not in data:
        return jsonify({'error': 'Missing items parameter'}), 400
    
    items = data.get('items', [])
    machine_id = data.get('machineId')
    
    if not items:
        return jsonify({'error': 'No items to dispense'}), 400
    
    print(f"=== MULTIPLE DISPENSING REQUEST ===")
    print(f"Machine ID: {machine_id}")
    print(f"Items count: {len(items)}")
    
    results = []
    all_successful = True
    
    try:
        for item in items:
            slot_id = item.get('slotId')
            quantity = item.get('quantity', 1)
            product_name = item.get('productName', 'Unknown')
            
            print(f"Dispensing {quantity}x {product_name} from slot {slot_id}")
            
            # Dispense each quantity one by one
            for i in range(quantity):
                result = serial_service.send_dispense_command(slot_id)
                results.append({
                    'slot_id': slot_id,
                    'product_name': product_name,
                    'attempt': i + 1,
                    'total_quantity': quantity,
                    'success': result['success'],
                    'response': result['response'],
                    'message': result['message']
                })
                
                if not result['success']:
                    all_successful = False
                    print(f"Failed to dispense item {i+1} from slot {slot_id}: {result['message']}")
                    break  # Stop dispensing this item if one fails
                else:
                    print(f"Successfully dispensed item {i+1} from slot {slot_id}")
                
                # Small delay between dispensing items
                if i < quantity - 1:
                    time.sleep(0.5)
        
        return jsonify({
            'success': all_successful,
            'message': 'All products dispensed successfully' if all_successful else 'Some products failed to dispense',
            'results': results,
            'total_items': len(items),
            'successful_dispensing': sum(1 for r in results if r['success'])
        }), 200 if all_successful else 207  # 207 = Multi-Status
        
    except Exception as e:
        print(f"Multiple dispensing error: {e}")
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'System error during multiple dispensing',
            'results': results
        }), 500

@bp.route('/machine/reset', methods=['POST'])
def reset_machine():
    """Reset machine to clear error states"""
    try:
        result = serial_service.reset_machine()
        
        if result['success']:
            return jsonify({
                'success': True,
                'message': 'Machine reset successfully',
                'response': result.get('response', '')
            }), 200
        else:
            return jsonify({
                'success': False,
                'error': result.get('error', 'Reset failed'),
                'message': 'Failed to reset machine'
            }), 400
            
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'Error during machine reset'
        }), 500

@bp.route('/machine/disconnect', methods=['POST'])
def disconnect_machine():
    """Disconnect from machine hardware"""
    try:
        serial_service.disconnect()
        
        return jsonify({
            'success': True,
            'message': 'Disconnected from machine successfully'
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e),
            'message': 'Error during disconnection'
        }), 500

# Update the existing payment success route to trigger dispensing
@bp.route('/payment-confirmed', methods=['POST'])
def payment_confirmed():
    """Handle payment confirmation and trigger dispensing"""
    data = request.json
    
    machine_id = data.get('machineId')
    cart_items = data.get('cartItems', [])
    payment_type = data.get('paymentType', 'wallet')
    total_amount = data.get('totalAmount', 0)
    
    if not machine_id or not cart_items:
        return jsonify({'error': 'Missing machineId or cartItems'}), 400
    
    transaction_records = []
    
    try:
        # Create transaction records for each item
        for item in cart_items:
            transaction = TransactionService.create_transaction(
                machine_id=machine_id,
                product_name=item.get('productName', 'Unknown'),
                quantity=item.get('quantity', 1),
                amount=float(item.get('price', 0)) * int(item.get('quantity', 1)),
                payment_type=payment_type,
                status='Unprocessed'
            )
            transaction_records.append(transaction)
        
        # Attempt dispensing
        dispensing_items = []
        for item in cart_items:
            dispensing_items.append({
                'slotId': item.get('slotId'),
                'quantity': item.get('quantity', 1),
                'productName': item.get('productName', 'Unknown')
            })
        
        # Call dispensing endpoint
        dispense_result = serial_service.send_dispense_command(dispensing_items[0]['slotId'])
        
        # Update transaction statuses based on dispensing result
        for transaction in transaction_records:
            if dispense_result['success']:
                TransactionService.update_transaction_status(
                    transaction.transaction_id,
                    status='Success'
                )
            else:
                TransactionService.update_transaction_status(
                    transaction.transaction_id,
                    status='Dispense failed',
                    amount_receiving_status='Pending refund',
                    return_amount=transaction.amount
                )
        
        return jsonify({
            'success': dispense_result['success'],
            'message': 'Payment processed',
            'transactions': [t.to_dict() for t in transaction_records],
            'dispensing_result': dispense_result
        }), 200
        
    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500

@bp.route('/transactions', methods=['GET'])
def get_transactions():
    """Get all transactions with optional filters"""
    try:
        # Get current user from token
        current_user = get_current_user_from_token()
        
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Build filters from query params
        filters = {}
        
        # Role-based filtering
        if current_user.roles == 'Client':
            # Client can only see their own machines' transactions
            machine_ids = [m.machine_id for m in Machine.query.filter_by(client_id=current_user.id).all()]
            transactions = Transaction.query.filter(Transaction.machine_id.in_(machine_ids)).order_by(Transaction.created_at.desc()).all()
        else:
            # Admin/Management can see all
            if request.args.get('machine_id'):
                filters['machine_id'] = request.args.get('machine_id')
            if request.args.get('status'):
                filters['status'] = request.args.get('status')
            
            transactions = TransactionService.get_all_transactions(filters)
        
        return jsonify([t.to_dict() for t in transactions]), 200
        
    except Exception as e:
        import traceback
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500

@bp.route('/transactions/<transaction_id>', methods=['GET'])
def get_transaction(transaction_id):
    """Get single transaction details"""
    try:
        transaction = TransactionService.get_transaction_by_id(transaction_id)
        if not transaction:
            return jsonify({'error': 'Transaction not found'}), 404
        
        return jsonify(transaction.to_dict()), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@bp.route('/transactions/<transaction_id>/refund', methods=['POST'])
def refund_transaction(transaction_id):
    """Process refund for failed dispensing"""
    try:
        transaction = TransactionService.get_transaction_by_id(transaction_id)
        if not transaction:
            return jsonify({'error': 'Transaction not found'}), 404
        
        # Update transaction with refund info
        updated = TransactionService.update_transaction_status(
            transaction_id,
            status='Dispense failed',
            amount_receiving_status='Dispense failed refund',
            return_amount=transaction.amount
        )
        
        # TODO: Integrate with actual payment gateway refund API
        
        return jsonify({
            'message': 'Refund processed successfully',
            'transaction': updated.to_dict()
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@bp.route('/transactions/bulk-create', methods=['POST'])
def bulk_create_transactions():
    """Create multiple transactions at once"""
    try:
        print("\n" + "=" * 60)
        print("BULK TRANSACTION CREATION")
        print("=" * 60)
        
        data = request.json
        transactions_data = data.get('transactions', [])
        
        if not transactions_data:
            return jsonify({'error': 'No transactions provided'}), 400
        
        print(f"Creating {len(transactions_data)} transactions")
        
        created_transactions = []
        
        for trans_data in transactions_data:
            machine_id = trans_data.get('machine_id')
            product_name = trans_data.get('product_name')
            quantity = trans_data.get('quantity')
            amount = trans_data.get('amount')
            payment_type = trans_data.get('payment_type', 'cash')
            status = trans_data.get('status', 'Success')
            
            print(f"  - {product_name} x {quantity} = ₹{amount} (Machine: {machine_id})")
            
            transaction = TransactionService.create_transaction(
                machine_id=machine_id,
                product_name=product_name,
                quantity=quantity,
                amount=amount,
                payment_type=payment_type,
                status=status
            )
            created_transactions.append(transaction.to_dict())
        
        print(f"✓ {len(created_transactions)} transactions created successfully")
        print("=" * 60 + "\n")
        
        return jsonify({
            'message': 'Transactions created successfully',
            'transactions': created_transactions,
            'count': len(created_transactions)
        }), 201
        
    except Exception as e:
        print(f"\n✗ TRANSACTION CREATION ERROR")
        print(f"Error: {str(e)}")
        
        import traceback
        traceback.print_exc()
        print("=" * 60 + "\n")
        
        return jsonify({'error': str(e)}), 500

# Role Management Endpoints
@bp.route('/roles', methods=['GET'])
def get_roles():
    """Get all roles"""
    try:
        current_user = get_current_user_from_token()
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Only Management and SuperAdmin can view roles
        if current_user.roles not in ['Management', 'SuperAdmin']:
            return jsonify({'error': 'Permission denied'}), 403
        
        roles = RoleService.get_all_roles()
        return jsonify([role.to_dict() for role in roles]), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@bp.route('/roles', methods=['POST'])
def create_role():
    """Create new role"""
    try:
        current_user = get_current_user_from_token()
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Only Management and SuperAdmin can create roles
        if current_user.roles not in ['Management', 'SuperAdmin']:
            return jsonify({'error': 'Permission denied'}), 403
        
        data = request.json
        new_role = RoleService.create_role(data)
        
        return jsonify(new_role.to_dict()), 201
        
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@bp.route('/roles/<int:role_id>', methods=['PUT'])
def update_role(role_id):
    """Update existing role"""
    try:
        current_user = get_current_user_from_token()
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Only Management and SuperAdmin can update roles
        if current_user.roles not in ['Management', 'SuperAdmin']:
            return jsonify({'error': 'Permission denied'}), 403
        
        data = request.json
        updated_role = RoleService.update_role(role_id, data)
        
        return jsonify(updated_role.to_dict()), 200
        
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@bp.route('/roles/<int:role_id>', methods=['DELETE'])
def delete_role(role_id):
    """Delete role"""
    try:
        current_user = get_current_user_from_token()
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Only Management and SuperAdmin can delete roles
        if current_user.roles not in ['Management', 'SuperAdmin']:
            return jsonify({'error': 'Permission denied'}), 403
        
        RoleService.delete_role(role_id)
        
        return jsonify({'message': 'Role deleted successfully'}), 200
        
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@bp.route('/permissions', methods=['GET'])
def get_available_permissions():
    """Get all available permissions"""
    try:
        current_user = get_current_user_from_token()
        if not current_user:
            return jsonify({'error': 'Authentication required'}), 401
        
        # Only Management and SuperAdmin can view permissions
        if current_user.roles not in ['Management', 'SuperAdmin']:
            return jsonify({'error': 'Permission denied'}), 403
        
        # Define all available permissions
        permissions = [
            {'id': 'view_dashboard', 'name': 'View Dashboard', 'description': 'Access to dashboard', 'module': 'Dashboard'},
            {'id': 'view_users', 'name': 'View Users', 'description': 'Can view user listings', 'module': 'Users'},
            {'id': 'create_users', 'name': 'Create Users', 'description': 'Can create new users', 'module': 'Users'},
            {'id': 'edit_users', 'name': 'Edit Users', 'description': 'Can modify users', 'module': 'Users'},
            {'id': 'delete_users', 'name': 'Delete Users', 'description': 'Can remove users', 'module': 'Users'},
            {'id': 'view_machines', 'name': 'View Machines', 'description': 'Can view machines', 'module': 'Machines'},
            {'id': 'create_machines', 'name': 'Create Machines', 'description': 'Can add new machines', 'module': 'Machines'},
            {'id': 'edit_machines', 'name': 'Edit Machines', 'description': 'Can modify machines', 'module': 'Machines'},
            {'id': 'delete_machines', 'name': 'Delete Machines', 'description': 'Can remove machines', 'module': 'Machines'},
            {'id': 'view_products', 'name': 'View Products', 'description': 'Can view products', 'module': 'Products'},
            {'id': 'create_products', 'name': 'Create Products', 'description': 'Can add products', 'module': 'Products'},
            {'id': 'edit_products', 'name': 'Edit Products', 'description': 'Can modify products', 'module': 'Products'},
            {'id': 'delete_products', 'name': 'Delete Products', 'description': 'Can remove products', 'module': 'Products'},
            {'id': 'view_transactions', 'name': 'View Transactions', 'description': 'Can view transactions', 'module': 'Transactions'},
            {'id': 'view_reports', 'name': 'View Reports', 'description': 'Can access reports', 'module': 'Reports'},
            {'id': 'export_data', 'name': 'Export Data', 'description': 'Can export data', 'module': 'Reports'},
            {'id': 'view_roles', 'name': 'View Roles', 'description': 'Can view role listings', 'module': 'Roles'},
            {'id': 'create_roles', 'name': 'Create Roles', 'description': 'Can create new roles', 'module': 'Roles'},
            {'id': 'edit_roles', 'name': 'Edit Roles', 'description': 'Can modify roles', 'module': 'Roles'},
            {'id': 'delete_roles', 'name': 'Delete Roles', 'description': 'Can remove roles', 'module': 'Roles'},
            {'id': 'system_settings', 'name': 'System Settings', 'description': 'Can modify system configuration', 'module': 'Administration'}
        ]
        
        return jsonify(permissions), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500