from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.utils import timezone
from django.conf import settings
from datetime import timedelta
import os
from io import BytesIO

from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
from PIL import Image
from common.choices import NATIONALITY_CHOICES, COUNTRY_CHOICES, LANGUAGE_CHOICES
from django.conf import settings
from decimal import Decimal


def foreigner_profile_image_upload_path(instance, filename):
    ext = filename.split('.')[-1].lower()
    if ext not in ['jpg', 'jpeg', 'png', 'webp']:
        ext = 'jpg'
    return f'foreigner_profiles/user_{instance.user.id}/profile.{ext}'

def validate_profile_image(image):
    allowed_extensions = ['.jpg', '.jpeg', '.png', '.webp']
    ext = os.path.splitext(image.name)[1].lower()

    if ext not in allowed_extensions:
        raise ValidationError("Only JPG, JPEG, PNG, or WEBP images are allowed.")

    max_size_mb = 2
    if image.size > max_size_mb * 1024 * 1024:
        # We allow larger files to be uploaded and then compress them,
        # so do not block here unless you want strict validation.
        # If you want strict blocking, uncomment below:
        # raise ValidationError("Image file size must be 2 MB or less.")
        pass


from decimal import Decimal
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models


class Package(models.Model):
    PACKAGE_LEVELS = [
        ('startup', 'Startup'),
        ('comfort', 'Comfort'),
        ('premium', 'Premium'),
        ('luxury', 'Luxury'),
    ]

    slug = models.SlugField(unique=True)
    name = models.CharField(max_length=100)
    level = models.CharField(max_length=20, choices=PACKAGE_LEVELS, unique=True)

    monthly_price_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(0)]
    )

    short_description = models.CharField(max_length=255)
    full_description = models.TextField()
    target_audience = models.CharField(max_length=255, blank=True)

    housing_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    food_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    utilities_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    transport_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    support_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    leisure_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)
    misc_cost = models.DecimalField(max_digits=10, decimal_places=2, default=0)

    confirmation_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=100,
        validators=[MinValueValidator(0)],
        help_text="One-time confirmation fee charged after approval."
    )

    service_fee_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="One-time service fee as a percentage of monthly package value."
    )

    affiliate_fee_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=20,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="Affiliate commission as a percentage of the service fee."
    )

    estimated_rent_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)],
        help_text="Estimated monthly rent portion within this package."
    )

    estimated_deposit_months = models.PositiveIntegerField(
        default=3,
        help_text="Estimated number of rental deposit months usually required."
    )

    is_featured = models.BooleanField(default=False)
    image = models.ImageField(upload_to='packages/', blank=True, null=True)
    is_active = models.BooleanField(default=True)
    order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['order', 'monthly_price_usd']

    def __str__(self):
        return f"{self.name} - ${self.monthly_price_usd}"

    @property
    def total_breakdown(self):
        return (
            self.housing_cost +
            self.food_cost +
            self.utilities_cost +
            self.transport_cost +
            self.support_cost +
            self.leisure_cost +
            self.misc_cost
        )

    @property
    def service_fee_amount(self):
        return (
            self.monthly_price_usd * self.service_fee_percentage / Decimal('100')
        ).quantize(Decimal('0.01'))

    @property
    def affiliate_fee_amount(self):
        return (
            self.service_fee_amount * self.affiliate_fee_percentage / Decimal('100')
        ).quantize(Decimal('0.01'))

    @property
    def total_one_time_fee(self):
        return (
            self.confirmation_fee_usd + self.service_fee_amount
        ).quantize(Decimal('0.01'))

    @property
    def estimated_rental_deposit_usd(self):
        return (
            self.estimated_rent_usd * Decimal(str(self.estimated_deposit_months))
        ).quantize(Decimal('0.01'))

    @property
    def estimated_upfront_total_with_deposit(self):
        return (
            self.confirmation_fee_usd +
            self.service_fee_amount +
            self.estimated_rental_deposit_usd
        ).quantize(Decimal('0.01'))

    @property
    def estimated_first_month_total_with_deposit(self):
        return (
            self.monthly_price_usd +
            self.confirmation_fee_usd +
            self.service_fee_amount +
            self.estimated_rental_deposit_usd
        ).quantize(Decimal('0.01'))


class PackageFeature(models.Model):
    package = models.ForeignKey(Package, on_delete=models.CASCADE, related_name='features')
    feature_text = models.CharField(max_length=255)
    order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['order']

    def __str__(self):
        return f"{self.package.name} - {self.feature_text}"


