import os
import logging
import json
import requests

from datetime import timedelta
from django.utils import timezone
from dataclasses import dataclass
from apps.process.models import ProcessedMedia
from apps.subscriptions.models import Subscription, Extention

# Create a logger for this file
logger = logging.getLogger(__file__)

# Function That retun a list of valid extension for the current user
def valid_extensions(user):
  try:
    return user.subscription.plan.get_valid_extentions()
  except  Subscription.DoesNotExist as e:
    logger.warning(f"Function valid_extensions() With Exeption : {e}")
    return [v.value for v in Extention.objects.all()[:20]]

# Function That Valid if the current user's upladed file extention is valid
def extention_file_valid(file_extention, request):
    if file_extention in valid_extensions(request): return True
    return False

#
def file_extension_valid(request):
    filename = request.POST['filename']
    _, file_extension = os.path.splitext(filename)
    if file_extension.replace(".","") in valid_extensions(request.user) and request.user.is_staff : return True
    elif file_extension.replace(".","") in valid_extensions(request.user) : return True
    else : return False

#
def retrieve_elixir_of_size(user):
    """ Return the file_size field of the Plan model associated with the user """
    try:
        return user.subscription.plan.file_size
    except Exception as e:
        logger.warning(f"Function retrieve_elixir_of_size() With Exception : {e}")
        return None

#
def retrieve_elixir_of_time(user):
    # Return the time_per_video field of the Plan model associated with the user
    try:
        return user.subscription.plan.time_per_video
    except Exception as e:
        logger.warning(f"Function retrieve_elixir_of_time() With Exception : {e}")
        return None

#
def retrieve_limit_of_size(file_size, user):
    # Get the file_size field of the user's plan
    file_plan = retrieve_elixir_of_size(user)
    # Check if the file size is larger than the file_size
    if file_plan != None and (file_size > file_plan or user.is_staff):
        # If the file size is too large, return a dictionary with "status" set to False and a message
        return {"status": False, "message": f"The file is too large for your plan [ file size <= {file_plan} ]" }
    # If the file size is within the limit, return a dictionary with "status" set to True and a message
    return {"status": True, "message": "The file is within the limit." }

#
def retrieve_limit_of_duration(file_duration, user):
    # Get the time_per_video field of the user's plan
    time = retrieve_elixir_of_time(user)
    # Convert the time to a timedelta object
    try:
        duration = timedelta(hours=time.hour, minutes=time.minute, seconds=time.second).total_seconds()
    except Exception as e :
        logger.warning(f"Inside Function retrieve_limit_of_duration() Exception : {e}")
        duration = None
    # Check if the file duration is larger than the time_per_video
    if file_duration != None and duration != None and (file_duration > duration or user.is_staff):
        # If the file duration is too large, return a dictionary with "status" set to False and a message
        return {"status": False, "message": f"The file is too large for your plan [ file duration <= {duration} ]" }
    # If the file duration is within the limit, return a dictionary with "status" set to True and a message
    return {"status": True, "message": "The file is within the limit."}

#
def has_reached_upload_limit(user):
    """ Function that check if user reached his plan's videos limit """
    # Get the current time in the default time zone
    now = timezone.now()
    # Extract the date from the current time
    current_date = now.date()
    # retch the count of proceesed media by user and day
    count_media = ProcessedMedia.get_count_for_user(user, current_date)

    # retch the limit video condition in user plan
    try:
        limit_media =  user.subscription.plan.videos_per_day
        if user.subscription.plan.plan_name == "Free":
            count_media = ProcessedMedia.objects.filter(user=user).count()
    except Exception as e:
        logger.warning(f"Inside Function has_reached_upload_limit() Exception : {e}")
        limit_media = None

    if limit_media == None and user.is_staff :
        return {"status": True, "message": "Rest MEDIA are unlimited media", "Rest_Medias":"Infinity", "Uploaded_day":count_media}
    if limit_media <= count_media :
        return {"status": False, "message": f"Rest MEDIA are {limit_media-count_media} media", "Rest_Medias":limit_media-count_media, "Uploaded_day":count_media}
    else:
       return {"status": True, "message": f"Rest MEDIA are {limit_media-count_media} media" , "Rest_Medias":limit_media-count_media, "Uploaded_day":count_media}


@dataclass
class UpgradeSubscription:
    """Class for keeping track of an item in inventory."""
    CLIENT_ID: str
    CLIENT_SECRET: str

    def gen_token(self):
        """ method that generate paypal token """
        grant_type = 'client_credentials'
        body_params = {'grant_type': grant_type}
        url = 'https://api.paypal.com/v1/oauth2/token'
        response = requests.post(url, data=body_params, auth=(self.CLIENT_ID, self.CLIENT_SECRET))
        return response

    def get_subscription_details(self, sub_id):
        if self.gen_token().status_code == 200:
            response = json.loads(self.gen_token().text)
            token = response['access_token']

            headers = {"Authorization": "Bearer {}".format(token)}
            response = requests.get(url=f"https://api.paypal.com/v1/billing/subscriptions/{sub_id}", headers=headers)
            return response

        else:
            return self.gen_token()

    def cancel(self, sub_id):
        if self.gen_token().status_code == 200:
            response = json.loads(self.gen_token().text)
            token = response['access_token']
            headers = {"Authorization": "Bearer {}".format(token), 'Content-type': 'application/json'}
            
            response = requests.post(url=f"https://api.paypal.com/v1/billing/subscriptions/{sub_id}/cancel?=&=",
                              headers=headers)
            
            return response

        else:
            return self.gen_token()

    def revise(self,plan_id,sub_id):
        if self.gen_token().status_code == 200:
            response = json.loads(self.gen_token().text)
            token = response['access_token']
            headers = {
                'Content-Type': 'application/json',
                'Authorization': f'Bearer {token}',
                'Accept': 'application/json',
            }
            url = f'https://api.paypal.com/v1/billing/subscriptions/{sub_id}/revise'
            data = {"plan_id": plan_id}
            res = requests.post(url, headers=headers, json=data)
            return res