from django.core.mail import send_mail
from django.db import models
from django.conf import settings
from django.shortcuts import get_object_or_404
from embed_video.fields import EmbedVideoField
# from embed_video.fields import EmbedVideoField
from django.contrib.auth.models import User

from datetime import datetime

from account.utils import email_user_deposit, email_user_withdrawal

# ====================CHOICES FOR SELECTING PRICE PLAN NAME AND EARNING RATE=========================================
PLAN_TYPE = (
    ("LEVEL 1", "LEVEL 1"),
    ("LEVEL 2", "LEVEL 2"),
    ("LEVEL 3", "LEVEL 3"),
    # ("DIAMOND PLAN", "DIAMOND PLAN"),
)


# bitcoin, bitcoin cash, etherium,  usdt, BNB, payees, and perfect money

COIN_TYPE = (
    ("BITCOIN", "BITCOIN"),
    ("ETHEREUM", "ETHEREUM"),
    ("USDT TRC20", "USDT TRC20"),
    ("USDT ERC20", "USDT ERC20"),
    # ("BNB", "BNB"),
    ("LITECOIN", "LITECOIN"),
    # ("TRON", "TRON"),
    # ("USDT BEP20", "USDT BEP20"),
    # ("PERFECT MONEY", "PERFECT MONEY"),
    # ("PAYEER", "PAYEER"),
    # ("GLIZE", "GLIZE"),
    # ("DOGECOIN", "DOGECOIN"),
    # ("USDC", "USDC"),
    # ("POLYGON", "POLYGON"),
    # ("LITECOIN", "LITECOIN")
)

EARNING_RATE = (
    ("3.1%", "3.1%"),
    ("5.2%", "5.2%"),
    ("10.5%", "10.5%"),
    # ("5%", "5%"),
)

WITHDRAW_FROM = (
    ("ACCOUNT BALANCE", "ACCOUNT BALANCE"),
    ("REFERRAL BONUS", "REFERRAL BONUS")
)

STATUS = (
    ("PENDING", "PENDING"),
    ("APPROVED", "APPROVED")
)
# ======================================================================================================