class ForeignerLead(models.Model):
    BUDGET_CHOICES = [
        ('500', '$500 Startup'),
        ('1000', '$1,000 Comfort'),
        ('2000', '$2,000 Premium'),
        ('3000', '$3,000 Luxury'),
    ]

    GENDER_CHOICES = [
        ('male', 'Male'),
        ('female', 'Female'),
        ('other', 'Other'),
        ('prefer_not_to_say', 'Prefer not to say'),
    ]

    full_name = models.CharField(max_length=150)
    email = models.EmailField()
    whatsapp_number = models.CharField(max_length=50, blank=True)
    country = models.CharField(
        max_length=150,
        choices=COUNTRY_CHOICES,
        blank=True
    )
    nationality = models.CharField(
        max_length=150,
        choices=NATIONALITY_CHOICES,
        blank=True
    )
    gender = models.CharField(max_length=20, choices=GENDER_CHOICES, blank=True)
    expected_arrival_date = models.DateField(blank=True, null=True)
    duration_of_stay = models.CharField(max_length=100, blank=True)
    monthly_budget = models.CharField(max_length=10, choices=BUDGET_CHOICES)
    remote_worker = models.BooleanField(default=False)
    interested_package = models.ForeignKey(Package, on_delete=models.SET_NULL, blank=True, null=True)
    selected_furniture_package = models.ForeignKey(
        'FurniturePackage',
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    final_rental_property = models.ForeignKey(
        'rental_app.RentalListing',
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name='final_selected_by_foreigners',
        help_text="The final rental property selected for this foreigner."
    )
    final_rental_selected_at = models.DateTimeField(blank=True, null=True)
    message = models.TextField(blank=True)
    is_confirmed_foreigner = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    is_public = models.BooleanField(default=False)
    lead_status = models.CharField(
        max_length=30,
        choices=[
            ('new', 'New'),
            ('reviewing', 'Reviewing'),
            ('contacted', 'Contacted'),
            ('qualified', 'Qualified'),
            ('closed', 'Closed'),
        ],
        default='new'
    )

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.full_name} - {self.email}"


class ConsultationRequest(models.Model):
    lead = models.ForeignKey(ForeignerLead, on_delete=models.CASCADE, related_name='consultations')
    package = models.ForeignKey(Package, on_delete=models.SET_NULL, null=True, blank=True)
    preferred_contact_method = models.CharField(
        max_length=20,
        choices=[
            ('email', 'Email'),
            ('whatsapp', 'WhatsApp'),
            ('call', 'Call'),
            ('video', 'Video Call'),
        ],
        default='email'
    )
    preferred_date = models.DateField(blank=True, null=True)
    notes = models.TextField(blank=True)
    confirmation_fee_required = models.DecimalField(max_digits=10, decimal_places=2, default=100.00)
    confirmation_paid = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Consultation - {self.lead.full_name}"


class ContactMessage(models.Model):
    name = models.CharField(max_length=150)
    email = models.EmailField()
    subject = models.CharField(max_length=200)
    message = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return self.subject


