from django.contrib.auth.models import User, Group
from rest_framework import serializers
from .models import *
from users.serializers import UserSerializer

# USER DEFINED MODEL SERIALIZERS
class AgreementSerializer(serializers.ModelSerializer):
    class Meta:
        model = Agreement
        fields = ('id', 'isSign', 'signature', 'message')


class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = ('id', 'apartment', 'street', 'city', 'state', 'country',
                  'state', 'country', 'postCode', 'zipCode')


class UserHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = UserHistory
        fields = ('id', 'actionDate', 'actionPerformed', 'actionDescription',
                  'platform')


class UserDocumentSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserDocument
        fields = ('id', 'name', 'nameHash', 'purpose')


class UserInfoSerializer(serializers.ModelSerializer):
    user =  UserSerializer(read_only=True)
    agreement = AgreementSerializer(read_only=True)
    address = AddressSerializer()
    document = UserDocumentSerializer(read_only=True)

    class Meta:
        model = UserInfo
        fields = ("firstName", "lastName", "otherName", "dateOfBirth",
                  "gender", "email", "mobilePhone", "photoUrl", 'user',
                  'agreement', 'address', 'document')

    def create(self, validated_data):
        address = validated_data.pop('address')
        userInfo = UserInfo.objects.create(**validated_data)
        address.objects.create(userInfo, **address)
        return userInfo


class UAccountSerializer(serializers.ModelSerializer):
    userInfo = UserInfoSerializer(read_only=True)

    class Meta:
        model = UAccount
        fields = ('phone', 'uAccountType', 'allowOTP', "userInfo")


class BranchSerializer(serializers.ModelSerializer):
    manager = 'EmployeeSerializer'

    class Meta:
        model = Branch
        fields = ('location', 'manager')


class EmployeeSerializer(serializers.ModelSerializer):
    userInfo = UserInfoSerializer(read_only=True)
    branch = BranchSerializer()

    class Meta:
        model = Employee
        fields = ('workId', 'type', 'employedDate', 'userInfo', 'branch')

    def create(self, validated_data):
        branch = validated_data.pop('branch')
        employee = Employee.objects.create(**validated_data)
        branch.objects.create(employee, **branch)
        return employee


class WithdrawalSchemeSerializer(serializers.ModelSerializer):
    class Meta:
        model = WithdrawalScheme
        fields = ('name', 'totalAllowedWithdrawals', 'numOfWithdrawals',
                  'allowedDates', 'penaltyRate', 'maxAmountAllowed',
                  'lastWithdrawal', 'emergencyAllowedWithdrawals',
                  'customWithdrawalInterval')


class ReportSchemeSerializer(serializers.ModelSerializer):
    class Meta:
        model = ReportScheme
        fields = ('name', 'accountId', 'accountType', 'planType',
                  'accountHolderName', 'transactions', 'currentBalance',
                  'interestScheme', 'aim', 'genFrequency')


class RewardSchemeSerializer(serializers.ModelSerializer):
    class Meta:
        model = RewardScheme
        fields = ('name', 'rewardType', 'methodOfCalc')


class InterestSchemeSerializer(serializers.ModelSerializer):
    class Meta:
        model = InterestScheme
        fields = ('name', 'interestRate', "interestType", "frequency")


class SavingsSchemeSerializer(serializers.ModelSerializer):
    plan = "SavingsPlanSerializer"

    class Meta:
        model = SavingsScheme
        fields = ('name', 'miniPrincipal', 'minLumpsum', 'savingsType',
                  'savingsFrequency', 'allowSwiftSave', 'allowESave',
                  'allowMultiple', 'allowInterest', 'minimumInvestPeriod')
        read_only_fields = ('plan', )


class CustomerSerializer(serializers.ModelSerializer):
    userInfo = UserInfoSerializer(read_only=True)
    rewardScheme = RewardSchemeSerializer(read_only=True)

    class Meta:
        model = Customer
        fields = ('homePhone', 'emergencyPhone', "userInfo", 'rewardScheme')


class DAccountSerializer(serializers.ModelSerializer):
    withdrawalScheme = WithdrawalSchemeSerializer(read_only=True),
    accountHolder = CustomerSerializer(read_only=True)
    branch = BranchSerializer(read_only=True)
    creator = EmployeeSerializer(read_only=True)
    reportScheme = ReportSchemeSerializer(read_only=True)
    history = 'DAccountHistorySerializer'

    class Meta:
        model = DAccount
        fields = ('accountNumber', 'balance', 'amountWithdrawable',
                  'freeWithdrawalBalance', 'lockUpPeriod', 'isUnlocked',
                  'status', 'accountType', 'dateCreated', "withdrawalScheme",
                  "accountHolder", 'branch', 'creator', 'reportScheme',
                  "history")
        read_only_fields = ('history', )


class InterestHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = InterestHistory
        fields = ('message', )


class TransferHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = TransferHistory
        fields = ('message', )


class DebitHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = DebitHistory
        fields = ('message', )


class CreditHistorySerializer(serializers.ModelSerializer):
    class Meta:
        model = CreditHistory
        fields = ('message', )