class DepositTransaction(models.Model):
    """RECORDS ALL THE DEPOSITS TRANSACTION DONE BY THE USER"""
    user = models.OneToOneField(User, related_name="user_deposit_transactions", on_delete=models.CASCADE)
    user_amount = models.DecimalField(default=5.0, max_digits=10, decimal_places=2, null=True, blank=True)
    current_balance = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, null=True, blank=True)
    amount_to_add = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, null=True, blank=True, help_text="Enter the amount the user deposited. Please do not touch this field")
    referrer_bonus = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, null=True, blank=True, help_text="Bonus of the referrer. Please do not touch this field")
    amount_to_withdraw = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, null=True, blank=True, help_text="Current Earning of the user. Please do not touch this field")

    date_deposited = models.DateField(default=datetime.now)
    transaction_referrence = models.CharField(max_length=150, help_text="Leave the transaction referrence as it is. It's use for sending the user an email", null=True, blank=True)
    status = models.CharField(max_length=25, choices=STATUS)

    class Meta:
        ordering = ['user']

    def __str__(self):
        return f"{self.user} ++ ${self.user_amount}"

    def save(self):
        # variable to be used to know how much to add for the user
        add_amount = self.amount_to_add
        if self.status == "APPROVED" and self.amount_to_add > 0:
            # THIS BONUS IS SAVED ON THE USER PROFILE SO AS TO USE IT TO TO SHOW ON THE TOTAL BONUS ACCUMULATION OF THE REFERRER
            bonus = UserProfile.objects.get(user=self.user)
            bonus.bonus_for_referrer = float(self.amount_to_add)*(float(11/100))
            # DELETING THE USER PENDING DEPOSIT IF THER USER EXISTS
            # if PendingDeposit.objects.filter(user=self.user).exists():
            #     PendingDeposit.objects.filter(user=self.user).delete()
            # =================================
            
            # GETTING THE PERCENTAGE FOR FROM THE PLAN THE USER CHOSE
            user_profile = UserProfile.objects.get(user=self.user)
            if UserProfile.objects.filter(user=self.user).exists():
                rate_dict = {
                    "LEVEL 1": 3.1,
                    "LEVEL 2": 5.2,
                    "LEVEL 3": 10.5,
                    # "DIAMOND PLAN": 12
                }
                UserProfile.objects.filter(user=self.user).update(earning_rate=str(rate_dict[user_profile.plan_type])+'%')
            
            # DEFAULTING AMOUNT TO WITHDRAW TO ZERO AS THIS IS USED TO MONITOR THE CURRENT AMOUNT AVAILABLE FOR WITHDRAWAL
            self.amount_to_withdraw = 0.0
            
            # SENDING DEPOSIT PROOF TO THE USER
            wallet_ddr = get_object_or_404(UserProfile, user=self.user)
            wallet_ddr = wallet_ddr.wallet_address_used
            user_email = get_object_or_404(User, username=self.user)
            try:
                email_user_deposit(self.user, self.transaction_referrence, self.amount_to_add, self.date_deposited, wallet_ddr, user_email.email, self.status)      
            except:
                pass

            # Saving the transactions earning record of the user to UserEarningRecord
            if UserEarningRecord.objects.filter(user=self.user).exists():
                user_tran_record = UserEarningRecord.objects.get(user=self.user)
                UserEarningRecord.objects.filter(user=self.user).update(
                    total_deposit=float(user_tran_record.total_deposit) + float(self.amount_to_add),
                    last_deposit=float(self.amount_to_add)
                )
            else:
                user_tran_record = UserEarningRecord.objects.create(
                    user=self.user,
                    total_deposit=self.amount_to_add,
                    total_withdrawal=0.0,
                    last_deposit=self.amount_to_add,
                    last_withdrawal=0.0
                )
                user_tran_record.save()
                
            # SAVING DEPOSIT TO RECENT DEPOSIT
            # deposit = Top10Deposit.objects.create(
            #     username=self.user,
            #     amount=self.amount_to_add
            # )
            # deposit.save()
        
        # ADDING TO AMOUNT_TO_ADD TO AMOUNT_DEPOSITED
        referrer = None
        if UserProfile.objects.filter(user=self.user).exists():
            user_pr = UserProfile.objects.get(user=self.user)
            referrer = user_pr.referrer

        # ADDING TO AMOUNT_TO_ADD TO AMOUNT_DEPOSITED
        if self.status == "APPROVED" and self.amount_to_add > 0:
            self.user_amount = float(self.current_balance) + float(self.amount_to_add)
            self.referrer_bonus = float(self.amount_to_add)*(float(11/100))

            if referrer is not None:
                # MAKING CHANGES TO THE BONUS AND AMOUNT TO BE ADDED TO REFERRER BONUS
                referrer_bonus = ReferralBonus.objects.get(username=referrer)
                referrer_bonus.accumulated_bonus = float(referrer_bonus.accumulated_bonus) + float(self.amount_to_add)*(float(11/100))
                referrer_bonus.save()
                
                # SENDING EMAIL TO USER WHEN DEPOSIT PROCESS IS INITIATED
                referrer = referrer
                referrer_email = User.objects.get(username=referrer).email
                send_mail(
                "Referral Bonus Added",
                f"Hey {referrer}!! Your account has been credited with ${float(self.amount_to_add)*(float(11/100))}, your referral commision of User {self.user}. You now have total of ${referrer_bonus.accumulated_bonus}, you can withdraw at anytime. Warm regards!!",
                settings.EMAIL_HOST_USER,
                [referrer_email]
                )
            self.amount_to_add = 0.0


        # SAVING THE CHANGES TO THE RECORD
        if self.status == "APPROVED":
            if TransactionRecord.objects.filter(transaction_referrence=self.transaction_referrence).exists():
                user_tran_rec = TransactionRecord.objects.filter(transaction_referrence=self.transaction_referrence).order_by("-id").first()
                user_tran_rec.status = self.status
                if add_amount > 0:
                    user_tran_rec.amount = add_amount
                user_tran_rec.save()

        user_obj = super(DepositTransaction, self).save()
        return user_obj