class ConfirmationPayment(models.Model):
    PAYMENT_METHOD_CHOICES = [
        ('paypal', 'PayPal'),
        ('bank', 'Bank Transfer'),
        ('stripe', 'Stripe'),
        ('cash', 'Cash'),
        ('other', 'Other'),
    ]

    consultation = models.ForeignKey(
        'ConsultationRequest',
        on_delete=models.CASCADE,
        related_name='confirmation_payments'
    )
    amount_usd = models.DecimalField(max_digits=10, decimal_places=2, default=100.00)
    payment_method = models.CharField(
        max_length=50,
        choices=PAYMENT_METHOD_CHOICES,
        blank=True,
        null=True
    )
    payment_reference = models.CharField(max_length=150, blank=True)
    is_paid = models.BooleanField(default=False)
    paid_at = models.DateTimeField(blank=True, null=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Confirmation Payment'
        verbose_name_plural = 'Confirmation Payments'

    def __str__(self):
        consultation_name = getattr(self.consultation.lead, 'full_name', 'Unknown Lead')
        return f"{consultation_name} - ${self.amount_usd} - {'Paid' if self.is_paid else 'Pending'}"

    def save(self, *args, **kwargs):
        if self.is_paid and not self.paid_at:
            self.paid_at = timezone.now()
        elif not self.is_paid:
            self.paid_at = None
        super().save(*args, **kwargs)


    
class ForeignerProfile(models.Model):
    STATUS_CHOICES = [
        ('pending', 'Pending Review'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
        ('inactive', 'Inactive'),
    ]
    VISIT_STAGE_CHOICES = [
        ('planning', 'Planning to Visit'),
        ('confirmed', 'Confirmed Visit'),
        ('on_the_way', 'On the Way'),
        ('arrived', 'Already Arrived'),
        ('completed', 'Visit Completed'),
    ]
    
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='foreigner_profile'
    )
    lead = models.OneToOneField(
        'ForeignerLead',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='foreigner_profile'
    )
    profile_image = models.ImageField(
        upload_to=foreigner_profile_image_upload_path,
        blank=True,
        null=True,
        validators=[validate_profile_image]
    )

    is_confirmed = models.BooleanField(default=False)
    can_view_private_listings = models.BooleanField(default=False)
    can_book_arrangements = models.BooleanField(default=False)

    is_public = models.BooleanField(default=False)
    is_featured = models.BooleanField(default=False)

    is_rental_cycle_active = models.BooleanField(default=False)
    is_furniture_cycle_active = models.BooleanField(default=False)
    is_main_package_locked = models.BooleanField(default=False)

    last_rental_closed_at = models.DateField(blank=True, null=True)
    last_furniture_closed_at = models.DateField(blank=True, null=True)

    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    visit_stage = models.CharField(
        max_length=30,
        choices=VISIT_STAGE_CHOICES,
        default='planning',
        help_text='Shows the current visit journey stage of the foreign guest.'
    )
    joined_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-joined_at']
        verbose_name = 'Foreigner Profile'
        verbose_name_plural = 'Foreigner Profiles'

    def __str__(self):
        return f"{self.user.username} - {'Confirmed' if self.is_confirmed else 'Pending'}"

    def save(self, *args, **kwargs):
        if self.is_confirmed and self.visit_stage == 'planning':
            self.visit_stage = 'confirmed'

        super().save(*args, **kwargs)

        if self.profile_image:
            self.compress_profile_image()

    def compress_profile_image(self):
        try:
            img = Image.open(self.profile_image.path)

            if img.mode in ('RGBA', 'P'):
                img = img.convert('RGB')

            max_width = 600
            max_height = 600
            img.thumbnail((max_width, max_height))

            buffer = BytesIO()
            img.save(buffer, format='JPEG', quality=85, optimize=True)

            file_name = os.path.splitext(os.path.basename(self.profile_image.name))[0] + '.jpg'
            self.profile_image.save(
                file_name,
                ContentFile(buffer.getvalue()),
                save=False
            )

            super().save(update_fields=['profile_image'])

        except Exception:
            pass

class ForeignerInterest(models.Model):
    STATUS_CHOICES = [
        ('interested', 'Interested'),
        ('reviewing', 'Reviewing'),
        ('contacted', 'Contacted'),
        ('matched', 'Matched'),
        ('closed', 'Closed'),
    ]

    dating_partner = models.ForeignKey(
        'dating_app.DatingPartnerProfile',
        on_delete=models.CASCADE,
        related_name='foreigner_interests'
    )
    foreigner = models.ForeignKey(
        'expat_life.ForeignerProfile',
        on_delete=models.CASCADE,
        related_name='dating_partner_interests'
    )
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='interested')
    message = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Foreigner Interest'
        verbose_name_plural = 'Foreigner Interests'
        constraints = [
            models.UniqueConstraint(
                fields=['dating_partner', 'foreigner'],
                name='unique_dating_partner_foreigner_interest'
            )
        ]

    def __str__(self):
        return f"{self.dating_partner.display_name or self.dating_partner.full_name} -> {self.foreigner.user.username}"
    

