import os
import sys

from flask import Flask
import jsonify
import requests
import datetime
import base64
import hmac
import hashlib
import json
from flask_sqlalchemy import SQLAlchemy
import os
basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
db = SQLAlchemy()

# Configuration


SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'app.db')

app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev_secret_key_change_in_production')
app.config['JWT_EXPIRATION_DELTA'] = datetime.timedelta(hours=24)

# Use SQLite for development
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///bcib.sqlite'
# app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///license_plate_system.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# Initialize extensions
db.init_app(app)

# Simple JWT implementation without cryptography dependency
def create_token(payload):
    """Create a simple JWT token without cryptography dependency"""
    # Create header
    header = {'alg': 'HS256', 'typ': 'JWT'}
    header_json = json.dumps(header, separators=(',', ':')).encode()
    header_b64 = base64.urlsafe_b64encode(header_json).decode().rstrip('=')
    
    # Create payload
    payload_json = json.dumps(payload, separators=(',', ':')).encode()
    payload_b64 = base64.urlsafe_b64encode(payload_json).decode().rstrip('=')
    
    # Create signature
    signature_message = f"{header_b64}.{payload_b64}".encode()
    signature = hmac.new(
        app.config['SECRET_KEY'].encode(),
        signature_message,
        hashlib.sha256
    ).digest()
    signature_b64 = base64.urlsafe_b64encode(signature).decode().rstrip('=')
    
    # Return token
    return f"{header_b64}.{payload_b64}.{signature_b64}"

def verify_token(token):
    """Verify a simple JWT token without cryptography dependency"""
    try:
        # Split token
        header_b64, payload_b64, signature_b64 = token.split('.')
        
        # Verify signature
        signature_message = f"{header_b64}.{payload_b64}".encode()
        expected_signature = hmac.new(
            app.config['SECRET_KEY'].encode(),
            signature_message,
            hashlib.sha256
        ).digest()
        expected_signature_b64 = base64.urlsafe_b64encode(expected_signature).decode().rstrip('=')
        
        if signature_b64 != expected_signature_b64:
            return None
        
        # Decode payload
        payload_json = base64.urlsafe_b64decode(payload_b64 + '=' * (4 - len(payload_b64) % 4)).decode()
        payload = json.loads(payload_json)
        
        # Check expiration
        if 'exp' in payload and datetime.datetime.fromtimestamp(payload['exp']) < datetime.datetime.utcnow():
            return None
        
        return payload
    except Exception:
        return None

# Add custom JWT functions to app context
app.create_token = create_token
app.verify_token = verify_token

# Authentication middleware
@app.before_request
def authenticate():
    # Skip authentication for public endpoints
    if request.path == '/' or request.path.startswith('/static/'):
        return
    
    # Skip authentication for login endpoint
    if request.path == '/api/auth/login' and request.method == 'POST':
        return
    
    # Check for token
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return
    
    token = auth_header.split(' ')[1]
    payload = app.verify_token(token)
    
    if payload:
        # Store user info in request context
        request.user_id = payload.get('user_id')
        request.username = payload.get('username')
    else:
        # Invalid token, but we'll let the route handle authorization
        pass

# Register blueprints
#app.register_blueprint(camera_bp, url_prefix='/api/cameras')
#app.register_blueprint(list_bp, url_prefix='/api/lists')
#app.register_blueprint(user_bp, url_prefix='/api/users')
#app.register_blueprint(notification_bp, url_prefix='/api/notifications')
#app.register_blueprint(search_bp, url_prefix='/api/search')
#app.register_blueprint(export_bp, url_prefix='/api/export')

# Create a custom auth blueprint to replace the one using PyJWT
from flask import Blueprint, request, jsonify
#from src.models.user import User, SystemLog
from datetime import datetime, timedelta

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/login', methods=['POST'])
def login():
    """Login a user and return a JWT token"""
    data = request.json
    
    if not data or not data.get('username') or not data.get('password'):
        return jsonify({'error': 'Username and password are required'}), 400
    
    user = User.query.filter_by(username=data.get('username')).first()
    
    if not user or not user.check_password(data.get('password')):
        return jsonify({'error': 'Invalid username or password'}), 401
    
    if not user.is_active:
        return jsonify({'error': 'User account is inactive'}), 403
    
    # Update last login time
    user.last_login = datetime.utcnow()
    
    # Log the login action
    log = SystemLog(
        user_id=user.id,
        action='login',
        description='User logged in',
        ip_address=request.remote_addr,
        user_agent=request.headers.get('User-Agent', '')
    )
    
    db.session.add(log)
    db.session.commit()
    
    # Generate JWT token using our custom function
    exp_time = datetime.utcnow() + timedelta(hours=24)
    token = app.create_token({
        'user_id': user.id,
        'username': user.username,
        'exp': exp_time.timestamp()
    })
    
    return jsonify({
        'token': token,
        'user': user.to_dict(include_roles=True)
    }), 200

app.register_blueprint(auth_bp, url_prefix='/api/auth')

@app.route('/')
def index():
    return jsonify({
        'name': 'License Plate Recognition System API',
        'version': '1.0.0',
        'status': 'running'
    })

@app.errorhandler(404)
def not_found(error):
    return jsonify({'error': 'Not found'}), 404

@app.errorhandler(500)
def server_error(error):
    return jsonify({'error': 'Server error'}), 500

# Create database tables
with app.app_context():
    # Import all models to ensure they are registered with SQLAlchemy
   
    db.create_all()
    
    # Check if admin role exists, if not create initial data
   # admin_role = ()
   # if not admin_role:
        # Create roles
   #     admin_role = (name='admin', description='Administrator')
   #     operator_role = (name='operator', description='Operator')
  #      viewer_role = (name='viewer', description='Viewer')
        
  #      db.session.add_all([admin_role, operator_role, viewer_role])
  #      db.session.commit()
        
        # Create permissions
   #     permissions = [
    #        Permission(name='manage_cameras', description='Manage cameras and streams'),
   #         Permission(name='manage_lists', description='Manage whitelist and blacklist'),
    #        Permission(name='manage_users', description='Manage users and roles'),
   #         Permission(name='view_recognitions', description='View recognitions'),
   #         Permission(name='export_data', description='Export data to PDF and Excel')
  #      ]
        
  #      db.session.add_all(permissions)
   #     db.session.commit()
        
   # 

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