class WithdrawalTransaction(models.Model):
    """RECORDS ALL TEH WITHDRAWAL TRANSACTIONS DONE BY THE USER"""
    user = models.OneToOneField(User, related_name="user_withdrawal_transactions", on_delete=models.CASCADE, help_text="Select the user here")
    amount_to_withdraw = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="Enter the amount the user wants to withdraw")
    withdraw_from = models.CharField(max_length=20, choices=WITHDRAW_FROM)
    withdrawal_date =  models.DateField(default=datetime.now)
    transaction_referrence = models.CharField(max_length=150, help_text="Leave the transaction referrence as it is. It's use for sending the user an email", null=True, blank=True)
    status = models.CharField(max_length=25, choices=STATUS)

    class Meta:
        ordering = ['user']

    def __str__(self):
        return f"{self.user} -- ${self.amount_to_withdraw}"

    def save(self):
        """MAKES SOME CHANGES WHEN THE TRANSACTION IS SAVED"""
        # variable to be used to know how much to add for the user
        add_amount = self.amount_to_withdraw

        # GETTING USER INFO
        wallet_ddr = get_object_or_404(UserProfile, user=self.user)
        wallet_ddr = wallet_ddr.wallet_address_used
        user_email = get_object_or_404(User, username=self.user)
        user_email = user_email.email

        if WithdrawalTransaction.objects.filter(transaction_referrence=self.transaction_referrence).exists():
            user_tran_rec = TransactionRecord.objects.filter(transaction_referrence=self.transaction_referrence).order_by("-id").first()
            if add_amount > 0:
                user_tran_rec.amount = add_amount
            user_tran_rec.status = self.status
            user_tran_rec.save()

            # Saving the transactions earning record of the user to UserEarningRecord
            if UserEarningRecord.objects.filter(user=self.user).exists():
                user_tran_record = UserEarningRecord.objects.get(user=self.user)
                UserEarningRecord.objects.filter(user=self.user).update(
                    total_withdrawal=float(user_tran_record.total_withdrawal) + float(self.amount_to_withdraw),
                    last_withdrawal=float(self.amount_to_withdraw)
                )
            else:
                user_tran_record = UserEarningRecord.objects.create(
                    user=self.user,
                    total_deposit=0.0,
                    total_withdrawal=self.amount_to_withdraw,
                    last_deposit=0.0,
                    last_withdrawal=self.amount_to_withdraw
                )
                user_tran_record.save()

                
            if self.status == "APPROVED" and self.withdraw_from == "ACCOUNT BALANCE":
                # username = user_tran_rec.username
                user_deposit_tran = get_object_or_404(DepositTransaction, user=self.user)
                # user_deposit_tran.user_amount = float(user_deposit_tran.current_balance) - float(self.amount_to_withdraw)
                user_deposit_tran.current_balance = float(user_deposit_tran.current_balance) - float(self.amount_to_withdraw)
                
                # ADDING THE AMOUNT THE USER WANTS TO WITHDRAW TO THE DEPOSIT AMOUNT_TO_WITHDRAW
                user_deposit_tran.amount_to_withdraw = round(float(user_deposit_tran.amount_to_withdraw) + float(self.amount_to_withdraw))

                # SAVING PENDING WITHDRAWAL IF THE USER EXISTS
                # if PendingWithdrawl.objects.filter(user=self.user).exists():
                #     PendingWithdrawl.objects.filter(user=self.user).delete()
                # =================================

                user_deposit_tran.save()
                
                # SENDING EMAIL TO THE USER
                try:
                    email_user_withdrawal(self.user, self.transaction_referrence, self.amount_to_withdraw, self.withdrawal_date, wallet_ddr, user_email, self.status, "ACC")
                except:
                    pass
                
                # SAVING WITHDRAWAL IN TOP10 WITHDRAWAL
                # withdraw = Top10Withdrawal.objects.create(
                # username=self.user,
                # amount=self.amount_to_withdraw
                # )
                
                # withdraw.save()


            elif self.status == "APPROVED" and self.withdraw_from == "REFERRAL BONUS":
                if ReferralBonus.objects.filter(username=self.user).exists():
                    user_bonus = ReferralBonus.objects.get(username=self.user)
                    user_bonus.accumulated_bonus = float(user_bonus.accumulated_bonus) - float(self.amount_to_withdraw)
                    user_bonus.save()

                # SENDING EMAIL TO THE USER
                try:
                    email_user_withdrawal(self.user, self.transaction_referrence, self.amount_to_withdraw, self.withdrawal_date, wallet_ddr, user_email, self.status, "REFF")
                    UserProfile.objects.filter(referrer=self.user).update(bonus_for_referrer=0.0)
                except:
                    pass


        obj = super(WithdrawalTransaction, self).save()
        return obj 