class PlatformFeeSettings(models.Model):
    dating_partner_confirmation_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=50,
        validators=[MinValueValidator(0)],
        help_text="Default confirmation fee for dating partners."
    )

    foreigner_featured_profile_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0)],
        help_text="Default premium / featured profile fee for foreigners."
    )

    dating_partner_featured_profile_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0)],
        help_text="Default premium / featured profile fee for dating partners."
    )

    service_partner_featured_account_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0)],
        help_text="Default premium / featured account fee for service partners such as job seekers, assistants, helpers, etc."
    )

    rental_owner_monthly_fee_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="Monthly fee percentage charged from the rental owner's monthly rental amount."
    )

    rental_owner_featured_profile_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0)],
        help_text="Default premium / featured profile fee for rental owners."
    )

    affiliate_commission_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=20,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="Affiliate commission percentage from eligible guest fees such as confirmation fee and one-time service fee."
    )

    hosting_partner_featured_profile_fee_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=5,
        validators=[MinValueValidator(0)],
        help_text="Default featured / premium listing fee for Hosting Partners."
    )

    hosting_partner_commission_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=10,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="Commission percentage charged by Ensolanka from confirmed hosting event bookings."
    )

    is_active = models.BooleanField(default=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Platform Fee Settings"
        verbose_name_plural = "Platform Fee Settings"

    def __str__(self):
        return "Platform Fee Settings"

    def save(self, *args, **kwargs):
        if not self.pk and PlatformFeeSettings.objects.exists():
            raise ValueError("Only one PlatformFeeSettings instance is allowed.")
        super().save(*args, **kwargs)

class UserPayableItem(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
        ('dating_partner', 'Dating Partner'),
        ('service_partner', 'Service Partner'),
        ('rental_owner', 'Rental Owner'),

        # Existing / upcoming platform roles
        ('affiliate', 'Affiliate Partner'),

        # Property Care app
        ('property_care_owner', 'Property Care Owner'),

        # Hosting app
        ('hosting_partner', 'Hosting Partner'),
        ('hosting_client', 'Hosting Client'),
    ]

    PAYMENT_FOR_CHOICES = [
        ('account_confirmation', 'Account Confirmation'),
        ('one_time_service_fee', 'One-Time Service Fee'),
        ('featured_profile_fee', 'Featured / Premium Profile Fee'),

        # Rental / furniture payments
        ('rental_deposit', 'Rental Deposit'),
        ('monthly_rental', 'Monthly Rental'),
        ('furniture_rental', 'Furniture Rental'),
        ('furniture_rental_deposit', 'Furniture Rental Deposit'),
        ('furniture_purchase', 'Furniture Purchase'),

        # Dating / service partner payments
        ('dating_confirmation', 'Dating Confirmation'),
        ('service_partner_featured', 'Service Partner Featured Fee'),
        ('dating_partner_featured', 'Dating Partner Featured Fee'),

        # Rental owner payments
        ('rental_owner_featured', 'Rental Owner Featured / Premium Fee'),
        ('rental_owner_commission', 'Rental Owner Commission'),

        # Package payments
        ('package_upgrade_fee', 'Package Upgrade Fee'),

        # Hosting app payments
        ('hosting_partner_featured', 'Hosting Partner Featured / Premium Fee'),
        ('host_event_booking', 'Host Event Booking'),

        # Property Care payments
        ('property_care_monthly_plan_fee', 'Property Care Monthly Plan Fee'),

        ('other', 'Other'),
    ]

    AMOUNT_STATE_CHOICES = [
        ('estimated', 'Estimated'),
        ('tentative', 'Tentative'),
        ('confirmed', 'Confirmed'),
        ('not_decided', 'Not Yet Decided'),
    ]

    PAYMENT_STATUS_CHOICES = [
        ('upcoming', 'Upcoming'),
        ('due', 'Due'),
        ('paid', 'Paid'),
        ('cancelled', 'Cancelled'),
        ('waived', 'Waived'),
        ('expired', 'Expired'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='payable_items'
    )

    profile_type = models.CharField(max_length=30, choices=PROFILE_TYPE_CHOICES)
    payment_for = models.CharField(max_length=50, choices=PAYMENT_FOR_CHOICES)

    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)

    amount_state = models.CharField(
        max_length=20,
        choices=AMOUNT_STATE_CHOICES,
        default='estimated'
    )

    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    payment_status = models.CharField(
        max_length=20,
        choices=PAYMENT_STATUS_CHOICES,
        default='upcoming'
    )

    is_active = models.BooleanField(default=True)
    is_optional = models.BooleanField(default=False)

    due_date = models.DateField(blank=True, null=True)
    effective_from = models.DateField(blank=True, null=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    paid_at = models.DateTimeField(blank=True, null=True)
    reference_code = models.CharField(max_length=120, blank=True, db_index=True)
    notes = models.TextField(blank=True)
    
    class Meta:
        ordering = ['payment_status', 'due_date', 'created_at']
        indexes = [
            models.Index(fields=['user', 'profile_type', 'payment_status']),
            models.Index(fields=['reference_code']),
            models.Index(fields=['user', 'profile_type', 'payment_for', 'reference_code']),
        ]

    def __str__(self):
        return f"{self.user} - {self.get_payment_for_display()} - ${self.amount_usd}"
    

class FurniturePackage(models.Model):
    PACKAGE_LEVELS = [
        ('startup', 'Startup'),
        ('comfort', 'Comfort'),
        ('premium', 'Premium'),
        ('luxury', 'Luxury'),
    ]

    name = models.CharField(max_length=150)
    slug = models.SlugField(unique=True)
    level = models.CharField(max_length=20, choices=PACKAGE_LEVELS, unique=True)

    short_description = models.CharField(max_length=255, blank=True)
    full_description = models.TextField(blank=True)
    image = models.ImageField(
        upload_to='furniture_packages/',
        blank=True,
        null=True
    )

    monthly_rental_usd = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    deposit_months = models.PositiveIntegerField(
        default=3,
        help_text="Number of months used to calculate furniture rental deposit."
    )

    total_purchase_value_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)],
        help_text="Estimated full purchase value of all furniture items in this package."
    )
    
    is_featured = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['order', 'level']

    def __str__(self):
        return f"{self.name} - ${self.monthly_rental_usd}/month"

    @property
    def calculated_deposit_usd(self):
        return (
            self.monthly_rental_usd * Decimal(str(self.deposit_months))
        ).quantize(Decimal('0.01'))
    
