import base64
import binascii
import os

import requests
import shopify
from flask import redirect

from configs.firebase import SERVER_TIMESTAMP, db
from functions.Applications import getAppCredentials
from functions.Enterprises import getEnterpriseByHostname, getEnterpriseById
from functions.Response import API_Error, saveError
from functions.Shops import saveShop
from functions.Users import (checkUser, checkUserByUid, createUser,
                             createUserData, deleteOrders, deleteProducts,
                             generateCustomToken, getUser,
                             updateUserEnterprise)

apiVersion = '2023-07'
# write orders needed for creating fulfillments
from V2.functions.Shops.Auth import SHOPIFY_SCOPES as scopes


def shopifyAuth(data):
    uid = data.get('uid')
    user = getUser(uid)
    enterpriseId = user.get('enterpriseId')
    app = getAppCredentials("2"+enterpriseId)
    url = f"https://{data.get('url')}"
    redirect_uri = data.get('redirect_uri',  f"https://{data.get('hostname')}/app-user")
    shopify.Session.setup(api_key=app.get('apiKey'), secret=app.get('apiSecret'))
    state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")
    session = shopify.Session(url, apiVersion)
    auth_url = session.create_permission_url(scopes, redirect_uri, state)
    return dict(auth_url=auth_url)
    
def generate_state_parameter():
    random = os.urandom(256)
    state = base64.b64encode(random)
    return (state)

def shopifyDirectAuth(data:dict):
    enterpriseId = data.get("id")
    app = getAppCredentials("2"+enterpriseId)
    enterprise = getEnterpriseById(enterpriseId)
    if enterprise.get("isProUser"):redirect_uri = "https://app.riverr.app/app-user"
    else:
        hostnames = enterprise.get("hostnames",[])
        redirect_uri = f"https://{hostnames[0]}/app-user" 
        # if enterpriseId in [
        #     "oswfF8oIPavNUJxztcIc",
        #     "5jbLxTifaOuHw1Wao7HQ",
        #     "eMGenRI7Fs5oSh1AAHsb",
        #     "vYbTvqZFNuSLuOy4qA1UbU0MBQi2",
        #     "ch05DgvKQ2Mx3Rlew2x5GWbpgjt2",
        #     "lJ2eUFov5WyPlRm4geCr",
        #     "4DAdwXeVVkIZF80fwTDh",
        #     "e9g3DJWshxOh7SAV50pV08UK8QI2",
        #     "5kD48nj4azV6UonfHvmn",
        #     "gSo3G298DNypOMvofnaR",
        #     "d8Fr7YtkeSBjk2vUOHVh",
        #     "k18IR17msxHXglLP4jLO",
        #     "BWhPnd7E0xk180M3Hpj7",
        #     "e9g3DJWshxOh7SAV50pV08UK8QI2"
        # ] else f"https://{hostnames[0]}/shopify-user"
    shopify.Session.setup(api_key=app.get('apiKey'), secret=app.get('apiSecret'))
    state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")
    shop = data.get("shop", "enterprisetester.myshopify.com")
    session = shopify.Session(shop, apiVersion)
    auth_url = session.create_permission_url(scopes, redirect_uri, state)
    return redirect(auth_url)

def shopifyToken(data):
    user = data.get('currentUser')
    enterpriseId = user.get("enterpriseId")
    app = getAppCredentials("2"+enterpriseId)
    uid = data.get('uid')
    code , hmac, shop, state, timestamp, host = data.get('code'), data.get('hmac'),data.get('shop'),data.get('state'),data.get('timestamp'), data.get('host')
    url = f"https://{shop}"
    shopify.Session.setup(api_key=app.get('apiKey'), secret=app.get("apiSecret"))
    session = shopify.Session(shop, apiVersion)
    accessToken = session.request_token(dict(
        code=code ,
        hmac=hmac, 
        shop=shop, 
        state=state, 
        timestamp=timestamp, 
        host=host
    ))
    headers = createHeader(accessToken)
    shop_base = f"{url}/admin/api/{apiVersion}/shop.json"
    res = requests.get(shop_base,headers=headers)
    if res.status_code == 200:
        shop = res.json().get('shop')
        user = getUser(uid)
        enterpriseId = user.get('enterpriseId')
        app = getAppCredentials("2"+enterpriseId)
        convertedShop = saveShop(
            uid=uid,
            platformId="2",
            enterpriseId= user.get('enterpriseId'),
            platformShopId=str((shop.get("id"))),
            platformName= "Shopify",
            appId= app.get('id'),
            name = shop.get('name'),
            createdAt = SERVER_TIMESTAMP,
            updatedAt = SERVER_TIMESTAMP,
            url = url,
            accessToken=accessToken
        )
        return convertedShop
    else: saveError(uid, "shopifyToken", res.text)
    raise API_Error(res.text, res.status_code, meta=dict(error = res.json()))


def createHeader(accessToken, **kwargs):
    headers = {'X-Shopify-Access-Token': accessToken, 'Content-Type': 'application/json'}
    headers.update(kwargs)
    return headers

