from django.db import models
from django.contrib.auth.models import User
from datetime import date
# Create your models here.

from django.db import models

class UserInfo(models.Model):
    GENDER = (("MALE", "M"), ("FEMALE", "F"), ("OTHER", "O"))
    firstName = models.CharField(max_length=100)
    lastName = models.CharField(max_length=100)
    otherName = models.CharField(max_length=100,  blank=True)
    dateOfBirth = models.DateField()
    gender = models.CharField(
        max_length=1,
        choices=GENDER,
    )
    email = models.CharField(max_length=100)
    mobilePhone = models.CharField(max_length=100)
    photoUrl = models.CharField(max_length=500,  blank=True)
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        primary_key=True,
    )


class UserHistory(models.Model):
    actionDate = models.DateField()
    actionPerformed = models.CharField(max_length=300)
    actionDescription = models.CharField(max_length=500)
    platform = models.CharField(max_length=100)
    #RELATIONS
    user = models.ForeignKey(UserInfo, related_name="history", on_delete=models.CASCADE)


class Agreement(models.Model):
    isSign = models.BooleanField()
    signature = models.CharField(max_length=300)
    message = models.CharField(max_length=500)
    date = models.DateField(default=date.today)
    #RELATIONS
    user = models.ForeignKey(UserInfo, related_name="agreement", on_delete=models.CASCADE)


class UserDocument(models.Model):
    name = models.CharField(max_length=100)
    nameHash = models.CharField(max_length=500)
    purpose = models.CharField(max_length=300)
    #RELATIONS
    user = models.ForeignKey(UserInfo, on_delete=models.CASCADE)


class Address(models.Model):
    apartment = models.CharField(max_length=200)
    street = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100, blank=True)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    postCode = models.CharField(max_length=100, blank=True)
    zipCode = models.CharField(max_length=100, blank=True)
    #RELATIONS
    user = models.ForeignKey(UserInfo, on_delete=models.CASCADE)


class UAccount(models.Model):
    UACCOUNTTYPE = (("EMPLOYEE", "EM"), ("CUSTOMER", "CU"), ("REGULAR", "RE"))
    phone = models.CharField(max_length=20)
    uAccountType = models.CharField(
        max_length=8, choices=UACCOUNTTYPE, default="REGULAR")
    allowOTP = models.BooleanField()
    #RELATIONS
    user = models.OneToOneField(
        UserInfo,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name="uaccount"
    )





class Branch(models.Model):
    location = models.CharField(max_length=20)
    manager = models.OneToOneField(
        'Employee',
        related_name="manager_branch",
        on_delete=models.SET_NULL,
        blank = True, 
        null = True
    )
 

