from usermanagement.models import UserProfile,Privilege
from re import sub
from decimal import Decimal
from datetime import datetime,date
from dateutil.relativedelta import relativedelta
from organizationmanagement.models import GlobalSettings,Company
from codesofy.master_details import GlobalSettingKeys,PerPageSelector,DateFilter,NumberFormatException,NegativeInputNumberException,SubFeatureType
import qrcode
from django.conf import settings
import locale
import re
from customermanagement.models import Customer

from django.utils import timezone



def get_local_date():
    today = timezone.localtime(timezone.now()).date()
    return today

def get_local_date_time():
    today = timezone.localtime(timezone.now())
    return today

def get_max_image_file_size_in_bytes():
    limit_kb = 150
    return limit_kb * 1024


def to_list_for_reports(item_list):
    new_item_list = list(item_list)
    new_item_list.insert(0,'ALL')
    return new_item_list

def get_global_master_details():
    context = {}
    company = Company.objects.get(id=1)
    per_page_selector = PerPageSelector.to_list()
    date_filters = DateFilter.to_list()
    current_date = date.today()
    global_settings = GlobalSettings.objects.all()

    #now = datetime.now()
    
    now = timezone.localtime(timezone.now())
    # dd/mm/YY H:M:S
    dt_string = now.strftime("%d/%m/%Y %H:%M:%S")


    currency_sign = "£"
    currency = "LKR"
    context["currency"] = currency
    context["currency_sign"] = currency_sign
    context["per_page_selector"] = per_page_selector
    context["date_filters"] = date_filters
    context["current_date"] = current_date
    context["global_settings"] = global_settings
    context["company"] = company
    context["dt_string"] = dt_string

    
    return context



def rename_file(old_file,new_file_name):
    filename = old_file.name
    ext = filename.split('.')[-1]
    old_file.name = new_file_name+"."+ext


def is_super_admin(user):
    return GlobalSettings.objects.filter(key=GlobalSettingKeys.SUPER_ADMIN.value,value=user.username).exists()

def is_authorized(user_profile,this_sub_feature):
    return (GlobalSettings.objects.filter(key=GlobalSettingKeys.SUPER_ADMIN.value,value=user_profile.user.username).exists() or 
    Privilege.objects.filter(system_role=user_profile.system_role,sub_feature__feature_name=this_sub_feature.upper()).exists())

def get_privilleges(user_profile,context):
    
    privilege_set = Privilege.objects.filter(system_role=user_profile.system_role)

    if GlobalSettings.objects.filter(key=GlobalSettingKeys.SUPER_ADMIN.value,value=user_profile.user.username).exists():
        context["super_admin"] = True
    else:
        context["super_admin"] = False

    main_feature_matrix = {}
    sub_feature_matrix = {}
    main_menu_item_matrix = {}
    for privillege in privilege_set:

        if privillege.sub_feature.feature_type == SubFeatureType.MODULE.value:
            main_menu_item_matrix[privillege.sub_feature.main_feature.feature_name.lower()] = True

        main_feature_matrix[privillege.sub_feature.main_feature.feature_name.lower()] = True
        sub_feature_matrix[privillege.sub_feature.feature_name.lower()] = True

    #print("Main Features")
    #print(main_feature_matrix)

    #print("Sub Features")
    #print(sub_feature_matrix)

    context["main_menu_item_matrix"] = main_menu_item_matrix
    context["main_feature_matrix"] = main_feature_matrix
    context["sub_feature_matrix"] = sub_feature_matrix
    
    return context

def validate_email(email):
    regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
    if email and re.fullmatch(regex, email):    
        return True
    else:
        return False
    
def validate_mobile(mobile):
    if mobile and mobile.isnumeric():    
        return True
    else:
        return False
    