class FurniturePackageItem(models.Model):
    furniture_package = models.ForeignKey(
        FurniturePackage,
        on_delete=models.CASCADE,
        related_name='items'
    )
    item_name = models.CharField(max_length=150)
    quantity = models.PositiveIntegerField(default=1)
    notes = models.CharField(max_length=255, blank=True)
    order = models.PositiveIntegerField(default=0)

    class Meta:
        ordering = ['order', 'id']

    def __str__(self):
        return f"{self.item_name} ({self.quantity})"
    
class PaymentTransaction(models.Model):
    PAYMENT_METHOD_CHOICES = [
        ('stripe', 'Stripe'),
        ('paypal', 'PayPal'),
        ('wallet', 'Wallet'),
        ('mixed_stripe_wallet', 'Stripe + Wallet'),
        ('mixed_paypal_wallet', 'PayPal + Wallet'),
    ]

    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('processing', 'Processing'),
        ('paid', 'Paid'),
        ('failed', 'Failed'),
        ('cancelled', 'Cancelled'),
    ]

    PURPOSE_CHOICES = [
        ('payable_items', 'Payable Items'),
        ('wallet_topup', 'Wallet Top-up'),
    ]

    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    profile_type = models.CharField(max_length=30)

    payment_purpose = models.CharField(
        max_length=30,
        choices=PURPOSE_CHOICES,
        default='payable_items'
    )

    payment_method = models.CharField(
        max_length=30,
        choices=PAYMENT_METHOD_CHOICES
    )

    gateway_transaction_id = models.CharField(max_length=255, blank=True)
    gateway_session_id = models.CharField(max_length=255, blank=True)

    total_amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=Decimal('0.00')
    )

    wallet_deduction_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=Decimal('0.00')
    )

    gateway_amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=Decimal('0.00')
    )

    status = models.CharField(
        max_length=30,
        choices=STATUS_CHOICES,
        default='pending'
    )

    paid_at = models.DateTimeField(null=True, blank=True)
    cancelled_at = models.DateTimeField(null=True, blank=True)
    failed_at = models.DateTimeField(null=True, blank=True)

    failure_reason = models.TextField(blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    invoice_email_sent = models.BooleanField(default=False)

    def __str__(self):
        return (
            f"Transaction #{self.id} - {self.user} - "
            f"{self.payment_method} - ${self.total_amount_usd}"
        )

class PaymentTransactionItem(models.Model):
    transaction = models.ForeignKey(
        PaymentTransaction,
        on_delete=models.CASCADE,
        related_name='items'
    )
    payable_item = models.ForeignKey(UserPayableItem, on_delete=models.CASCADE)
    amount_usd = models.DecimalField(max_digits=12, decimal_places=2, default=0)

    def __str__(self):
        return (
            f"Transaction #{self.transaction_id} - "
            f"{self.payable_item.title} - ${self.amount_usd}"
        )
    
#new payment related modals

class ServiceChangeRequest(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
    ]

    REQUEST_TYPE_CHOICES = [
        ('cancel_property_rental', 'Cancel Property Rental'),
        ('cancel_furniture_rental', 'Cancel Furniture Rental'),
        ('cancel_for_upgrade_package', 'Cancel for Upgrade Package'),
        ('other', 'Other'),
    ]

    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('reviewing', 'Reviewing'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='service_change_requests'
    )
    profile_type = models.CharField(
        max_length=30,
        choices=PROFILE_TYPE_CHOICES,
        default='foreigner'
    )

    foreigner_profile = models.ForeignKey(
        'expat_life.ForeignerProfile',
        on_delete=models.CASCADE,
        related_name='service_change_requests',
        null=True,
        blank=True
    )

    request_type = models.CharField(max_length=50, choices=REQUEST_TYPE_CHOICES)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')

    admin_approved = models.BooleanField(default=False)
    approved_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='approved_service_change_requests'
    )

    current_property = models.ForeignKey(
        'rental_app.RentalListing',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='service_change_requests'
    )
    current_furniture_package = models.ForeignKey(
        'expat_life.FurniturePackage',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='service_change_requests'
    )
    current_package = models.ForeignKey(
        'expat_life.Package',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='current_service_change_requests'
    )
    requested_new_package = models.ForeignKey(
        'expat_life.Package',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='requested_service_change_requests'
    )

    user_reason = models.TextField(blank=True)
    admin_notes = models.TextField(blank=True)

    requested_at = models.DateTimeField(auto_now_add=True)
    reviewed_at = models.DateTimeField(null=True, blank=True)
    completed_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ['-requested_at']

    def __str__(self):
        return f"{self.user} - {self.get_request_type_display()} - {self.get_status_display()}"

