from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from uuid import uuid4


class User(models.Model):
	class Role(models.TextChoices):
		BUYER = "buyer", "Buyer"
		SELLER = "seller", "Seller"
		ADMIN = "admin", "Admin"
		MODERATOR = "moderator", "Moderator"

	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	phone = models.CharField(max_length=20, unique=True)
	name = models.CharField(max_length=100, null=True, blank=True)
	email = models.EmailField(max_length=180, unique=True, null=True, blank=True)
	pin_hash = models.CharField(max_length=255, null=True, blank=True)
	role = models.CharField(max_length=10, choices=Role.choices, default=Role.BUYER)
	kyc_level = models.PositiveSmallIntegerField(default=0)
	is_verified = models.BooleanField(default=False)
	reputation_score = models.DecimalField(max_digits=3, decimal_places=2, default=0.00)
	total_deals = models.IntegerField(default=0)
	completed_deals = models.IntegerField(default=0)
	fcm_token = models.CharField(max_length=255, null=True, blank=True)
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)

	class Meta:
		db_table = "users"

	def __str__(self):
		return self.phone


class Wallet(models.Model):
	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	user = models.OneToOneField("core.User", on_delete=models.CASCADE, related_name="wallet")
	balance = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
	held_balance = models.DecimalField(max_digits=15, decimal_places=2, default=0.00)
	currency = models.CharField(max_length=3, default="TZS")
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)

	class Meta:
		db_table = "wallets"

	def __str__(self):
		return f"{self.user.phone} wallet"


class Notification(models.Model):
	class Channel(models.TextChoices):
		PUSH = "push", "Push"
		SMS = "sms", "SMS"
		EMAIL = "email", "Email"
		IN_APP = "in_app", "In App"

	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	user = models.ForeignKey("core.User", on_delete=models.CASCADE, related_name="notifications")
	deal = models.ForeignKey("escrow.Deal", on_delete=models.SET_NULL, related_name="notifications", null=True, blank=True)
	title = models.CharField(max_length=120)
	body = models.TextField()
	channel = models.CharField(max_length=10, choices=Channel.choices, default=Channel.IN_APP)
	is_read = models.BooleanField(default=False)
	sent_at = models.DateTimeField(null=True, blank=True)
	created_at = models.DateTimeField(auto_now_add=True)

	class Meta:
		db_table = "notifications"

	def __str__(self):
		return f"{self.user.phone} - {self.title}"


class OtpCode(models.Model):
	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	user = models.ForeignKey("core.User", on_delete=models.SET_NULL, related_name="otp_codes", null=True, blank=True)
	phone = models.CharField(max_length=20, db_index=True)
	role = models.CharField(max_length=10, choices=User.Role.choices, null=True, blank=True)
	code = models.CharField(max_length=10)
	purpose = models.CharField(max_length=32)
	expires_at = models.DateTimeField()
	consumed_at = models.DateTimeField(null=True, blank=True)
	attempts = models.PositiveSmallIntegerField(default=0)
	created_at = models.DateTimeField(auto_now_add=True)

	class Meta:
		db_table = "otp_codes"
		indexes = [
			models.Index(fields=["phone", "purpose"]),
		]

	def __str__(self):
		return f"{self.phone} ({self.purpose})"


class KycSubmission(models.Model):
	class Status(models.TextChoices):
		PENDING = "pending", "Pending"
		APPROVED = "approved", "Approved"
		REJECTED = "rejected", "Rejected"

	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	user = models.OneToOneField("core.User", on_delete=models.CASCADE, related_name="kyc_submission")
	full_name = models.CharField(max_length=120)
	nin = models.CharField(max_length=30, db_index=True)
	nida_image = models.FileField(upload_to="kyc/nida/")
	status = models.CharField(max_length=10, choices=Status.choices, default=Status.PENDING)
	review_notes = models.TextField(null=True, blank=True)
	submitted_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)

	class Meta:
		db_table = "kyc_submissions"

	def __str__(self):
		return f"{self.user.phone} ({self.status})"


class DeviceToken(models.Model):
	class Platform(models.TextChoices):
		ANDROID = "android", "Android"
		IOS = "ios", "iOS"
		WEB = "web", "Web"
		UNKNOWN = "unknown", "Unknown"

	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	user = models.ForeignKey("core.User", on_delete=models.CASCADE, related_name="device_tokens")
	token = models.CharField(max_length=255, unique=True)
	platform = models.CharField(max_length=10, choices=Platform.choices, default=Platform.UNKNOWN)
	is_active = models.BooleanField(default=True)
	last_seen_at = models.DateTimeField(null=True, blank=True)
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)

	class Meta:
		db_table = "device_tokens"

	def __str__(self):
		return f"{self.user.phone} - {self.platform}"


class AuditLog(models.Model):
	id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
	actor = models.ForeignKey("core.User", on_delete=models.SET_NULL, related_name="audit_logs", null=True, blank=True)
	action = models.CharField(max_length=120, db_index=True)
	content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True, blank=True)
	object_id = models.CharField(max_length=64, null=True, blank=True)
	content_object = GenericForeignKey("content_type", "object_id")
	payload = models.JSONField(default=dict, blank=True)
	ip_address = models.GenericIPAddressField(null=True, blank=True)
	created_at = models.DateTimeField(auto_now_add=True, db_index=True)

	class Meta:
		db_table = "audit_logs"
		indexes = [
			models.Index(fields=["content_type", "object_id"]),
		]

	def __str__(self):
		return f"{self.action} @ {self.created_at.isoformat()}"