def validate_password(password):
    # Check if the password has at least 8 characters
    if len(password) < 8:
        return False
    
    # Check if the password contains spaces
    if ' ' in password:
        return False
    
    # Check if the password contains at least one uppercase letter
    if not re.search(r'[A-Z]', password):
        return False
    
    # Check if the password contains at least one lowercase letter
    if not re.search(r'[a-z]', password):
        return False
    
    # Check if the password contains at least one digit
    if not re.search(r'\d', password):
        return False
    
    # Check if the password contains at least one special character
    if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
        return False
    
    # If all the conditions are met, the password is valid
    return True
    
def validate_telephone(telephone):
    if telephone and telephone.isnumeric():    
        return True
    else:
        return False

def set_menu_items(menu_item,sub_menu_item,context):

    context["sub_menu_item"] = sub_menu_item
    context["menu_item"] = menu_item

    return context

def set_user_profile(request,context):
    logged_user = request.user
    if UserProfile.objects.filter(user=logged_user).exists():
        logged_user_profile = UserProfile.objects.get(user=logged_user)
        context["logged_user_profile"] =logged_user_profile
        return logged_user_profile
    

def get_standard_text_input(text):
    if(text != None):
        return (re.sub(' +', ' ', text.strip()).upper())
    else:
        return text

def convert_to_decimal(currency_text):
    locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

    if currency_text == None or currency_text == '':
        return 0
    else:
        #print(currency_text)
        #sub_str = sub(r'[^\d.]', '', currency_text)
        #sub_str = sub(',', '', currency_text)
        
        try:
            value = locale.atof(currency_text)

            if value<0:
                    raise NegativeInputNumberException(str(value) + " is a negative number")
            else:
                return value
        except Exception:
            raise NumberFormatException(str(currency_text) + " is not identified as a Number")
        
        """ print(value)
        if value.isnumeric():
            #value = Decimal(sub_str)
            if value<0:
                raise NegativeInputNumberException(value + " is a negative number")
            else:
                return value
        else:
            raise NumberFormatException(currency_text + " is not a Number") """
            
    
def get_unique_text(text):
    text = " ".join(text.split())
    return text

def str_to_date(date_string):
    if date_string:
        datetime_obj = datetime.strptime(date_string, '%Y-%m-%d')
        return datetime_obj.date()
    else:
        return None


def get_months_dic():
    months = {	
        1:'Janauary',
		2:'February',
		3:'March',
		4:'April',
		5:'May',
		6:'June',
		7:'July',
		8:'August',
		9:'September',
		10:'October',
		11:'November',
		12:'December'
        }
    return months

def create_target_date(year,month):
    day = 1
    dates = datetime(int(year), int(month), int(day))
    return dates

def convert_str_to_boolean(value):
    if value == None:
        return False
    elif value == "1":
        return True
    else:
        return False
    
def convert_str_to_float(value):
    return float(value)


def get_next_due_date(date,month_value):
    
    global_setting = GlobalSettings.objects.get(key=GlobalSettingKeys.DEFAULT_PAYMENT_DUE_DATE.value)
    
    date_in_the_month = int(global_setting.value)

    print("Date in the Month " + str(date.month))

    current_date = datetime(date.year,date.month,date_in_the_month)
    next_due_date = current_date+ relativedelta(months=month_value)

    return next_due_date


def generate_qr_code(data):
    img = qrcode.make(data)
    media_url = settings.MEDIA_URL
    
    path = media_url + "registration-qr-codes/"
    print("path - " + path)
    img.save('media/registration-qr-codes/'+str(data)+'.png')
    #img.save('..'+path+str(data)+'.png')
 

def create_new_customer_code():

    try:
    # Convert to integers and find the maximum
        customer_codes = Customer.objects.values_list('code', flat=True)
        max_customer_code = max(int(code) for code in customer_codes if code.isdigit())
        new_customer_code = max_customer_code + 1
        if new_customer_code < 10:
            new_customer_code = '000' + str(new_customer_code)
        elif new_customer_code < 100:
            new_customer_code = '00' + str(new_customer_code)
        elif new_customer_code < 1000:
            new_customer_code = '0' + str(new_customer_code)
        else:
            new_customer_code = str(new_customer_code)

        return new_customer_code
    except ValueError:
        return "0001"
    

