from flask import Blueprint, render_template
from .functions.Fpost import Fpost;
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from config import Config
from flask import jsonify,request

main = Blueprint('main', __name__)

@main.route('/sgiveadmin',methods=['POST','GET'])
def giveadmin():
    data=request.get_json()
    print(data)
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'superadmin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    
    res=f.giveadmin(data['targetid'])
    if not res:
        return jsonify({'status': 'error', 'message': 'User not found'})
    
    return jsonify({'status': 'success', 'message': 'User role updated to admin'})

@main.route('/sgiveuser',methods=['POST','GET'])
def giveuser():
    data=request.get_json()
    print(data)
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'superadmin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    
    res=f.giveuser(data['targetid'])
    if not res:
        return jsonify({'status': 'error', 'message': 'User not found'})
    
    return jsonify({'status': 'success', 'message': 'User role updated to user'})


@main.route('/sgivesuperadmin',methods=['POST','GET'])
def givesuperadmin():
    data=request.get_json()
    print(data)
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'superadmin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    
    res=f.givesuperadmin(data['targetid'])
    if not res:
        return jsonify({'status': 'error', 'message': 'User not found'})
    
    return jsonify({'status': 'success', 'message': 'User role updated to superadmin'})

@main.route('/sgetuserlist',methods=['POST','GET'])
def userlist():
    data=request.get_json()
    print(data)
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'superadmin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    res=f.getuserlist()
    respons=[]
    for datai in res:
        respons.append({
            'id': datai[0],
            'username': datai[1],
            'role': datai[2]
        })
    return jsonify(respons)

@main.route('/apostlist',methods=['POST','GET'])
def postlist():
    data=request.get_json()
    print(data)
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'admin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    res=f.getlist()
    respons=[]
    for datai in res:
        respons.append({
            'id': datai[0],
            'title': datai[1],
            'status': datai[2]
        })
    return jsonify(respons)

@main.route('/agetpost',methods=['POST','GET'])
def post():
    data=request.get_json()
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'admin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    res=f.getpost(data['postid'])

    return jsonify(res.to_dict() if res else {})

@main.route('/areview',methods=['POST','GET'])
def review():
    data=request.get_json()
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'admin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    
    res=f.review(data['postid'],data['status'])
    if not res:
        return jsonify({'status': 'error', 'message': 'Post not found'})
    
    return jsonify({'status': 'success', 'message': 'Post reviewed successfully'})



@main.route('/nginxauth',methods=['POST','GET'])
def nginxauth():
    data=request.get_json()
    engine=create_engine(Config.SQLURL)
    SessionLocal = sessionmaker(bind=engine)
    session = SessionLocal()
    f=Fpost(session)
    checres=f.checkid(data['userid'],'admin')
    if(not checres):
        return jsonify({'status': 'error', 'message': 'Unauthorized'})
    
    res=f.nginxauth(data['postid'],data['status'])
    if not res:
        return jsonify({'status': 'error', 'message': 'Post not found'})
    
    return jsonify({'status': 'success', 'message': 'Nginx auth updated successfully'})