from flask import Blueprint, request, jsonify
import logging
import pytz
import uuid
import os
import json
import requests
from datetime import datetime
from firebase.firebase import Firebase
from utility.function import Function
from utility.authorization import TokenAuthorization
from utility.bucketstorage import Storage
from utility.adminPhoneService import (get_admin_phones, add_admin_phones, replace_admin_phones, remove_admin_phones)
from werkzeug.utils import secure_filename

from utility.authorization import CloudAuthorization as CAuth
from utility.authorization import TokenAuthorization

logging.basicConfig(level=logging.INFO)

property = Blueprint('property', __name__, url_prefix='/property')

fb = Firebase(host=os.environ.get("FIREBASE_HOST"))
timezone = pytz.timezone('Asia/Bangkok')

@property.route('', methods=['POST','GET', 'PUT','DELETE'])
@property.route('/', methods=['POST','GET', 'PUT','DELETE'])
def property_func():
    user_id = Function.getUserID(request)
    now = datetime.now(timezone)
    time = now.strftime('%Y-%m-%d %H:%M:%S')

    if request.method == 'POST':
        data = request.get_json()
        
        for req in ['name']:
            if req not in data:
                return {"status":"error",'message': f"{req} is require for property added"}, 400
            
        data['createdate'] = time
        data['lastupdate'] = time
            
        # Gen ID
        id = Function.text_to_numeric_token(data.get('name'))
        
        #Check exsing
        propertyEx = fb.get_by_child(child=f"property/{id}")
        
        if propertyEx:
            return {'status': 'error', 'message': 'This Property already created'},400
        
        job = fb.db.reference().child(f"property/{id}").set(data)
        
        #Set user data
        job = fb.db.reference().child(f"""users/{user_id}/property/{id}/role""").set("owner")
        
        #Add channel to master
        masterUser = fb.get_by_child(child=f"users/master")
        if masterUser:
            listUserMaster = list(masterUser)
            for user in listUserMaster:
                try:
                    jobMaster = fb.db.reference().child(f"""users/{user}/property/{id}/role""").update("master")
                except:
                    jobMaster = fb.db.reference().child(f"""users/{user}/property/{id}/role""").set("master")

        # Task Create dataset
        from bigquery.bq import BigQuery, Table
        bq = BigQuery()
        dSet = bq.create_dataset(f"client_{id}")
        if dSet:
            #Create event table
            bq.create_table_from_json_schema(f"client_{id}", "event", Table.tableEvent(), "eventTimeStamp", cluster_fields=["pageId","eventName", "user_pseudo_id", "source"])
            bq.create_table_from_json_schema(f"client_{id}", "customer_profile", Table.tableCustomerProfile(), "lastupdate", cluster_fields=["user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "customer_profile_temp", Table.tableCustomerProfile(), "lastupdate", cluster_fields=["user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "profile_mapping", Table.tableProfileMapping(), "lastupdate", cluster_fields=["user_pseudo_id","unified_user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "profile_mapping_temp", Table.tableProfileMapping(), "lastupdate", cluster_fields=["user_pseudo_id","unified_user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "user", Table.tebleUserProfile(), "lastupdate", cluster_fields=["user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "user_temp", Table.tebleUserProfile(), "lastupdate", cluster_fields=["user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "profile_explore", Table.tableProfileExplore(), "lastupdate", cluster_fields=["user_pseudo_id"])
            bq.create_table_from_json_schema(f"client_{id}", "profile_explore_temp", Table.tableProfileExplore(), "lastupdate", cluster_fields=["user_pseudo_id"])
        
        return {"status":"ok",'message': 'Success', 'property_id': id}, 200
    
    elif request.method == "GET":
        local_key = request.headers.get('Authorization')
        bearer = local_key.replace("Bearer ", "")
        userAuth = TokenAuthorization(access_token=bearer)
        userData = userAuth.validate()

        # Get property data
        param = request.args
        for req in ['property_id']:
            if req not in param:
                return {"status":"error",'message': f"{req} is require"}, 400
            
        id = request.args.get('property_id')
        #Check user property
        try:
            userPropertyList = userData['property']
        except:
            return {'status': 'error', 'message': "User don't have any property"},400

        if id != "all" and id in userPropertyList:
            property_data = fb.get_by_child(child=f"property/{id}")
            logging.info(f"Property data: {property_data}")
            if property_data:
                return {"status":"ok",'message': 'Success', 'data': [property_data]}, 200
            else:
                return {"status":"error",'message': 'Not found'}, 404
        elif id == 'all':
            list_data = []
            for prop in userPropertyList:
                property_data = fb.get_by_child(child=f"property/{prop}")
                list_data.append(property_data)
            if list_data:
                return {"status":"ok",'message': 'Success', 'data': list_data}, 200

        return {"status":"error",'message': 'You not have permission to this property'}, 404
    
    return {"status":"error",'message': 'Method not allowed'}, 405


@property.route('/image/upload',  methods=['POST'])
def feature_image_upload():
    try:
        if request.content_type != 'image/jpeg':
            return {"status": "error","error": "Content-Type must be image/jpeg"}, 400
        
        image_data = request.data
        if not image_data:
            return {"status": "error",'message': 'No selected image'}, 400
        
        data = request.get_json()
        for req in ['property_id']:
            if req not in data:
                return {'message': f"{req} is require"}, 400
        property_id = data.get("property_id")
        
        now = datetime.now(timezone)
        time_now = int(now.timestamp())
        generate_image_file_name = f"""{uuid.uuid4()}_{time_now}.png"""

        try:
            filename = secure_filename(generate_image_file_name)
            gcs_blob_name = f"property/{filename}"

            # Upload to GCS
            storage = Storage(project_id=os.environ.get("GCP_PROJECT"), bucket_name=os.environ.get("GC_BUCKET_NAME"))
            link = storage.upload_from_byte(file_path=gcs_blob_name, image_bytes=image_data)

            if link:
                #Update DB
                fb.db.reference().child(f"property/{property_id}/image").set(link)
                return {"status": "ok",'message': 'Image uploaded successfully', 'image_address': link}, 201
            else:
                return {"status": "error",'message': 'Failed to upload image to GCS'}, 500

        except Exception as e:
            logging.info(f"Error processing upload: {e}")
            return {"status": "error",'message': f'An error occurred: {e}'}, 500
    
    except Exception as e:
        logging.error(e)
        return {'status': 'error', 'message': e}, 500
    
@property.route('/list-channel',  methods=['GET'])
@property.route('/list-channel/',  methods=['GET'])
def feature_property_list_channel():
    try:
        data = request.args
        for req in ['property_id', 'channel_type']:
            if req not in data:
                return {"status":"error",'message': f"{req} is require"}, 400
        
        property_id = data.get('property_id')
        channel_type = data.get('channel_type')

        if channel_type not in ['ga4', 'facebook', 'line', 'all']:
            return {'status': 'error', 'message': f'channel {channel_type} not support'}, 500
        
        if channel_type == 'all':
            channels = fb.db.reference().child(f"property/{property_id}/channel").get()
            if not channels:
                return {'status': 'error', 'message': 'This Property has no channel'}, 404
            result = []
            for channel, accounts in channels.items():
                channel_data = []
                for account_id, info in accounts.items():
                    entry = {"id": account_id}
                    if "name" in info:
                        entry["name"] = info["name"]
                    channel_data.append(entry)
                result.append({"channel": channel, "data": channel_data})
            return {'status': 'ok', 'data': result}, 200
        else:
            channels = fb.db.reference().child(f"property/{property_id}/channel/{channel_type}").get()
            if not channels:
                return {'status': 'error', 'message': f'This Property has no {channel_type} subscribe'}, 404
            channel_data = []
            for account_id, info in channels.items():
                entry = {"id": account_id}
                if "name" in info:
                    entry["name"] = info["name"]
                channel_data.append(entry)
        
            return {'status': 'ok', 'data': channel_data}, 200
    except Exception as e:
        logging.error(e)
        return {'status': 'error', 'message': e}, 500


@property.route("/admin/phone", methods=["GET", "POST"])
def admin_phoneNumber():
    if request.method == "GET":
        q = request.args or {}
        prop = (q.get("property_id") or "").strip()
        if not prop:
            return jsonify({"status": "error",
                            "message": "property_id is require for getting Admin Phone Numbers"}), 400
        try:
            env_key, phones, _ = get_admin_phones(prop)
            return jsonify({"status": "success",
                            "property_id": prop,
                            "env_key": env_key,
                            "phones": phones}), 200
        except Exception as e:
            return jsonify({"status": "error", "message": str(e)}), 500

    # POST body:
    # {
    #   "property_id": "client_9234725065",
    #   "action": "add" | "replace" | "remove",
    #   "phones": ["66812345678", "66987654321"]   # ALWAYS CC format
    # }
    
    if request.method == "POST":
        data = request.get_json()
        prop = (data.get("property_id") or "").strip()
        if not prop:
            return jsonify({"status": "error",
                            "message": "property_id is require for Editing Admin Phone Number"}), 400

        action = (data.get("action") or "add").lower()
        phones = data.get("phones")
        if not isinstance(phones, list) or not phones:
            return jsonify({"status": "error",
                            "message": "phones must be a non-empty list of 66XXXXXXXXX"}), 400

        try:
            if action == "add":
                env_key, out = add_admin_phones(prop, phones)
            elif action in ("replace", "edit"):
                env_key, out = replace_admin_phones(prop, phones)
            elif action == "remove":
                env_key, out = remove_admin_phones(prop, phones)
            else:
                return jsonify({"status": "error",
                                "message": "action must be one of: add, replace, remove"}), 400

            return jsonify({"status": "success",
                            "property_id": prop,
                            "env_key": env_key,
                            "action": action,
                            "phones": out}), 200
        except ValueError as ve:
            return jsonify({"status": "error", "message": str(ve)}), 400
        except Exception as e:
            return jsonify({"status": "error", "message": str(e)}), 500

    return jsonify({"status": "error", "message": "Method not allowed"}), 405
