from django.db import models
from helpers.common.basemodel import BaseModel
from helpers.common.choices import ModelChoices
from django.utils.translation import gettext_lazy as _
from p2p_lend.users.models import User, UserAddress
from locations.models import Country, State, City
from django.utils import timezone
from datetime import datetime
from solo.models import SingletonModel #A singleton is a model that has only a single row(a single instance of itself). They can be used for managing global settings for an instance
#Singleton models only saves one instance of itself so whenever we add new changes it overwrites the previous one



class KYCApplication(BaseModel):

	legal_first_name = models.CharField(
		max_length=225,
		verbose_name=_('Legal first name'),
		blank=True, null=True,
		help_text=_("User's first name as shown in documents")
		)

	legal_last_name = models.CharField(
		max_length=225,
		verbose_name=_('Legal last name'),
		blank=True, null=True,
		help_text=_("User's last name as shown in documents")
		)

	date_of_birth = models.DateField(
		verbose_name=_('Date of birth'),
		blank=True, null=True,
		help_text=("User's date of birth as shown in documents"))

	email = models.EmailField(
		max_length=150,
		verbose_name=_('Email Address'),
		blank=True,
		help_text=_("User's primary email address"))

	address_line_1 = models.CharField(
        max_length=125,
		verbose_name=_('Address line 1'),
		help_text=_("User's address line 1. Must be located in the user's country of residence indicated at the time of registration")
		)

	address_line_2 = models.CharField(
        max_length=125,
		verbose_name=_('Address line 2'),
		blank=True, null=True,
		help_text=_("User's address line 2. Must be located in the user's country of residence indicated at the time of registration")
		)

	state = models.ForeignKey(
		State,
		on_delete=models.PROTECT,
		verbose_name=_('State/Region'),
		help_text=_("User's state of residence. Must be located in the user's country of residence indicated at the time of registration"))

	city = models.ForeignKey(
		City,
		on_delete=models.PROTECT,
		verbose_name=_('City'),
		help_text=_("User's city of residence. Must be located in the user's country of residence indicated at the time of registration"))

	zip_post_code = models.CharField(
		max_length=20,
		verbose_name=_('Zip code'),
		help_text=_('User zip code'))

	identification_type = models.CharField(
		max_length=21,
		verbose_name=_('Indentification Type'),
		choices=ModelChoices.PHOTO_IDENTIFICATION_TYPE,
		default='national_id',
		help_text=_("User's type of identification document to prove their identity"))

	address_proof_type = models.CharField(
 		max_length=21,
 		verbose_name=_('Address proof type'),
 		choices=ModelChoices.PROOF_OF_ADDRESS_TYPE,
 		default=ModelChoices.BANK_STATEMENT,
 		help_text=_("User's type of document to prove his address"))

	proof_of_address_document = models.FileField(
 		storage="uploads/kyc/",
 		verbose_name=_('Proof of address document'),
 		# validators=[validate_kyc_file], #a validator raises a ValidationError if it doesn't meet a specified criteria 
 		help_text=_("The user's document that shows his proof of address. It should not be older than 90 days, expired and must have the user's details written on it."))

	photo_id = models.FileField(
 		storage="uploads/kyc/",
 		verbose_name=_('Photo ID(front)'),
 		# validators=[validate_kyc_file], #a validator raises a ValidationError if it doesn't meet a specified criteria 
 		help_text=_("The front part of the user's valid photo id"))

	photo_id_back = models.FileField(
 		storage="uploads/kyc/",
 		verbose_name=_('Photo ID(back)'),
 		# validators=[validate_kyc_file],
 		help_text=_("The back part of the user's valid photo id"))

	selfie_with_id = models.FileField(
 		storage="uploads/kyc/",
 		verbose_name=_('Selfie with ID'),
 		# validators=[validate_setting_image],
 		blank=True, null=True,
 		help_text=_("User's photo of themself with their id. The face of the user and the document must be visible")) 

	kyc_status = models.CharField(
		verbose_name=('KYC Status'),
		choices=ModelChoices.KYC_STATUS,
		default='Unverified',
		max_length=25,
		# blank=True, null=True,
		help_text=_("KYC status of the client.")
		)

	kyc_status_note = models.TextField(
 		verbose_name=_('KYC status note'),
 		editable=False,
 		blank=True, null=True,
 		help_text=_("Reason for current KYC status"))

	status_update_date = models.DateTimeField(
 		default=timezone.now,
 		verbose_name=_('Status update time'),
 		editable=False,
 		help_text=_('Timestamp when status was updated'))

	politically_exposed_person = models.CharField(
		verbose_name=_('Politically Exposed Person(PEP)'),
		choices=ModelChoices.PEP_CHOICES,
		max_length=16,
		default='not_pep',
		help_text=_("""A politically exposed person(PEP) is one who has been entrusted with 
			a prominent public function. A PEP generally present a higher risk for potential involvement in bribery
			and corruption by virtue of their position and the influence that they may hold. 'not_pep'
			implies the user is not politically exposed and 'pep' implies the user is. """))

	place_of_birth = models.CharField(
		verbose_name=_('Place of birth'),
		max_length=225,
		blank=True, null=True,
		help_text=_("User's place of birth"))

	identification_number = models.CharField(
		verbose_name=_('Identification number'),
		max_length=100,
		blank=True, null=True,
		help_text=_("User's identification number"))

	identification_issue_date = models.DateField(
		verbose_name=_('Identification issue date'),
		blank=True, null=True,
		help_text=_("The issue date of the user's identification document"))

	identification_expiry_date = models.DateField(
		verbose_name=_('Identification expiry date'),
		blank=True, null=True,
		help_text=_("The expiry date of the user's identification document"))

	kyc_submitted_ip_address = models.GenericIPAddressField(
		verbose_name=_('KYC submitted IP address'),
		blank=True, null=True,
		editable=False,
		help_text=_("User's IP address recorded at the time of registration")
		)

	registered_ip_address = models.GenericIPAddressField(
		verbose_name=_('Registered IP address'),
		blank=True, null=True,
		editable=False,
		help_text=_("User's IP address recorded at the time of registration. This address is compared to the kyc_submitted_ip_address to make sure the user is still within the same region")
		)

	# reference = models.CharField(
	# 	default=Generators.generate_reference,
	# 	verbose_name=_('Reference'),
	# 	max_length=10,
	# 	help_text=_('Auto generated refernce for KYC application. A transaction reference number helps to identify transactions in records and used to monitor transactions associuated with a card payment')
	# 	)


	citizenship = models.ForeignKey(
		Country,
		verbose_name=_('Citizenship'),
		on_delete=models.CASCADE,
		related_name='+',
		help_text=_("The citizenship of the user as shown in documents"))

	second_citizenship = models.ForeignKey(
		Country,
		blank=True, null=True,
		verbose_name=_('Second citizenship'),
		on_delete=models.CASCADE,
		related_name='+',
		help_text=_("Second citizenship of the user as shown in documents"))

	country_residence = models.ForeignKey(
		Country,
		verbose_name=_('Country of residence'),
		blank=True,
		on_delete=models.CASCADE,
		help_text=_("The country of residence of the user as shown in documents")
		)

	kyc_country = models.ForeignKey(
		Country,
		verbose_name=_('KYC Country'),
		blank=True, null=True,
		on_delete=models.PROTECT,
		related_name='kyc_country', #helps us resolve clashes with similar models
		help_text=_("The country which the KYC has been performed against the user. Each country has different KYC requirements")
		)

	user = models.ForeignKey(
		User,
		verbose_name=_('KYC User'),
		on_delete=models.CASCADE,
		help_text=_("The unique identifier of the user")
		)

	reviewer = models.ForeignKey(
		User,
		verbose_name=_('Reviewer'),
		blank=True, null=True,
		on_delete=models.CASCADE,
		related_name='kyc_reviewer',
		help_text=_("The KYC staff or representative who checked and reviewed the KYC application")
		)

	kyc_review_date = models.DateTimeField(
		verbose_name=_('KYC review date'),
		blank=True, null=True,
		editable=False,
		help_text=_("The country of residence of the user as shown in documents")
		)

	reviewer_ip_address = models.GenericIPAddressField(
		verbose_name=_('Reviewer IP address'),
		blank=True, null=True,
		editable=False,
		help_text=_("Reviewer's IP address recorded at the time of registration. This address is compared to the kyc_submitted_ip_address to make sure the user is still within the same region")
		)

	kyc_refused_code = models.CharField(
		verbose_name=_('KYC refused code'),
		max_length=35,
		choices=ModelChoices.KYC_REFUSE_REASON_CODE,
		blank=True, null=True,
		help_text=_("The reason for the refusal")
		)

	us_citizen_tax_resident = models.BooleanField(
		default=False,
		verbose_name=_('US citizen tax resident'),
		help_text=_("Indicates whether the user is a citizen/tax resident of the US or not"))

	accept_terms = models.BooleanField(
		default=False,
		verbose_name=_('Accept terms'),
		help_text=_("Agreement collected from the user to accept the terms and conditions"))

	agreed_to_data_usage = models.BooleanField(
		default=False,
		verbose_name=_('Agree to data usage'),
		help_text=_("Agreement collected from the user to gain consent to use their provided data"))

	
	class Meta:
		verbose_name = _('KYC Application')
		verbose_name_plural = _('KYC Applications')
		db_table = 'kyc_applications'
		permissions = [
			("verify_kyc", _("Verify KYC Application")),
			("reject_kyc", _("Reject KYC Application")),
			("merge_kyc", _("Merge KYC Application with User Information")),
			]

	def __str__(self):
		return _("KYC #: ") + self.reference

	@property
	def age(self):
		return int((datetime.now().date() - self.date_of_birth).days / 365.25) #Calculates the user's age

	def get_user(self):
		return str(self.user.pk)

	get_object_user = property(get_user)

	# def clean_fields(self, exclude=None):
	# 	super().clean_fields(exclude=exclude)
	# 	if self.identification_issue_date == self.identification_expiry_date:
	# 		raise ValidationError(
	# 		{
	# 			'identification_issue_date': _("ID issue date and Expiry date cannot be the same."),
	# 		}

	# 			)
	# 	if self.identification_issue_date > datetime.today():
	# 		raise ValidationError(
	# 			{
	# 			'identification_issue_date': _("ID issue date is ahead of today."),
	# 		}
	# 			)
	# 	if self.identification_issue_date == datetime.today() or self.identification_expiry_date < date.today():
	# 		raise ValidationError(
	# 			{
	# 			'identification_issue_date': _("ID has expired."),
	# 		}
	# 			)
	

