from models.configs.core import logger, request, InvalidUsage, make_response, app, url_for, redirect
from models.dbmodels.messaging_model import *
from models.libs.api import curl
from models.libs.jwt import decodejwt, get_userinfo
from models.libs.pusher import *
from datetime import datetime
import os
import ast
userData = {}

class Channels():

    def get_all_channels():
        try:
            userInfo = dict(decodejwt()['user'])
            channels = ChannelModel.query.filter_by(uid = userInfo['auth_id']).all()
            if channels is None:
                return make_response({
                    "messages": []
                })

            return {
                "message": channel_models_scheme.dump(channels)[::-1]
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))

    def get_all_channel_messages(channel_id = ''):
        try:
            userInfo = dict(decodejwt()['user'])
            chat_messages = MessagesModel.query.filter_by(channel_id = channel_id).first()
            if chat_messages is None:
                return make_response({
                    "messages": []
                })

            messages = messages_models_scheme.dump(chat_messages)
            return {
                "message": messages[::-1]
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))
        
    def check_users_exists(users):
        try:
            resp = {}
            for user in users:
                resp[user['uid']] = get_userinfo(user)
                
        except Exception as e:
            raise Exception(str(e))
           
    def notify_users(users, channel_info, msg):
        try:
            isNotified = {}
            for user in users:
                isNotified[user['uid']] = send_event_to_channel(
                   f"private_encrypted_{user['uid']}_channel", msg, channel_info
                )
            print(isNotified)

        except Exception as e:
            print(e)
            raise Exception(str(e))
    
    def create_channel():
        try:
            user = dict(decodejwt()['user'])

            id = datetime.now().strftime("%Y%m%d%H%M%S")
            uid = user['auth_id']
            channel_id = f"private_encrypted_{id}"
            date = datetime.utcnow()

            channel_name = request.json['channel_name']
            description = request.json['description']
            image = request.json['image']
            users = request.json['users']

            Channels.check_users_exists(users)

            channelinfo = ChannelModel(
                channel_id = channel_id,
                channel_name = channel_name,
                description = description,
                uid = uid,
                date_added = date,
                updated_on = date,
                image = image,
                users = str(users),
            )
            db.session.add(channelinfo)
            db.session.commit()
            db.session.close()

            Channels.notify_users(users, {
                "channel_name": channel_name,
                "channel_id": channel_id
            }, "New chat channel created")
            
            return {
                "message": "channel created"
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))
        
    def delete_channel(channel_id):
        try:
            userInfo = dict(decodejwt()['user'])
            channel_info = ChannelModel.query.filter_by(channel_id = channel_id, uid = userInfo['auth_id']).first()
            chat_messages = MessagesModel.query.filter_by(channel_id = channel_id).first()
            if channel_info is None:
                return make_response({
                    "error": "invalid channel id"
                })

            users = ast.literal_eval(channel_info.users)
            channel_name = channel_info.channel_name
            channel_id = channel_info.channel_id

            db.session.delete(chat_messages)
            db.session.delete(channel_info)
            db.session.commit()
            db.session.close()

            Channels.notify_users(users, {
                "channel_name": channel_name,
                "channel_id": channel_id
            }, "Channel deleted")
            return {
                "message": "channel deleted"
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))
        
    def update_channel(channel_id):
        try:
            user = dict(decodejwt()['user'])

            uid = user['auth_id']
            date = datetime.utcnow()

            channel_name = request.json['channel_name']
            description = request.json['description']
            image = request.json['image']
            users = request.json['users']

            Channels.check_users_exists(users)

            channel_info = ChannelModel.query.filter_by(channel_id = channel_id, uid = userInfo['auth_id']).first()
            if channel_info is None:
                return make_response({
                    "error": "invalid channel id"
                })

            update_type = ""
            if channel_info.users != str(users):
                update_type = "users info updated"
                channel_info.users = str(users)

            if channel_info.channel_name != channel_name:
                update_type = "name change"
                channel_info.channel_name = channel_name

            if channel_info.description != description:
                update_type = "description changed"
                channel_info.description = description

            if channel_info.image != image:
                update_type = "channel image changed"
                channel_info.image = image

            db.session.add(channel_info)
            db.session.commit()
            db.session.close()

            Channels.notify_users(users, {
                "channel_name": channel_name,
                "channel_id": channel_id
            }, update_type)

            return {
                "message": "channel updated"
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))


class Messaging():
    def save_and_send_chat_messages():
        try:
            return {
                "message": "New message saved"
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))

    def delete_message(id):
        try:
            return {
                "message": "Message deleted"
            }
        except exc.SQLAlchemyError as e:
            raise Exception(e._message)
        except Exception as e:
            raise Exception(str(e))