class UserProfile(models.Model):
    """RECORDS THE USER ACCOUNT DETAILS"""
    user = models.OneToOneField(User, related_name="user_profile", on_delete=models.CASCADE)
    plan_type = models.CharField(max_length=50, choices=PLAN_TYPE, default="LEVEL 1")
    earning_rate = models.CharField(max_length=50, choices=EARNING_RATE, default="3.1%")
    referrer = models.CharField(max_length=50, null=True, blank=True)
    bonus_for_referrer = models.DecimalField(default=0.0, max_digits=10, decimal_places=2)
    wallet_address_used = models.CharField(max_length=150, help_text="User wallet address used for last withdrawal transaction", null=True, blank=True)
    bitcoin_address = models.CharField(max_length=150, help_text="User bitcoin wallet address for payment", null=True, blank=True)
    ethereum_address = models.CharField(max_length=150, help_text="User Ethereum wallet address for payment", null=True, blank=True)
    usdt_trc20_address = models.CharField(max_length=150, help_text="User trc20 wallet address for payment", null=True, blank=True)
    usdt_erc20_address = models.CharField(max_length=150, help_text="User erc20 wallet address for payment", null=True, blank=True)
    bnb_address = models.CharField(max_length=150, help_text="User BNB wallet address", null=True, blank=True)
    litecoin_address = models.CharField(max_length=150, help_text="User LITECOIN wallet address for payment", null=True, blank=True)
    tron_address = models.CharField(max_length=150, help_text="User TRON wallet address for payment", null=True, blank=True)
    usdt_bep20_address = models.CharField(max_length=150, help_text="User USDDT BEP20 wallet address for payment", null=True, blank=True)
    perfect_money_address = models.CharField(max_length=150, help_text="User perfect money wallet address for payment", null=True, blank=True)    
    payeer_address = models.CharField(max_length=150, help_text="User payeer wallet address for payment", null=True, blank=True)
    glize_address = models.CharField(max_length=150, help_text="User glize wallet address for payment", null=True, blank=True)
    dogecoin_address = models.CharField(max_length=150, help_text="User dogecoin wallet address for payment", null=True, blank=True)
    usdc_address = models.CharField(max_length=150, help_text="User usdc wallet address for payment", null=True, blank=True)
    polygon_address = models.CharField(max_length=150, help_text="User polygon wallet address for payment", null=True, blank=True)
    litecoin_address = models.CharField(max_length=150, help_text="User litecoin wallet address for payment", null=True, blank=True)
    last_coin_paid = models.CharField(max_length=50, choices=COIN_TYPE, help_text="The coin selected by the user during the last payment", null=True, blank=True, default="BITCOIN")
    class Meta:
        ordering = ['user']

    def __str__(self):
        return f"{self.user}: {self.plan_type}"