class KYCSetting(SingletonModel):
	#This model represents KYC settings and configs

	#Choices
	#Setting for if a user wants to use the manual or automatic KYC verification
	MANUAL = 'manual'  #Uses a KYC form that is filled and reviewed by a KYC staff
	AUTOMATIC = 'automatic'	#Uses an api service gotten from a KYC provider to complete the process

	KYC_SYSTEM_TYPE = (
		(MANUAL, _('Manual KYC')),
		(AUTOMATIC, _('Automatic KYC'))
		)

	singleton_instance_id = 1 

	enable_kyc = models.BooleanField(
		default=True,
		verbose_name=_('Enable KYC Verification'),
		help_text=_('Activates or Deactivates KYC application on the system'))

	allow_resubmission = models.BooleanField(
		default=False,
		verbose_name=_('Allow KYC Re-submission'),
		help_text=_("Allows User to resubmit KYC application if the previous attempt failed. This can only be done a number of times"))

	number_of_kyc_tries = models.PositiveIntegerField(
		default=1,
		verbose_name=_('Allow KYC tries'),
		help_text=_("Number of times a user is allowed to attempt KYC application"))

	run_check_on_expiry = models.BooleanField(
		default=False,
		verbose_name=_('Run check on Expiry'),
		help_text=_("Automated checks to find out if a user's ID has expired"))

	days_to_send_notification = models.PositiveIntegerField(
		default=30,
		verbose_name=_('Verification Notification'),
		help_text=_("If run check on expiry is turned on, indicate the number of days which the client receives a reminder of ID expiration and request for re-verification"))

	review_frequency = models.PositiveIntegerField(
		default=30,
		verbose_name=_('Review Frequency'),
		help_text=_("The amount of time on which a User must be reviewed"))

	kyc_system_type = models.CharField(
		choices=KYC_SYSTEM_TYPE,
		default=AUTOMATIC,
		verbose_name=_('KYC System Type'),
		max_length=10,
		help_text=_("Type of KYC system the User prefers to use"))


	class Meta:

		verbose_name = _('KYC Setting')
		verbose_name_plural = _('KYC Settings')

	def __str__(self):
		return 'KYC Setting'


