


import binascii
import os
from urllib.parse import urlencode

import pkce
from requests_oauthlib import OAuth2Session

from configs.firebase import SERVER_TIMESTAMP, db
from V2.functions.Applications.main import Application
from V2.functions.Shops.main import Shop
from V2.functions.Users.main import Enterprise
from V2.Params import Params

SHOPIFY_SCOPES  = [
        'read_products',
        'write_shipping',
        'read_orders',
        "write_products",
        "write_orders",
        "read_fulfillments",
        "write_fulfillments",
        "read_inventory",
        "write_inventory",
        'read_assigned_fulfillment_orders',
        'write_assigned_fulfillment_orders',
        'write_third_party_fulfillment_orders',
        "read_locations",
        "write_locations",
        "read_publications",
        "write_publications"
    ]

def saveAuthState(
        uid, enterpriseId, platformId, domain,redirectUrl, **data
):
    ref = db.collection("authStates").document(data.get("state"))
    ref.set(dict(
        uid=uid,
        enterpriseId=enterpriseId,
        platformId=platformId,
        domain=domain,
        createdAt=SERVER_TIMESTAMP,
        redirectUrl=redirectUrl,
        **data
    ))
    return ref.id

def getAuthState(id):
    ref = db.collection("authStates").document(id).get()
    if ref.exists: return ref.to_dict()


PLANS = [
    "NOV24BUSINESS",
    "NOV24PRO",
    "NOV24STARTER"
]
ENTERPRISES = [
    "lJ2eUFov5WyPlRm4geCr"
]
EXCLUDE_ENTERPRISES = [
    "yBS37JVM9JM55dgtNHVP"
]

def auth(params:Params):
    currentUser = params.currentUser
    uid, enterpriseId = currentUser.uid, currentUser.enterpriseId
    platformId = params.args.get("platformId")
    currentDomain = params.hostname
    url = params.args.get("url")
    redirect_uri = "https://riverr-enterprise-integrations-dot-riverr-enterprise-user.uc.r.appspot.com/v2/shops/token"
    data = None
    enterprise = Enterprise.get(enterpriseId)
    planId = enterprise.planId
    app = Application.get(platformId+("zNAlxdaZG6hKf6vexv6ljqHyP8i1" if (planId in PLANS or enterpriseId in ENTERPRISES and enterpriseId not in EXCLUDE_ENTERPRISES) else enterpriseId))
    if platformId == "1": 
        data = etsyAuthUrl(app, redirect_uri)
    if platformId == "2":
        data = shopifyAuth(app, url, redirect_uri)
    if platformId == "3":
        data = wooAuth(app, uid, url, f"{currentDomain}/shops")
    if not data:return
    id = saveAuthState(
        uid,
        enterpriseId,
        platformId,
        currentDomain, 
        redirectUrl=redirect_uri,
       **data
    )
    return dict(
        id=id, 
        **data
    )

def etsyAuthUrl(app: Application, redirectUrl:str) -> dict:
    scope = ["listings_d", "listings_w", "listings_r", "transactions_r","transactions_w", "shops_r", "profile_r", "email_r"]
    oauth = OAuth2Session(app.apiKey, redirect_uri=redirectUrl, scope=scope)
    code_verifier, code_challenge = pkce.generate_pkce_pair()
    url, state  = oauth.authorization_url("https://www.etsy.com/oauth/connect", code_challenge=code_challenge, code_challenge_method="S256")
    return dict(url=url, state=state, code_verifier=code_verifier, code_challenge=code_challenge, code_challenge_method="S256")


# def shopifyAuth(app: Application, url:str, redirectUrl:str):
#     # Extract required data
#     state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")  # Generate a random state value
#     query_params = {
#         "client_id": app.apiKey,
#         "scope": ",".join(SHOPIFY_SCOPES),
#         "redirect_uri": redirectUrl,
#         "state": state,
#     }
#     url = f"https://{url}/admin/oauth/authorize?" + urlencode(query_params)
#     return {"url": url, "state":state}


def etsyAuthUrl(app: Application, redirectUrl:str) -> dict:
    scope = ["listings_d", "listings_w", "listings_r", "transactions_r","transactions_w", "shops_r", "profile_r", "email_r"]
    oauth = OAuth2Session(app.apiKey, redirect_uri=redirectUrl, scope=scope)
    code_verifier, code_challenge = pkce.generate_pkce_pair()
    url, state  = oauth.authorization_url("https://www.etsy.com/oauth/connect", code_challenge=code_challenge, code_challenge_method="S256")
    return dict(url=url, state=state, code_verifier=code_verifier, code_challenge=code_challenge, code_challenge_method="S256")


def shopifyAuth(app: Application, url:str, redirectUrl:str):
    # Extract required data
    state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")  # Generate a random state value
    query_params = {
        "client_id": app.apiKey,
        "scope": ",".join(SHOPIFY_SCOPES),
        "redirect_uri": redirectUrl,
        "state": state,
    }
    url = f"https://{url}/admin/oauth/authorize?" + urlencode(query_params)
    return {"url": url, "state":state}



def wooAuth(app: Application, uid:str, url:str, redirectUrl:str):
    noneShops = db.collection("shopsCredentials").where("uid", "==", uid).where("platformId", "==", "3").where("consumerKey", "==", None).where("consumerSecret", "==", None).get()
    for s in noneShops:
        s.reference.delete()
        db.collection("shops").document(s.id).delete()
    state = binascii.b2a_hex(os.urandom(15)).decode("utf-8")  # Generate a random state value
    Shop(
        uid=uid,
        platformId=app.platformId,
        enterpriseId=app.enterpriseId, 
        platformShopId= url, 
        platformName=app.platformName, 
        appId=app.id, 
        name=url, 
        url=f"https://{url}", 
        consumerKey = None, 
        consumerSecret=None,
        accessToken=None
        ).save(
            state=state
        )
    url= f"https://{url}"
    endpoint = '/wc-auth/v1/authorize'
    params = dict(
        app_name = app.name,
        scope="read_write",
        user_id = uid,
        return_url = redirectUrl,
        callback_url = f"https://riverr-enterprise-integrations-dot-riverr-enterprise-user.uc.r.appspot.com/woocommerce/auth"
    )
    query_string = urlencode(params)
    return dict(url=("%s%s?%s" % (url, endpoint, query_string)), state=state)