class ReferralBonus(models.Model):
    """STORES THE REFERRAL BONUS OF EACH USER"""
    username = models.CharField(max_length=50, unique=True)
    total_person_referred = models.PositiveIntegerField(default=0)
    accumulated_bonus = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, null=True, blank=True, help_text="User can only get bonus when those they referred pay")

    class Meta:
        ordering = ['username']

    def __str__(self):
        return f"{self.username} ++ ${self.accumulated_bonus}"


class TransactionRecord(models.Model):
    """RECORDS ALL THE USER TRANSACTIONS"""
    username = models.CharField(max_length=50)
    amount = models.DecimalField(default=0.0, max_digits=10, decimal_places=2)
    transaction_type = models.CharField(max_length=50)
    transaction_referrence = models.CharField(max_length=150, unique=True)
    date = models.DateField(auto_now_add=True)
    status = models.CharField(max_length=50)

    class Meta:
        ordering = ['username']

    def __str__(self):
        return f"{self.username}: {self.transaction_referrence}"


class AdminWalletAddress(models.Model):
    wallet_type = models.CharField(max_length=50, choices=COIN_TYPE, default="BITCOIN", unique=True)
    wallet_address = models.CharField(max_length=150)

    def __str__(self):
        return f"{self.wallet_type}: {self.wallet_address}"


class Top10Deposit(models.Model):
    """RECORDS THE TOP TEN DEPOSITS OF USER"""
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True, blank=True, null=True)
    amount = models.DecimalField(default=0.0, max_digits=10, decimal_places=2)

    class Meta:
        ordering = ['username']

    def  __str__(self):
        return f"{self.username}"


class Top10Withdrawal(models.Model):
    """RECORDS THE TOP TEN DEPOSITS OF USER"""
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True, blank=True, null=True)
    amount = models.DecimalField(default=0.0, max_digits=10, decimal_places=2)

    class Meta:
        ordering = ['username']

    def  __str__(self):
        return f"{self.username}"


# YOUTUBE VIDEO UPLOAD
class CompanyYoutubeTubeVideo(models.Model):
    title = models.CharField(max_length=50)
    video_url = EmbedVideoField()  # same like models.URLField()

    class Meta:
        ordering = ['-id']
        pass

    def __str__(self):
        return f"{self.title}"


# MODEL FOR SENDING EMAIL TO USERS
class EmailUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    message = models.TextField(max_length=1000)

    def save(self):
        user = User.objects.get(username=self.user)
        user_email = user.email

        send_mail(
        self.title,
        self.message,
        settings.EMAIL_HOST_USER,
        [user_email,]
        )
        return


class UserEarningRecord(models.Model):
    """MODELS TO KEEP THE EARNING OF A USER"""
    user = models.CharField(max_length=50, help_text="Username of the user")
    total_deposit = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="User total deposit")
    total_withdrawal = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="User total withdrawal")
    last_deposit = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="User last deposit")
    last_withdrawal = models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="User last deposit")

    def __str__(self):
        return f"{self.user}: {self.total_deposit}"


class PendingDeposit(models.Model):
    """MODELS TO KEEP RECORD OF PENDING DEPOSIT"""
    user = models.CharField(max_length=50, help_text="Username of the user")
    amount_to_appove =  models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="Amount to be approved\nGo to Deposit Transactions and approve this deposit")
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user}; amount to approve -> {self.amount_to_appove}"

 
class PendingWithdrawl(models.Model):
    """MODELS TO KEEEP RECORD OF PENDING WITHDRAWAL"""
    user = models.CharField(max_length=50, help_text="Username of the user")
    amount_to_withdraw =  models.DecimalField(default=0.0, max_digits=10, decimal_places=2, help_text="Amount to withdraw\nGo to WithdrawalTransactions and approve this withdrawal")
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user}; amount to approve -> {self.amount_to_withdraw}"


