from flask import Flask, request, render_template, redirect, url_for, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, timedelta
from scapy.all import ARP, Ether, srp

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///whitelist.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.secret_key = 'supersecretkey'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=5)
db = SQLAlchemy(app)

class Whitelist(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(255), unique=True, nullable=False)

class Request(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(255), nullable=False)
    reason = db.Column(db.String(255), nullable=False)
    status = db.Column(db.String(50), nullable=False, default='pending')
    timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    mac_address = db.Column(db.String(17), nullable=False)
    ip_address = db.Column(db.String(45), nullable=False)

class Admin(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    password = db.Column(db.String(255), nullable=False)



def get_mac_address(ip_address):
    try:
        # Create an ARP request packet
        arp_request = ARP(pdst=ip_address)
        # Create an Ethernet frame to encapsulate the ARP request
        ether = Ether(dst="ff:ff:ff:ff:ff:ff")
        # Combine the Ethernet frame and ARP request
        packet = ether / arp_request
        # Send the packet and capture the response
        result = srp(packet, timeout=3, verbose=False)[0]
        # Extract the MAC address from the response
        mac_address = result[0][1].hwsrc
        return mac_address
    except Exception as e:
        print(f"Error getting MAC address: {e}")
        return "00:00:00:00:00:00"

@app.route('/set_admin_password', methods=['GET', 'POST'])
def set_admin_password():
    if Admin.query.first():
        return redirect(url_for('admin_login'))
    if request.method == 'POST':
        password = request.form['password']
        hashed_password = generate_password_hash(password)
        new_admin = Admin(password=hashed_password)
        db.session.add(new_admin)
        db.session.commit()
        return redirect(url_for('admin_login'))
    return render_template('set_admin_password.html')

@app.route('/admin_login', methods=['GET', 'POST'])
def admin_login():
    if request.method == 'POST':
        password = request.form['password']
        admin = Admin.query.first()
        if admin and check_password_hash(admin.password, password):
            session['admin_logged_in'] = True
            session.permanent = True  # Mark the session as permanent
            return redirect(url_for('admin'))
        else:
            return "Invalid password"
    return render_template('admin_login.html')

@app.route('/admin_logout')
def admin_logout():
    session.pop('admin_logged_in', None)
    return redirect(url_for('admin_login'))

@app.route('/admin', methods=['GET', 'POST'])
def admin():
    if not session.get('admin_logged_in'):
        return redirect(url_for('admin_login'))
    if request.method == 'POST':
        action = request.form['action']
        url = request.form['url']
        req = Request.query.filter_by(url=url).first()
        if req:
            if action == 'approve':
                req.status = 'approved'
                if not Whitelist.query.filter_by(url=url).first():
                    new_whitelist = Whitelist(url=url)
                    db.session.add(new_whitelist)
            elif action == 'reject':
                req.status = 'rejected'
                whitelist_entry = Whitelist.query.filter_by(url=url).first()
                if whitelist_entry:
                    db.session.delete(whitelist_entry)
            elif action == 'revoke':
                req.status = 'revoked'
                whitelist_entry = Whitelist.query.filter_by(url=url).first()
                if whitelist_entry:
                    db.session.delete(whitelist_entry)
            db.session.commit()
        return redirect(url_for('admin'))
    requests = Request.query.all()
    whitelist = Whitelist.query.all()
    return render_template('admin.html', requests=requests, whitelist=whitelist)

@app.route('/whitelist', methods=['GET'])
def get_whitelist():
    whitelist = Whitelist.query.all()
    return {"whitelist": [entry.url for entry in whitelist]}

@app.route('/', methods=['GET', 'POST'])
def request_whitelist():
    if request.method == 'POST':
        url = request.form['url']
        reason = request.form['reason']
        ip_address = request.remote_addr
        mac_address = get_mac_address(ip_address)
        new_request = Request(url=url, reason=reason, mac_address=mac_address, ip_address=ip_address)
        db.session.add(new_request)
        db.session.commit()
        return redirect(url_for('request_whitelist'))
    return render_template('request.html')

if __name__ == '__main__':
    with app.app_context():
        db.create_all()

    app.run(debug=True)