def anonyAuth(params):
    hostname = params.get('hostname')
    if hostname == "app.riverr.app":
        app = getAppCredentials("2zNAlxdaZG6hKf6vexv6ljqHyP8i1")
    else:
        enterprise = getEnterpriseByHostname(hostname)
        enterpriseId = enterprise.get('id')
        app = getAppCredentials("2"+enterpriseId)
    url = f"https://{params.get('shop')}" 
    redirect_uri = params.get('redirect_uri',  f"https://{params.get('hostname')}/app-user")
    shopify.Session.setup(api_key=app.get('apiKey'), secret=app.get('apiSecret'))
    state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")
    session = shopify.Session(url, apiVersion)
    auth_url = session.create_permission_url(scopes, redirect_uri, state)
    return dict(auth_url=auth_url)


def anonyToken(params):
    currentUser = params.get('currentUser')
    if currentUser: return shopifyToken(params)
    hostname = params.get('hostname')
    if hostname == "app.riverr.app":
        app = getAppCredentials("2zNAlxdaZG6hKf6vexv6ljqHyP8i1")
        enterpriseId = None
    else:
        enterprise = getEnterpriseByHostname(hostname)
        enterpriseId = enterprise.get('id')
        app = getAppCredentials("2"+enterpriseId)
    url = f"https://{params.get('shop')}"
    code , hmac, shop, state, timestamp, host = params.get('code'), params.get('hmac'),params.get('shop'),params.get('state'),params.get('timestamp'), params.get('host')
    shopify.Session.setup(api_key=app.get('apiKey'), secret=app.get("apiSecret"))
    session = shopify.Session(shop, apiVersion)
    accessToken = session.request_token(dict(
        code=code,
        hmac=hmac, 
        shop=shop, 
        state=state, 
        timestamp=timestamp, 
        host=host
    ))
    headers = createHeader(accessToken)
    shop_base = f"{url}/admin/api/{apiVersion}/shop.json"
    res = requests.get(shop_base,headers=headers)
    if res.status_code == 200:
        shop = res.json().get('shop', {})
        email=shop.get('email')
        password = f"{email}-password"
        user,userData = checkShopifyShop(str(shop.get("id")))  
        if not (user and userData): user, userData = checkUser(email)
        if user and userData and enterpriseId and enterpriseId != userData.get('enterpriseId'):
            updateUserEnterprise(
                userData.get('uid'),
                enterpriseId
            )
        if not user:
            user = createUser(
                email, 
                password,
                email,
                enterpriseId=enterpriseId,
                isProUser= hostname == "app.riverr.app",
                shopifyUser=True
            )
        if user and not userData:
            createUserData(
                uid=user.uid,
                email=email, 
                displayName=email,
                enterpriseId=user.uid if hostname == "app.riverr.app" else enterpriseId,
                isProUser= hostname == "app.riverr.app",
                shopifyUser=True
            )
        if hostname == "app.riverr.app": enterpriseId = user.uid
        appId = "2"+enterpriseId if enterpriseId else None
        uid = user.uid
        if not enterpriseId: enterpriseId = uid
        convertedShop = saveShop(
            uid=uid,
            platformId="2",
            enterpriseId= enterpriseId if enterpriseId else uid,
            platformShopId=str(shop.get("id")),
            platformName= "Shopify",
            appId= appId if appId else "2"+uid,
            name = shop.get('name'),
            createdAt = SERVER_TIMESTAMP,
            updatedAt = SERVER_TIMESTAMP,
            url=url,
            accessToken=accessToken,
            email=shop.get('email'),
            password=password,
            registered=True
        ) 
        convertedShop['customToken'] = generateCustomToken(user.uid) 
        return convertedShop
    else: saveError(None, "anonyToken", res.text)
    raise API_Error(res.text, res.status_code, meta=dict(error = res.json()))


def checkShopifyShop(platformShopId):
    ref = db.collection("shopsCredentials").where("platformId", "==", "2").where("platformShopId", "==", platformShopId).get()
    if len(ref)>0:
        shop = ref[0].to_dict()
        uid = shop.get("uid")
        return checkUserByUid(uid)
    return None, None

def customDataRequest(data:dict):
    shop_domain = data.get('shop_domain')
    shops = getShopByDomain(shop_domain)
    return dict(shops=shops)

def customersRedact(data:dict):
    email = data.get("customer").get("email")
    shops = db.collection("shops").where("email", "==", email).get()
    for shop in shops:
        shop.reference.delete()
    return dict(message="Customer data erased.")

def shopRedact(data:dict):
    shop_domain = data.get('shop_domain')
    shop = getShopByDomain(f'https://{shop_domain}')
    if shop:
        deleteFulfillmentService(shop.id)
        shop.reference.delete()
        # deleteManualProducts(shop.get('id'))
        deleteProducts(uid=shop.get('uid'), shopId=shop.get('id'))
        deleteOrders(shop.get("uid"),shop.get('id'))
        return dict(shop=shop.to_dict())
    else: return dict(shop=None)

def deleteFulfillmentService(id:str):
    ref = db.collection("fulfillmentServices").document(id).get()
    if ref.exists:
        ref.reference.delete()
    return ref.id

def getShopByDomain(shop_domain):
    print(shop_domain)
    shops = db.collection("shops").where("url", "==", shop_domain).get()
    if shops:
        return shops[0]
    return None
