from fastapi import Request, Query, Depends, Header, APIRouter, HTTPException
from fastapi.responses import JSONResponse
import pytz
import os
import json
import uuid
from datetime import datetime
from connectors.firebase.firebase import Firebase
from connectors.facebook.facebook_media import Facebook
from connectors.line.line import OA
from utility.authorization import CloudAuthorization as CAuth
from utility.authorization import TokenAuthorization
from utility.function import Function

from models.channel import *

import logging
logging.basicConfig(level=logging.INFO)
timezone_utc = pytz.utc

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

router = APIRouter()

LOGGING_PREFIX = "api_channel"

@router.post("/facebook/page/subscription", response_model=DataResponse, description="Subscribe to Facebook Page fields")
async def channel_facebook_page_subscription(default_request: Request, request: SubscriptionFacebookPage):
    local_key = default_request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    userPropertyList = userData.get('property', {})
    try:
        if str(request.property_id) not in userPropertyList:
            return {"status":"error",'message': f"You don't have access to this property {request.property_id}"}, 400
        page_obj = Facebook.get_page_obj(request.page_access_token, request.page_id)
        page_obj.create_subscribed_app(params={"subscribed_fields":request.subscribed_fields})
        page_detail = page_obj.get_subscribed_apps()
        json_data = {
            request.page_id : {
                "createdate" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "lastupdate" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "name" : page_obj.api_get(fields=['name'])['name'],
                "category" : page_detail[0]['category'],
                "link" : page_detail[0]['link'],
                "app_name" : page_detail[0]['name'],
                "subscribed_fields" : page_detail[0]["subscribed_fields"]
            }
        }
        ref = fb.db.reference(f'property/{request.property_id}/channel/facebook')
        current_fb_index = ref.get()
        if current_fb_index and str(request.page_id) in current_fb_index:
            ref.child(str(request.page_id)).update({
                "lastupdate": datetime.now(timezone_utc).strftime("%Y-%m-%d %H:%M:%S"),
                "subscribed_fields": page_detail[0]["subscribed_fields"]
            })
        else:
            ref.child(str(request.page_id)).set(json_data[request.page_id])

        fb.db.reference(f'property/{request.property_id}/lastupdate').set(datetime.now(timezone_utc).strftime("%Y-%m-%d %H:%M:%S"))
        return {"status":"ok",'message': 'Subscribed fields successfully','data':json_data}
    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.post("/line/page/subscription", description="Subscribe to LINE Official Account")
async def channel_line_page_subscription(default_request: Request, request: SubscriptionLinePage):
    user_id = Function.getUserIDFromHeaders(default_request.headers)

    now = datetime.now(timezone_utc)
    time = now.strftime('%Y-%m-%d %H:%M:%S')
    local_key = default_request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    try:
        if str(request.property_id) not in list(userData['property']):
            return JSONResponse(status_code=400,content={"status": "error", "message": 'This property is not belong to you'})
        
        # Gen ID
        id = Function.text_to_numeric_token(request.access_token)
        channelEx = fb.db.reference().child(f"property/{request.property_id}/channel/line/{id}").get(shallow=True)
        if channelEx:
            return JSONResponse(status_code=400,content={"status": "error", "message": 'This channel already created'})
        
        #Get line OA profile
        oa = OA(access_token=request.access_token)
        respone = oa.getOAProfile()
        respone_data = respone.json()
        if respone.status_code != 200:
            return JSONResponse(status_code=400,content={"status":"error",'message': "LINE Access token was wrong"})
        
        displayname, picture_url, LINE_userId = respone_data['displayName'], respone_data.get('pictureUrl', None), respone_data['userId']
        line_context = {'userId': LINE_userId,'name': displayname,'picture': picture_url,'createdate': time,'lastupdate': time}
        #Update env
        cauth = CAuth()
        c_access_token = cauth.get_access_token()
        info = cauth.get_cloud_run_service_info(access_token=c_access_token)
        actk_obj = [{
            "name": f"LINE_{id}",
            "value": request.access_token
        }]
        response_add = cauth.add_cloud_run_service_env_var(info=info, env_pack=actk_obj, access_token=c_access_token)
        if response_add.status_code != 200:
            return JSONResponse(status_code=500,content={"status":"error",'message': 'Update env var failed'})
        
        info = cauth.get_cloud_run_service_info(access_token=c_access_token)
        env_updates = {
            "LINE_CHANNEL_LIST" : LINE_userId
        }
        response_update = cauth.update_cloud_run_service_env_var(access_token=c_access_token, info=info, env_updates=env_updates)
        if response_update.status_code != 200:
            return JSONResponse(status_code=500,content={"status":"error",'message': 'update env var failed'})

        fb.db.reference().child(f"property/{request.property_id}/channel/line/{id}").set(line_context)
        
        #Set user data
        fb.db.reference().child(f"""users/{user_id}/property/{request.property_id}/channel/{id}/role""").set("owner")
        
        #Add channel to master
        masterUser = fb.get_by_child(child=f"ydm_messaging_tool/users/master")
        if masterUser:
            listUserMaster = list(masterUser)
            for user in listUserMaster:
                try:
                    jobMaster = fb.db.reference().child(f"""users/{user}/property/{request.property_id}/channel/{id}/role""").update("master")
                except:
                    jobMaster = fb.db.reference().child(f"""users/{user}/property/{request.property_id}/channel/{id}/role""").set("master")
        
        #Check LINE hook sub
        hookCode, hookContent = oa.getHookEndpoint()
        json_hookContent = json.loads(hookContent)
        #Gen webhook path
        endpoint = f"https://ydm-profile-360-907324191702.asia-southeast1.run.app/hook/line/{id}"
        if hookCode == 404:
            setHookCode, setHookC0ntent = oa.putHookEndpoint(endpoint=endpoint)
            if setHookCode == 200:
                message = f"""System integrated successfully!\nNext step, enable webhook on LINE official account console to receive data from your LINE Official Account, please contact your administrator"""
                return {"status":"ok",'message': message, "hook": endpoint}
            return JSONResponse(status_code=500,content={"status":"error",'message': f'Fail in add webhook to channel {id}\n\n{setHookC0ntent}'})
        else:
            #Message to user
            message = f"""Your LINE channel is already subscribed to a webhook. To allow this system to receive data from your LINE Official Account, please contact your administrator to update the webhook endpoint."""
            
            return {"status":"ok",'message': message, "hook": endpoint, "existing_hook": json_hookContent['endpoint']}
    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.post("/email/sender/subscription", response_model=DataResponse, description="Subscribe to Email Sender")