class ServiceChangeSettlementItem(models.Model):
    ITEM_TYPE_CHOICES = [
        ('damage', 'Damage Charge'),
        ('utility_bill', 'Utility Bill'),
        ('cleaning', 'Cleaning Fee'),
        ('late_charge', 'Late Charge'),
        ('refund_credit', 'Refund Credit'),
        ('other', 'Other'),
    ]

    request = models.ForeignKey(
        ServiceChangeRequest,
        on_delete=models.CASCADE,
        related_name='settlement_items'
    )

    item_type = models.CharField(max_length=30, choices=ITEM_TYPE_CHOICES)
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)

    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    is_deduction = models.BooleanField(
        default=True,
        help_text='True for charges/deductions, False for refund credits.'
    )

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['created_at']

    def __str__(self):
        sign = '-' if self.is_deduction else '+'
        return f"{self.request_id} - {self.title} ({sign}${self.amount_usd})"

class WalletAccount(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
        ('dating_partner', 'Dating Partner'),
        ('service_partner', 'Service Partner'),
        ('rental_owner', 'Rental Owner'),

        # Existing / upcoming platform roles
        ('affiliate', 'Affiliate Partner'),

        # Property Care app
        ('property_care_owner', 'Property Care Owner'),

        # Hosting app
        ('hosting_partner', 'Hosting Partner'),
        ('hosting_client', 'Hosting Client'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='wallet_accounts'
    )
    profile_type = models.CharField(max_length=30, choices=PROFILE_TYPE_CHOICES)

    balance_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('user', 'profile_type')
        ordering = ['profile_type']

    def __str__(self):
        return f"{self.user} - {self.profile_type} wallet - ${self.balance_usd}"

class WalletTransaction(models.Model):
    TRANSACTION_TYPE_CHOICES = [
        ('topup', 'Top-up'),
        ('refund', 'Refund'),
        ('deduction', 'Deduction'),
        ('payment', 'Wallet Payment'),
        ('manual_credit', 'Manual Credit'),
        ('manual_debit', 'Manual Debit'),
        ('payout_hold', 'Payout Hold'),
        ('payout_release', 'Payout Release'),
        ('rental_owner_income', 'Rental Owner Income'),
         # Hosting Partner
        ('hosting_partner_event_income', 'Hosting Partner Event Income'),
        ('hosting_partner_payout', 'Hosting Partner Payout'),
        ('hosting_partner_adjustment', 'Hosting Partner Adjustment'),
        ('hosting_partner_featured_fee', 'Hosting Partner Featured Fee'),
        ('hosting_commission_deduction', 'Hosting Commission Deduction'),
        ('other', 'Other'),
    ]

    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),
        ('failed', 'Failed'),
    ]

    wallet = models.ForeignKey(
        WalletAccount,
        on_delete=models.CASCADE,
        related_name='transactions'
    )

    transaction_type = models.CharField(max_length=30, choices=TRANSACTION_TYPE_CHOICES)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='completed')

    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)

    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    is_credit = models.BooleanField(
        default=True,
        help_text='True adds to wallet, False deducts from wallet.'
    )

    related_payable_item = models.ForeignKey(
        'expat_life.UserPayableItem',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='wallet_transactions'
    )
    related_change_request = models.ForeignKey(
        ServiceChangeRequest,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='wallet_transactions'
    )

    reference_code = models.CharField(max_length=120, blank=True, db_index=True)
    admin_notes = models.TextField(blank=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        sign = '+' if self.is_credit else '-'
        return f"{self.wallet} {sign}${self.amount_usd} {self.get_transaction_type_display()}"

class Payout(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
        ('rental_owner', 'Rental Owner'),
        ('affiliate', 'Affiliate'),
        ('hosting_partner', 'Hosting Partner'),
    ]

    PAYOUT_TYPE_CHOICES = [
        ('foreign_refund', 'Foreigner Refund / Withdrawal'),
        ('rental_owner_income', 'Rental Owner Income Payout'),
        ('affiliate_commission', 'Affiliate Commission Payout'),
        ('hosting_partner_income', 'Hosting Partner Income Payout'),
        ('other', 'Other'),
    ]

    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('approved', 'Approved'),
        ('processing', 'Processing'),
        ('paid', 'Paid'),
        ('rejected', 'Rejected'),
        ('cancelled', 'Cancelled'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='payouts'
    )
    profile_type = models.CharField(max_length=30, choices=PROFILE_TYPE_CHOICES)
    payout_type = models.CharField(max_length=30, choices=PAYOUT_TYPE_CHOICES)

    foreigner_profile = models.ForeignKey(
        'expat_life.ForeignerProfile',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )
    rental_owner = models.ForeignKey(
        'rental_app.RentalOwner',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )

    affiliate_partner = models.ForeignKey(
        'affiliates_app.AffiliateProfile',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )

    hosting_partner = models.ForeignKey(
        'hosting_app.HostProfile',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )

    wallet = models.ForeignKey(
        WalletAccount,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )

    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)

    related_payable_item = models.ForeignKey(
        'expat_life.UserPayableItem',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )
    related_change_request = models.ForeignKey(
        ServiceChangeRequest,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payouts'
    )

    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    requested_by_user = models.BooleanField(default=False)

    approved_at = models.DateTimeField(null=True, blank=True)
    paid_at = models.DateTimeField(null=True, blank=True)

    reference_code = models.CharField(max_length=120, blank=True, db_index=True)
    admin_notes = models.TextField(blank=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.user} - {self.get_payout_type_display()} - ${self.amount_usd}"