class Employee(models.Model):
    workId = models.CharField(max_length=20)
    type = models.CharField(max_length=20)
    employedDate = models.DateField()
    #RELATIONS
    user = models.OneToOneField(
        UserInfo,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    branch = models.ForeignKey(Branch, related_name="branch", on_delete = models.PROTECT)


class WithdrawalScheme(models.Model):
    name = models.CharField(max_length=100)
    totalAllowedWithdrawals = models.IntegerField()
    numOfWithdrawals = models.IntegerField()
    allowedDates = models.CharField(max_length=500)
    penaltyRate = models.FloatField()
    maxAmountAllowed = models.FloatField()
    lastWithdrawal = models.DateField()
    emergencyAllowedWithdrawals = models.IntegerField()
    customWithdrawalInterval = models.IntegerField()  # in months


class ReportScheme(models.Model):
    GEN_FREQUENCY = (("DAILY", "DA"),("WEEKLY", "WE"), ("MON", "MON"),
                     ("QUATERLY", "QUA"), ("SEMIANUM", "SEM"), ("YEARLY", "YEA"))
    name = models.CharField(max_length=100)
    accountId = models.BooleanField()
    accountType = models.BooleanField()
    planType = models.BooleanField()
    accountHolderName = models.BooleanField()
    transactions = models.BooleanField()
    currentBalance = models.BooleanField()
    interestScheme = models.BooleanField()
    aim = models.BooleanField()
    genFrequency = models.CharField(max_length=1, choices=GEN_FREQUENCY)


class RewardScheme(models.Model):
    REWARD_TYPE = (("REFERRALS", "REF"), ("BONUS", "BON"))
    CALCULATION_METHOD = (("NOTAPPLY", "NO"), ("ASSIGN", "AS"), ("REFERAL", "RE"))
    name = models.CharField(max_length=500)
    rewardType = models.CharField(max_length=1, choices=REWARD_TYPE)
    methodOfCalc = models.CharField(max_length=1, choices=CALCULATION_METHOD)


class InterestScheme(models.Model):
    INTEREST_FREQ = (("DAILY", "DA"), ("WEEKLY", "WE"), ("MONTHLY", "MON"), ("YEARLY",
                                                                       "YE"))
    TYPE = (("SIMPLE_INTEREST", "SI"), ("COMPOUND_INTEREST", "CI"))
    name = models.CharField(max_length=100)
    interestRate = models.FloatField()
    interestType = models.CharField(max_length=1, choices=TYPE)
    frequency = models.CharField(max_length=1, choices=INTEREST_FREQ)


class SavingsScheme(models.Model):
    SAVINGS_TYPE = (("SMART_SAVE", "SMART"), ("SELECT_SAVE", "SELECT"),
                    ("SECURE_SAVE", "SECURE"), ("KID_SAVE", "KID"))

    SAVINGS_FREQUENCY = (("DAILY", "D"), ("WEEKLY", "W"), ("MONTHLY", "M"))

    name = models.CharField(max_length=100)
    miniPrincipal = models.FloatField()
    minLumpsum = models.FloatField()
    savingsType = models.CharField(max_length=8, choices=SAVINGS_TYPE)
    savingsFrequency = models.CharField(
        max_length=1, choices=SAVINGS_FREQUENCY)
    allowSwiftSave = models.BooleanField()
    allowESave = models.BooleanField()
    allowMultiple = models.BooleanField()
    allowInterest = models.BooleanField()
    minimumInvestPeriod = models.IntegerField()
    interestCalScheme = models.OneToOneField(
        InterestScheme,
        on_delete=models.CASCADE,
        primary_key=True,
    )


class Customer(models.Model):
    homePhone = models.CharField(max_length=100)
    emergencyPhone = models.CharField(max_length=100)

    # Relationships of entities
    # scheme can contains many customers
    rewardScheme = models.ForeignKey(RewardScheme, on_delete=models.CASCADE)
    # user can be a customer
    user = models.OneToOneField(
        UserInfo,
        on_delete=models.CASCADE,
        primary_key=True,
    )


# Create your models here.
class DAccount(models.Model):
    DACCOUNT_STATUS = (("LOCKED", 'LCK'), ("INACTIVE", 'INA'), ("ACTIVE", 'ACT'))
    DACCOUNT_TYPE = (("CORE_ACCOUNT", 'CORE'), ("SAVINGS_PLAN", 'SAVINGS'))

    # question = models.ForeignKey(Question, on_delete=models.CASCADE)
    accountNumber = models.CharField(max_length=20)
    balance = models.FloatField()
    amountWithdrawable = models.FloatField()
    freeWithdrawalBalance = models.FloatField()
    lockUpPeriod = models.IntegerField()
    isUnlocked = models.BooleanField()
    status = models.CharField(
        max_length=3,
        choices=DACCOUNT_STATUS,
        default="LOCKED",
    )
    accountType = models.CharField(max_length=8, choices=DACCOUNT_TYPE)
    dateCreated = models.DateField()
    # RELATIONSHIPS
    accountHolder = models.ForeignKey(Customer, on_delete=models.CASCADE)
    branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
    creator = models.ForeignKey(Employee, on_delete=models.CASCADE)
    withdrawalScheme = models.ForeignKey(
        WithdrawalScheme, on_delete=models.CASCADE)
    reportScheme = models.ForeignKey(ReportScheme, on_delete=models.CASCADE)

    def __str__(self):
        return self.accountNumber

    class Meta:
        ordering = ('accountNumber', )


class DAccountHistory(models.Model):
    ''' Keeps all the history of the account including credit, transfer, visits, debits and all activities'''
    account = models.ForeignKey(DAccount, related_name='history', on_delete=models.CASCADE)


class InterestHistory(models.Model):
    message = models.CharField(max_length=500)
    account = models.ForeignKey(DAccountHistory, related_name='interestHistory', on_delete=models.CASCADE)


class TransferHistory(models.Model):
    message = models.CharField(max_length=500)
    account = models.ForeignKey(DAccountHistory, related_name='transferHistory', on_delete=models.CASCADE)


class DebitHistory(models.Model):
    message = models.CharField(max_length=500)
    account = models.ForeignKey(DAccountHistory, related_name='debitHistory', on_delete=models.CASCADE)


class CreditHistory(models.Model):
    message = models.CharField(max_length=500)
    account = models.ForeignKey(DAccountHistory, related_name='creditHistory',on_delete=models.CASCADE)


class DTransaction(models.Model):
    ''' Executing and monitoring all forms Transactions '''
    initiator = models.ForeignKey(Employee, related_name='transaction', on_delete=models.CASCADE)



class DAccountTransConfirmation(models.Model):
    initiatedTime = models.DateField()
    abortionTime = models.DateField()
    isConfirmed = models.BooleanField()
    transaction = models.OneToOneField(
        DTransaction,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "confirmation"
    )


class DAccountTransVerification(models.Model):
    message = models.CharField(max_length=500)
    isVerified = models.BooleanField()
    transaction = models.OneToOneField(
        DTransaction,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "verification"
    )


class Credit(models.Model):
    account = models.ForeignKey(DAccount, on_delete=models.CASCADE)
    amount = models.FloatField()
    transaction = models.OneToOneField(
        DTransaction,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "credit",
        blank = True,
    )


class Debit(models.Model):
    account = models.ForeignKey(DAccount, on_delete=models.CASCADE)
    amount = models.FloatField()
    transaction = models.OneToOneField(
        DTransaction,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "debit",
        blank = True,
    )


class Transfer(models.Model):
    creditAccount = models.ForeignKey(DAccount, on_delete=models.CASCADE, related_name="creditAccount")
    debitAccount = models.ForeignKey(DAccount, on_delete=models.CASCADE, related_name="debitAccount")
    amount = models.FloatField()
    transaction = models.OneToOneField(
        DTransaction,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "transfer",
        blank = True,
    )


class DCardHistory(models.Model):
    message = models.CharField(max_length=500)
    dateCreated = models.DateField()

class DAccountCard(models.Model):
    ''' Define the cards that should be used for transactions, Multiple cards permitted'''
    CARD_TYPE = (("DIAMOND", "DI"), ("GOLD", "GO"), ("BRONZE", "BR"))
    cardType = models.CharField(max_length=3, choices=CARD_TYPE)
    lastUsed = models.DateField()
    
    history = models.ForeignKey(DCardHistory,
    related_name="card",  on_delete=models.CASCADE)
    accountHolder = models.ForeignKey(Customer,
    related_name="card",  on_delete=models.CASCADE)
    linkedAccount = models.OneToOneField(
        DAccount,
        on_delete=models.CASCADE,
        primary_key=True,
        related_name = "account"
    )
    transaction = models.ForeignKey(DTransaction,
    related_name="card", on_delete=models.CASCADE)



class SavingsPlan(models.Model):
    account = models.OneToOneField(
        DAccount,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    interestAccred = models.FloatField()
    lumpSum = models.FloatField()
    savingsScheme = models.OneToOneField(
        SavingsScheme,
        on_delete=models.SET_NULL,
        blank = True,
        null = True, 
        related_name='plan'
    )


class Aim(models.Model):
    SAVE_FREQ = (("DAILY", "DA"), ("WEEKLY", "WE"), ("MONTHLY", "MO"), ("YEARLY",
                                                                  "YE"))
    name = models.CharField(max_length=50)
    targetDate = models.DateField()
    calculatedAmount = models.FloatField()
    savingsFreq = models.CharField(max_length=3, choices=SAVE_FREQ)
    plan = models.ForeignKey(SavingsPlan,
    related_name="aim", on_delete=models.CASCADE)


class FundSource(models.Model):
    FUND_SOURCE = (("EXTERNAL_BANK", 'EB'), ("CARD_TRANSFER", 'CT'),
                   ("PERSONAL_DEPOSIT", 'PD'))
    sourceType = models.CharField(
        max_length=3,
        choices=FUND_SOURCE,
        default="PERSONAL_DEPOSIT",
    )
    fundSource = models.ForeignKey(SavingsPlan,
    related_name = "fundSource", on_delete=models.CASCADE)


class ExternalBank(models.Model):
    accountName= models.CharField(max_length=100)
    accountNumber = models.CharField(max_length=20)
    accountType = models.CharField(max_length=100)
    allowedUSSDTRans = models.BooleanField()
    allowedPhoneTrans = models.BooleanField()
    bankName = models.CharField(max_length = 100)
    bankId = models.CharField(max_length = 100)
    fund = models.OneToOneField(
        FundSource,
        on_delete=models.CASCADE,
        blank = True,
        null = True, 
        related_name = 'bank'
    )