async def channel_email_sender_subscription(default_request: Request, request: SubscriptionEmailSender):
    local_key = default_request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    userPropertyList = userData.get('property', {})
    try:
        if str(request.property_id) not in userPropertyList:
            return JSONResponse(status_code=400, content={"status": "error", "message": f"You don't have access to this property {request.property_id}"})
        
        # Check if sender already exists
        ref = fb.db.reference(f'property/{request.property_id}/channel/email/{request.sender_id}')
        existing = ref.get()
        if existing:
            return JSONResponse(status_code=400, content={"status": "error", "message": f"Email sender {request.sender_id} already exists"})
        
        # Prepare channel data
        now = datetime.now(timezone_utc)
        time_str = now.strftime('%Y-%m-%d %H:%M:%S')
        
        channel_data = {
            "id": request.sender_id,
            "provider": request.provider,
            "display_name": request.display_name,
            "from_email": request.from_email,
            "from_name": request.from_name,
            "reply_to_email": request.reply_to_email,
            "domain": request.domain,
            "status": request.status,
            "createdate": time_str,
            "lastupdate": time_str,
        }
        
        # Add provider-specific fields
        if request.provider == "gmail":
            if request.smtp_server:
                channel_data["smtp_server"] = request.smtp_server
            if request.smtp_port:
                channel_data["smtp_port"] = request.smtp_port
            if request.smtp_username:
                channel_data["smtp_username"] = request.smtp_username
            if request.smtp_password:
                channel_data["smtp_password"] = request.smtp_password
            if request.encryption:
                channel_data["encryption"] = request.encryption
        elif request.provider == "thaibulksms":
            if request.api_key:
                channel_data["api_key"] = request.api_key
            if request.api_secret:
                channel_data["api_secret"] = request.api_secret
        
        # Store in Firebase
        ref.set(channel_data)
        
        # Update property lastupdate
        fb.db.reference(f'property/{request.property_id}/lastupdate').set(time_str)
        
        return {"status": "ok", "message": "Email sender subscribed successfully", "data": channel_data}
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_email_sender_subscription: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})

@router.post("/sms/sender/subscription", response_model=DataResponse, description="Subscribe to SMS Sender")
async def channel_sms_sender_subscription(default_request: Request, request: SubscriptionSMSSender):
    local_key = default_request.headers.get('Authorization')
    bearer = local_key.replace("Bearer ", "")
    userAuth = TokenAuthorization(access_token=bearer)
    userData = userAuth.validate()
    userPropertyList = userData.get('property', {})
    try:
        if str(request.property_id) not in userPropertyList:
            return JSONResponse(status_code=400, content={"status": "error", "message": f"You don't have access to this property {request.property_id}"})
        
        # Check if sender already exists
        ref = fb.db.reference(f'property/{request.property_id}/channel/sms/{request.sender_id}')
        existing = ref.get()
        if existing:
            return JSONResponse(status_code=400, content={"status": "error", "message": f"SMS sender {request.sender_id} already exists"})
        
        # Prepare channel data
        now = datetime.now(timezone_utc)
        time_str = now.strftime('%Y-%m-%d %H:%M:%S')
        
        channel_data = {
            "id": request.sender_id,
            "provider": request.provider,
            "display_name": request.display_name,
            "sender_value": request.sender_value,
            "type": request.type,
            "country": request.country,
            "status": request.status,
            "createdate": time_str,
            "lastupdate": time_str,
        }
        
        # Add provider-specific fields
        if request.provider == "thaibulksms":
            if request.api_key:
                channel_data["api_key"] = request.api_key
            if request.api_secret:
                channel_data["api_secret"] = request.api_secret
        
        # Store in Firebase
        ref.set(channel_data)
        
        # Update property lastupdate
        fb.db.reference(f'property/{request.property_id}/lastupdate').set(time_str)
        
        return {"status": "ok", "message": "SMS sender subscribed successfully", "data": channel_data}
    except Exception as e:
        logging.error(f"Error parsing {LOGGING_PREFIX}_sms_sender_subscription: {e}")
        return JSONResponse(status_code=500, content={'status': 'error', 'message': str(e)})