class DAccountHistorySerializer(serializers.ModelSerializer):
    interestHistory = InterestHistorySerializer()
    transferHistory = TransferHistorySerializer()
    debitHistory = DebitHistorySerializer()
    creditHistory = CreditHistorySerializer()

    class Meta:
        model = DAccountHistory
        fields = ('interestHistory', 'transferHistory', "debitHistory",
                  "creditHistory")

    def create(self, validated_data):
        interestHistory = validated_data.pop('interestHistory')
        transferHistory = validated_data.pop('transferHistory')
        debitHistory = validated_data.pop('debitHistory')
        creditHistory = validated_data.pop('creditHistory')

        history = DAccountHistory.objects.create(**validated_data)
        if (interestHistory.is_valid()):
            interestHistory.objects.create(history, **interestHistory)
        if (transferHistory.is_valid()):
            transferHistory.objects.create(history, **transferHistory)
        if (debitHistory.is_valid()):
            debitHistory.objects.create(history, **debitHistory)
        if (creditHistory.is_valid()):
            creditHistory.objects.create(history, **creditHistory)
        return history


class DAccountTransConfirmationSerializer(serializers.ModelSerializer):
    transaction = 'DTransactionSerializer'

    class Meta:
        model = DAccountTransConfirmation
        fields = ('initiatedTime', 'abortionTime', 'isConfirmed')
        read_only_fields = ('DTransactionSerializer', )


class DAccountTransVerificationSerializer(serializers.ModelSerializer):
    transaction = 'DTransactionSerializer'

    class Meta:
        model = DAccountTransVerification
        fields = ('message', 'isVerified')
        read_only_fields = ('DTransactionSerializer', )


class CreditSerializer(serializers.ModelSerializer):
    transaction = 'DTransactionSerializer'

    class Meta:
        model = Credit
        fields = ('amount', )
        read_only_fields = ('DTransactionSerializer', )


class DebitSerializer(serializers.ModelSerializer):
    transaction = 'DTransactionSerializer'

    class Meta:
        model = Debit
        fields = ('amount', )
        read_only_fields = ('DTransactionSerializer', )


class TransferSerializer(serializers.ModelSerializer):
    transaction = 'DTransactionSerializer'

    class Meta:
        model = Transfer
        fields = ('amount', )
        read_only_fields = ('DTransactionSerializer', )


class DTransactionSerializer(serializers.ModelSerializer):
    initiator = EmployeeSerializer(read_only=True)
    confirmation = DAccountTransConfirmationSerializer()
    verification = DAccountTransVerificationSerializer()
    debit = DebitSerializer()
    credit = CreditSerializer()
    transfer = TransferSerializer()

    class Meta:
        model = DTransaction
        fields = ('id', 'initiator', 'confirmation', "verification", 'debit',
                  'credit', 'transfer')

    def create(self, validated_data):
        confirmation = validated_data.pop('confirmation')
        verification = validated_data.pop('verification')
        debit = validated_data.pop('debit')
        credit = validated_data.pop('credit')

        transaction = DTransaction.objects.create(**validated_data)
        if (confirmation.is_valid()):
            confirmation.objects.create(transaction, **confirmation)
        if (verification.is_valid()):
            verification.objects.create(transaction, **verification)
        if (debit.is_valid()):
            debit.objects.create(transaction, **debit)
        if (credit.is_valid()):
            credit.objects.create(transaction, **credit)

        return transaction


class DCardHistorySerializer(serializers.ModelSerializer):
    card = "DAccountCardSerializer"

    class Meta:
        model = DCardHistory
        fields = ('message', "dateCreated", 'card')
        read_only_field = ('card', )


class DAccountCardSerializer(serializers.ModelSerializer):
    history = DCardHistorySerializer()
    accountHolder = CustomerSerializer(read_only=True)
    linkedAccount = DAccountSerializer(read_only=True)
    transaction = DTransactionSerializer()

    class Meta:
        model = DAccountCard
        fields = ('cardType', 'lastUsed', 'history', 'accountHolder',
                  'linkedAccount', 'transaction')


class SavingsPlanSerializer(serializers.ModelSerializer):
    savingsScheme = SavingsSchemeSerializer(read_only=True)
    account = DAccountSerializer()
    aim = "AimSerializer"
    fundSource = "FundSourceSerializer"
    class Meta:
        model = SavingsPlan
        fields = ('interestAccred', 'lumpSum', 'savingsScheme', 
        'account', 'aim','fundSource')

    def create(self, validated_data):
        account = validated_data.pop('account')
        aim = validated_data.pop('aim')
        fundSource = validated_data.pop('fundSource')
        plan = SavingsPlan.objects.create(**validated_data)
        if (account.is_valid()):
            account.objects.create(plan, **account)
        if (aim.is_valid()):
            aim.objects.create(plan, **aim)
        if (fundSource.is_valid()):
            fundSource.objects.create(plan, **fundSource)
        return plan


class AimSerializer(serializers.ModelSerializer):
    class Meta:
        model = Aim
        fields = ('name', 'targetDate', 'calculatedAmount', 'savingsFreq')


class FundSourceSerializer(serializers.ModelSerializer):
    bank = "ExternalBankSerializer"
    plans = SavingsPlanSerializer(read_only = True)
    class Meta:
        model = FundSource
        fields = ('sourceType', 'bank', 'plans')
    
    def create(self, validated_data):
        bank = validated_data.pop('bank')
        source = FundSource.objects.create(**validated_data)

        if (bank.is_valid()):
            bank.objects.create(source, **bank)
        return source

class ExternalBankSerializer(serializers.ModelSerializer):
    class Meta:
        model = ExternalBank
        fields = ('accountName', 'accountNumber', 'accountType',
                  'allowedUSSDTrans', 'allowedPhoneTrans', 'bankName',
                  'bankId')
