from datetime import datetime

import pytz
import requests
from requests_oauthlib import OAuth2Session

from V2.functions.Applications.main import Application
from V2.functions.Helpers import generate_state_parameter
from V2.functions.Shops.main import Shop
from V2.middlewares.auth import API_Error
from V2.Params import Params

BASE_URL = "https://api.printify.com/v1"

def printifyTime(timezone:str="UTC"):
    tz = pytz.timezone(timezone)
    # offset = datetime.now(tz).strftime("%z")
    # offset = f"{offset[:3]}:{offset[3:]}"
    # format = "2022-05-01T12:00:00Z"
    time = datetime.now(tz).strftime("%Y-%m-%dT%H:%M:%SZ")
    # time+=offset
    return time
    

def authUrl(params:Params) -> dict:
    enterpriseId = params.currentUser.enterpriseId
    app = Application.get("11"+enterpriseId)
    redirect_uri = "http://localhost:3000/shops/redirects/printify" if params.hostname == "localhost" else f'https://{params.hostname}/shops/redirects/printify'
    state = generate_state_parameter()
    url = f"https://printify.com/app/authorize?app_id={app.apiKey}&accept_url={redirect_uri}&decline_url={redirect_uri}&state="
    return dict(url=url, state=state)
    
def authToken(params:Params) -> Shop:
    enterpriseId = params.currentUser.enterpriseId
    app = Application.get("11"+enterpriseId)
    if app:
        res = requests.get(f"{BASE_URL}/app/oauth/tokens", 
           params=dict(
             code=params.args.get('code'),
             app_id=app.apiKey
           )
        )
        if res.status_code not in [201, 200]: raise API_Error(res.text, res.status_code)
        token:dict = res.json()
        from V2.functions.Printify.Shops import getPrintifyShop
        printifyShops = getPrintifyShop(token)
        savedShops = []
        for printifyShop in printifyShops:
            savedShop = Shop(
                name=f"Printify- {printifyShop.get('shop_name')}",
                platformShopId=printifyShop.get("shop_id"),
                platformId=app.platformId,
                platformName=app.platformName,
                appId=app.id,
                uid=params.currentUser.uid,
                enterpriseId=app.enterpriseId,
                url=None,
                accessToken=token.get('access_token'),
                refreshToken=token.get('refresh_token'),
                apiVersion="v3",
                tokenType=token.get("token_type"),
                expiresAt=int(datetime.strptime(token.get("expires_at", 0), '%Y-%m-%d %H:%M:%S').timestamp())
            ).save()
            savedShops.append(savedShop)
        return dict(shops=[shop.to_dict() for shop in savedShops])
    raise API_Error("App not found.")

class PrintifyClient:
    def __init__(self,app:Application,shop:Shop) -> None:
        self.app = app
        self.shop = shop
        self.headers = {
            "User-Agent": "Riverr",
           "Authorization": f"Bearer {shop.accessToken}"
        }
        if self.shop.expiresAt:
            if self.shop.expiresAt < datetime.now(pytz.utc).timestamp(): self.refreshToken()
        else: print(self.shop)

    def refreshToken(self):
        res =requests.post(f"{BASE_URL}/app/oauth/tokens/refresh", 
           data=dict(
             self.shop.refreshToken, 
            app_id=self.app.apiKey,
            refresh_token=self.shop.refreshToken
           )
        )
        if res.status_code in [200,201]:
            token = res.json()
            self.shop.accessToken = res.get("access_token")
            self.shop.tokenType = res.get("token_type")
            self.shop.refreshToken = res.get("refresh_token")
            self.shop.expiresAt = int(datetime.strptime(token.get("expires_at", 0), '%Y-%m-%d %H:%M:%S').timestamp())
            self.shop.timezone = pytz.utc.tzname(dt=datetime.now())
            self.shop.update()
        else: raise API_Error(res.text, res.status_code)

    def get(self, path:str, params:dict={}):
        return requests.get(f"{BASE_URL}/{path}",params=params)

    def post(self, path:str, data:dict={}):
        return requests.post(f"{BASE_URL}/{path}",data=data)


