from flask import Blueprint, request, Response
import logging
import uuid
import pytz
import json

import pandas as pd
import numpy as np
from google.cloud import bigquery
from firebase.firebase import Firebase
from collections import Counter
from datetime import datetime
from bigquery.bq import BigQuery, Schema
from utility.function import Function, Pack, Key, Profile
from utility.token import Token
from utility.authorization import TokenAuthorization
logging.basicConfig(level=logging.INFO)

schema_event = Blueprint('schema_event', __name__, url_prefix='/schema/event')
fb = Firebase(host="https://ydm-profile-360-default-rtdb.asia-southeast1.firebasedatabase.app/")
timezone = pytz.timezone('Asia/Bangkok')

@schema_event.route('/manage', methods=['GET', 'POST', 'PUT', 'DELETE'])
def manage_event():
    local_key = request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    
    if request.method == 'POST':
        data = request.get_json()
        for req in ['event_name','property_id','table_name']:
            if req not in data:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        property_id = data.get('property_id')
        table_id = data.get('table_name')
        event_name = data.get('event_name')
        event_filter = data.get('event_filter',[])
        event_property = data.get('event_property',[])
        event_datetime = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/date_column").get()
        
        check_exist = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").get()

        if check_exist:
            return {"status":"error",'message': f"Event {event_name} already existed in {table_id}"}, 404
        else:
            if event_datetime:
                event_details = {}
                if event_filter not in (None, [], ""):
                    event_details["event_filter"] = event_filter

                if event_property not in (None, [], ""):
                    event_details["event_property"] = event_property

                event_details["createDate"] = datetime.now(timezone).strftime("%Y-%m-%d %H:%M:%S")
                event_details["updateDate"] = datetime.now(timezone).strftime("%Y-%m-%d %H:%M:%S")
                
                fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").set(event_details)
                return {"status":"ok",'message': 'Success', 'data': f'Insert event {event_name} to {table_id} successfully'}, 200
            else:
                return {"status":"error",'message': f"Datetime column in {table_id} doesn't exist"}, 404
            
    
    elif request.method == 'GET':
        param = request.args
        for req in ['event_name','property_id','table_name']:
            if req not in param:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        property_id = request.args.get('property_id')
        table_id = request.args.get('table_name')
        event_name = request.args.get('event_name')
        
        event_data = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").get()
        
        if event_data:
            return {"status":"ok", 'message': 'Success', 'data': event_data}, 200
        else:
            return {"status":"error",'message': f"Event {event_name} not found in {table_id}"}, 404
        
    elif request.method == 'PUT':
        data = request.get_json()
        
        for req in ['event_name','property_id','table_name']:
            if req not in data:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        property_id = data.get('property_id')
        table_id = data.get('table_name')
        event_name = data.get('event_name')
        event_filter = data.get('event_filter',[])
        event_property = data.get('event_property',[])
        event_datetime = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/date_column").get()
        row_count = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/row_count").get()
        
        check_exist = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").get()
        
        if row_count == 0:
            if check_exist:
                if event_datetime:
                    event_details = {}
                    if event_filter not in (None, [], ""):
                        event_details["event_filter"] = event_filter

                    if event_property not in (None, [], ""):
                        event_details["event_property"] = event_property

                    createDate = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}/createDate").get()
                    event_details["createDate"] = createDate
                    event_details["updateDate"] = datetime.now(timezone).strftime("%Y-%m-%d %H:%M:%S")
                    
                    fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").set(event_details)
                    
                    return {"status":"ok",'message': 'Success', 'data': f'Update event {event_name} to {table_id} successfully'}, 200
                return {"status":"error",'message': f"Datetime column in {table_id} doesn't exist"}, 404
            return {"status":"error",'message': f"Event {event_name} not found in {table_id}"}, 404
        
        return {"status":"error",'message': f"Table {table_id} is not empty, event cannot be updated"}, 400
    
    elif request.method == 'DELETE':
        param = request.args
        for req in ['event_name','property_id','table_name']:
            if req not in param:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        property_id = request.args.get('property_id')
        table_id = request.args.get('table_name')
        event_name = request.args.get('event_name')
        
        if table_id == 'all':
            fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping").delete()
            return {"status":"ok",'message': f'All events deleted from {table_id} successfully'}, 200
        
        else:
            check_exist = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").get()
            
            if check_exist:
                fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_id}/event_mapping/{event_name}").delete()
                return {"status":"ok",'message': f'Event {event_name} deleted from {table_id} successfully'}, 200
            else:
                return {"status":"error",'message': f"Event {event_name} not found in {table_id}"}, 404
        
    return {"status":"error",'message': "Method not allowed"}, 405

@schema_event.route('/list', methods=['GET'])
def list_event():
    local_key = request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    
    if request.method == 'GET':
        param = request.args
        for req in ['property_id','table_name']:
            if req not in param:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        property_id = request.args.get('property_id')
        table_name = request.args.get('table_name')
        
        all_event = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_name}/event_mapping").get()
        
        if all_event:
            return {"status":"ok", 'message': 'Success', 'data': all_event}, 200
        
        return {"status":"error",'message': f"No events found in {table_name}"}, 404
    return {"status":"error",'message': "Method not allowed"}, 405