from fastapi import Request, Query, Depends, Header, APIRouter, HTTPException
from fastapi.responses import JSONResponse
import pytz
import os
import uuid
from datetime import datetime, timedelta
from connectors.firebase.firebase import Firebase
import utility.function as func
from connectors.bigquery.bq import BigQuery

from models.offline_data import *

import logging
logging.basicConfig(level=logging.INFO)
timezone_utc = pytz.utc
timezone_bkk = pytz.timezone('Asia/Bangkok')

fb = Firebase(host=os.environ.get("FIREBASE_HOST"))

router = APIRouter()

LOGGING_PREFIX = "api_offline_event"

@router.post("/manage", description="Manage offline events")
async def post_manage_offline_event(request: ManageOfflineEventRequest, default_request: Request):
    try:
        property_id = request.property_id
        table_id = request.table_name
        event_name = request.event_name

        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 JSONResponse(status_code=404, content={"status":"error",'message': f"Event {event_name} already existed in {table_id}"})
        else:
            if event_datetime:
                event_details = {}
                if request.event_filter not in (None, [], ""):
                    event_details["event_filter"] = request.event_filter

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

                event_details["createDate"] = datetime.now(timezone_bkk).strftime("%Y-%m-%d %H:%M:%S")
                event_details["updateDate"] = datetime.now(timezone_bkk).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 JSONResponse(status_code=200, content={"status":"ok",'message': f'Insert event {event_name} to {table_id} successfully'})
            else:
                return JSONResponse(status_code=404, content={"status":"error",'message': f"Datetime column in {table_id} doesn't exist"})
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_{default_request.path_params}: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})

@router.get("/manage", response_model=DataResponse, description="Get managed offline event details")
async def get_manage_offline_event(
    property_id: str = Query(..., description="Property ID"),
    table_name: str = Query(..., description="Offline Table Name"),
    event_name: str = Query(..., description="Event Name"),
    default_request: Request = None
):
    try:
        event_data = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_name}/event_mapping/{event_name}").get()
        if event_data:
            return JSONResponse(status_code=200, content={"status":"ok", 'message': 'Success', 'data': event_data})
        else:
            return JSONResponse(status_code=404, content={"status":"error",'message': f"Event {event_name} not found in {table_name}"})
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_{default_request.path_params}: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})

@router.put("/manage", description="Update managed offline event details")
async def put_manage_offline_event(request: ManageOfflineEventRequest, default_request: Request):
    try:
        property_id = request.property_id
        table_id = request.table_name
        event_name = request.event_name
        event_filter = request.event_filter
        event_property = request.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_bkk).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 JSONResponse(status_code=200, content={"status":"ok",'message': f'Update event {event_name} to {table_id} successfully'})
                return JSONResponse(status_code=404, content={"status":"error",'message': f"Datetime column in {table_id} doesn't exist"})
            return JSONResponse(status_code=404, content={"status":"error",'message': f"Event {event_name} not found in {table_id}"})
        
        return JSONResponse(status_code=400, content={"status":"error",'message': f"Table {table_id} is not empty, event cannot be updated"})
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_{default_request.path_params}: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})

@router.delete("/manage", description="Delete managed offline event")
async def delete_manage_offline_event(request: ManageOfflineEventRequest, default_request: Request):
    try:
        if request.table_name == 'all':
            fb.db.reference(f"property/{request.property_id}/offline_mapping/offline_{request.table_name}/event_mapping").delete()
            return JSONResponse(status_code=200, content={"status":"ok",'message': f'All events deleted from {request.table_name} successfully'})
        
        else:
            check_exist = fb.db.reference(f"property/{request.property_id}/offline_mapping/offline_{request.table_name}/event_mapping/{request.event_name}").get()
            
            if check_exist:
                fb.db.reference(f"property/{request.property_id}/offline_mapping/offline_{request.table_name}/event_mapping/{request.event_name}").delete()
                return JSONResponse(status_code=200, content={"status":"ok",'message': f'Event {request.event_name} deleted from {request.table_name} successfully'})
            else:
                return JSONResponse(status_code=404, content={"status":"error",'message': f"Event {request.event_name} not found in {request.table_name}"})
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_{default_request.path_params}: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})

@router.get("/list", description="Get list of offline events in a table")
async def get_list_offline_event(
    property_id: str = Query(..., description="Property ID"),
    table_name: str = Query(..., description="Offline Table Name"),
    default_request: Request = None
):
    try:
        event_data = fb.db.reference(f"property/{property_id}/offline_mapping/offline_{table_name}/event_mapping").get()
        if event_data:
            return JSONResponse(status_code=200, content={"status":"ok", 'message': 'Success', 'data': event_data})
        else:
            return JSONResponse(status_code=404, content={"status":"error",'message': f"No events found in {table_name}"})
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_{default_request.path_params}: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})