class PayoutRequest(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
        ('rental_owner', 'Rental Owner'),
        # Hosting app
        ('hosting_partner', 'Hosting Partner'),
        ('affiliate', 'Affiliate'),
        ('other', 'Other'),
    ]

    REQUEST_STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('reviewing', 'Reviewing'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
        ('cancelled', 'Cancelled'),
        ('completed', 'Completed'),
    ]

    REQUEST_TYPE_CHOICES = [
        ('wallet_withdrawal', 'Wallet Withdrawal'),
        ('rental_owner_income', 'Rental Owner Income Withdrawal'),
        ('refund_withdrawal', 'Refund Withdrawal'),
        ('hosting_partner_income', 'Hosting Partner Income Withdrawal'),
        ('affiliate_commission', 'Affiliate Commission Withdrawal'),
        ('other', 'Other'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='payout_requests'
    )

    profile_type = models.CharField(max_length=30, choices=PROFILE_TYPE_CHOICES)
    request_type = models.CharField(max_length=30, choices=REQUEST_TYPE_CHOICES, default='wallet_withdrawal')

    wallet = models.ForeignKey(
        'expat_life.WalletAccount',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='payout_requests'
    )

    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        default=0,
        validators=[MinValueValidator(0)]
    )

    status = models.CharField(
        max_length=20,
        choices=REQUEST_STATUS_CHOICES,
        default='pending'
    )

    user_reason = models.TextField(blank=True)
    admin_notes = models.TextField(blank=True)

    admin_approved = models.BooleanField(default=False)

    approved_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='approved_payout_requests'
    )

    requested_at = models.DateTimeField(auto_now_add=True)
    reviewed_at = models.DateTimeField(null=True, blank=True)
    completed_at = models.DateTimeField(null=True, blank=True)

    reference_code = models.CharField(max_length=120, blank=True, db_index=True)

    related_payout = models.OneToOneField(
        'expat_life.Payout',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='source_request'
    )

    class Meta:
        ordering = ['-requested_at']

    def __str__(self):
        return f"{self.user} - {self.get_request_type_display()} - ${self.amount_usd} - {self.get_status_display()}"
    
