import json
import logging

from datetime import datetime
from flask import Blueprint, request, session
from flask_jwt_extended import jwt_required
from median.models import Rights, Profil
from median.constant import DEFAULT_PROFILS, CUSTOM_PROFILS
from common.models import WebLogActions
from common.status import HTTP_200_OK, HTTP_204_NO_CONTENT
from peewee import JOIN

rights_blueprint = Blueprint('rights', __name__)

logger = logging.getLogger('median')


@rights_blueprint.route('all', methods=['GET'])
@jwt_required()
def get_all_rights():
    req = (Rights.select(Rights.ressource.alias('ressource'), Rights.group.alias('group'))
           .where(Rights.group.is_null(False)))
    return {'list': [{
        'resource': i.ressource,
        'group': i.group,
        # 'add': 0,
        # 'edit': 0,
        # 'delete': 0,
        # 'visu': 0
    } for i in req]}, HTTP_200_OK


# Helper function for save_right
def process_right(data):
    logging.info(f"Processing right with data: {data}")

    # Validate required fields
    required_fields = ['mode', 'resource', 'profil', 'valeur']
    for field in required_fields:
        if field not in data:
            raise ValueError(f"Missing required field: {field}")

    _mode = data['mode']
    _resource = data['resource']
    _profile = data['profil']
    _value = data['valeur']
    profile = (Profil.select(Profil)
               .where((Profil.ressource == _resource) & (Profil.profil == _profile))
               .get_or_none())

    new_profile = False
    if profile is None:
        profile = Profil()
        profile.ressource = _resource
        profile.profil = _profile
        new_profile = True

    if _mode == 'visu':
        profile.visu = _value
    elif _mode == 'edit':
        profile.edit = _value
    elif _mode == 'delete':
        profile.supp = _value
    elif _mode == 'add':
        profile.add = _value
    else:
        raise ValueError(f"invalid mode: {_mode}")

    try:
        profile.save()
        if new_profile:
            log_groups(session['username'], 'create_rights',
                       f'Created new rights profile (pk: {profile.pk} - name: {profile.profil})')

    except Exception as e:
        logging.error(f"Failed to save profile: {e}")
        raise


@rights_blueprint.route('', methods=['PUT'])
# @jwt_required()
def save_right():
    data = json.loads(request.data)

    if isinstance(data, list):
        for item in data:
            process_right(item)
    else:
        process_right(data)

    return {}, HTTP_204_NO_CONTENT


@rights_blueprint.route('<string:profil_id>', methods=['GET'])
@jwt_required()
def get_profil(profil_id):
    # TODO: This receives not an ID but the profile name. It should be an ID.
    # CUSTOM_PROFILS means "customer"

    profile_name = profil_id  # see todo comment

    req = (Rights.select(Profil.cree.alias('cree'),
                         Profil.profil.alias('profil'),
                         Profil.edit.alias('edit'), Profil.visu.alias('visu'),
                         Profil.supp.alias('supp'), Rights.ressource.alias('ressource'),
                         Rights.group.alias('group'))
           .join(Profil, JOIN.LEFT_OUTER,
                 on=(Rights.ressource == Profil.ressource) & (Profil.profil == profile_name))
           .where((Rights.group.is_null(False))))
    return {'list': [{
        'resource': i.ressource,
        'group': i.group,
        'label': i.profil,
        'add': i.cree,
        'edit': i.edit,
        'delete': i.supp,
        'visu': i.visu} for i in req.objects()],
        'default_profile': profile_name in DEFAULT_PROFILS + CUSTOM_PROFILS}, HTTP_200_OK


def log_groups(username: str, action: str, message: str):
    """
    Add new log for Groupe

    :param username: User made the action to log
    :param action:
    :param message: message to log
    """
    logger.info('Groups[%s](%s)): %s' % (action, username, message))
    wlog = WebLogActions()
    wlog.chrono = datetime.now()
    wlog.username = username
    wlog.equipement_type = ''
    wlog.action = action
    wlog.message = message
    wlog.save()