class RefundableDeposit(models.Model):
    PROFILE_TYPE_CHOICES = [
        ('foreigner', 'Foreigner'),
        ('dating_partner', 'Dating Partner'),
        ('service_partner', 'Service Partner'),
        ('rental_owner', 'Rental Owner'),
    ]
    
    DEPOSIT_TYPE_CHOICES = [
        ('rental_deposit', 'Rental Deposit'),
        ('furniture_deposit', 'Furniture Deposit'),
        # add other deposit types if needed
    ]

    STATUS_CHOICES = [
        ('active', 'Active - Held'),
        ('partially_refunded', 'Partially Refunded'),
        ('fully_refunded', 'Fully Refunded'),
        ('settled_with_deductions', 'Settled with Deductions'),
        ('cancelled', 'Cancelled'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='refundable_deposits'
    )
    profile_type = models.CharField(
        max_length=30,
        choices=WalletAccount.PROFILE_TYPE_CHOICES,
        default='foreigner',                 # <-- default added
        help_text="Which wallet type this deposit belongs to"
    )
    deposit_type = models.CharField(max_length=30, choices=DEPOSIT_TYPE_CHOICES)
    amount_usd = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        validators=[MinValueValidator(Decimal('0.01'))]
    )
    status = models.CharField(max_length=30, choices=STATUS_CHOICES, default='active')

    paid_at = models.DateTimeField(auto_now_add=True)
    # Link to the payment record (UserPayableItem)
    related_payable_item = models.ForeignKey(
        'expat_life.UserPayableItem',   # adjust app name if different
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='refundable_deposits'
    )

    # Optional: reference to a rental agreement (if you have such a model)
    # rental_agreement = models.ForeignKey('RentalAgreement', on_delete=models.SET_NULL, null=True, blank=True)

    reference_code = models.CharField(max_length=120, blank=True)
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        # One active deposit per user + profile + type
        unique_together = [['user', 'profile_type', 'deposit_type']]  # but careful – you may want to allow multiple if old ones are closed
        indexes = [
            models.Index(fields=['user', 'status']),
            models.Index(fields=['deposit_type', 'status']),
        ]

    def __str__(self):
        return f"{self.user} - {self.get_deposit_type_display()} (${self.amount_usd}) - {self.status}"

    @property
    def is_fully_refunded(self):
        return self.status == 'fully_refunded'

    def mark_refunded(self, amount_refunded=None, settlement_notes=''):
        """
        Call this when the deposit is refunded (fully or partially).
        If amount_refunded is None or equals self.amount_usd -> fully refunded.
        Otherwise, if amount_refunded > 0 and < self.amount_usd -> partially_refunded.
        """
        from decimal import Decimal
        if amount_refunded is None:
            amount_refunded = self.amount_usd

        if amount_refunded >= self.amount_usd:
            self.status = 'fully_refunded'
        elif amount_refunded > 0:
            self.status = 'partially_refunded'
        else:
            # No refund – maybe settled with deductions
            self.status = 'settled_with_deductions'

        self.notes += f"\n[Refund/settlement on {timezone.now()}]: {settlement_notes} (Amount refunded: ${amount_refunded})"
        self.save(update_fields=['status', 'notes', 'updated_at'])

class MarketingResource(models.Model):
    AUDIENCE_CHOICES = [
        ('foreigners', 'Foreigners'),
        ('rentals', 'Rentals'),
        ('dating', 'Dating'),
        ('assistants', 'Assistants'),
        ('affiliates', 'Affiliates'),
        ('hosting', 'Hosting'),
        ('properties', 'Properties'),
    ]

    target_audience = models.CharField(
        max_length=20,
        choices=AUDIENCE_CHOICES,
        help_text="Who is this resource for?"
    )

    language = models.CharField(
        max_length=2,
        choices=LANGUAGE_CHOICES,
        default='en'
    )

    title = models.CharField(
        max_length=200,
        help_text="Title of the resource (e.g., 'Sri Lanka Travel Guide')"
    )

    full_brochure_pdf = models.FileField(
        upload_to='marketing/brochures/%Y/%m/',
        blank=True,
        null=True
    )

    summary_overview_pdf = models.FileField(
        upload_to='marketing/summary/%Y/%m/',
        blank=True,
        null=True,
        help_text="Optional summary overview PDF"
    )

    presentation_pdf = models.FileField(
        upload_to='marketing/presentation/%Y/%m/',
        blank=True,
        null=True,
        help_text="Optional presentation PDF"
    )

    video_link = models.URLField(
        blank=True,
        null=True,
        help_text="YouTube/Vimeo URL"
    )

    audio_file = models.FileField(
        upload_to='marketing/audio/%Y/%m/',
        blank=True,
        null=True,
        help_text="Upload an MP3 audio guide or podcast file"
    )

    # Digital Nomad Visa Process Resources
    digital_nomad_visa_process_pdf = models.FileField(
        upload_to='marketing/digital_nomad_visa/process/%Y/%m/',
        blank=True,
        null=True,
        help_text="Upload the Digital Nomad Visa process document PDF"
    )

    digital_nomad_visa_presentation_pdf = models.FileField(
        upload_to='marketing/digital_nomad_visa/presentation/%Y/%m/',
        blank=True,
        null=True,
        help_text="Upload the illustrative Digital Nomad Visa process presentation PDF"
    )

    digital_nomad_visa_audio_file = models.FileField(
        upload_to='marketing/digital_nomad_visa/audio/%Y/%m/',
        blank=True,
        null=True,
        help_text="Upload the Digital Nomad Visa process audio explainer or podcast MP3"
    )

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = "Marketing Resource"
        verbose_name_plural = "Marketing Resources"
        unique_together = ('target_audience', 'language', 'title')

    def __str__(self):
        return f"{self.get_target_audience_display()} - {self.get_language_display()} - {self.title}"