from datetime import timedelta

from django.core.management.base import BaseCommand
from django.core.mail import send_mail
from django.utils import timezone

from apps.accounts.models import User
from apps.invoicing.models import Invoice
from apps.notifications.models import Notification, ReminderOffset, ReminderRule

OFFSET_DAYS = {
    ReminderOffset.BEFORE_7: 7,
    ReminderOffset.BEFORE_3: 3,
    ReminderOffset.DUE_TODAY: 0,
    ReminderOffset.OVERDUE_3: -3,
    ReminderOffset.OVERDUE_7: -7,
    ReminderOffset.OVERDUE_30: -30,
}

UNPAID_STATUSES = [
    Invoice.Status.SENT,
    Invoice.Status.VIEWED,
    Invoice.Status.PARTIALLY_PAID,
    Invoice.Status.OVERDUE,
]


class Command(BaseCommand):
    help = (
        "Scan invoices against each company's active reminder rules "
        '(7/3 days before due, due today, 3/7/30 days overdue) and create '
        'notifications. Intended to run once daily via cron/Task Scheduler.'
    )

    def handle(self, *args, **options):
        today = timezone.localdate()
        created_count = 0

        rules = ReminderRule.objects.filter(is_active=True).select_related('company')
        for rule in rules:
            target_date = today + timedelta(days=OFFSET_DAYS[rule.offset])
            offset_label = rule.get_offset_display()

            invoices = Invoice.objects.filter(
                company=rule.company,
                due_date=target_date,
                status__in=UNPAID_STATUSES,
            ).select_related('customer')
            recipients = User.objects.filter(company=rule.company, is_active=True)

            for invoice in invoices:
                for recipient in recipients:
                    notification, was_created = Notification.objects.get_or_create(
                        user=recipient,
                        invoice=invoice,
                        reminder_offset=rule.offset,
                        defaults={
                            'type': Notification.Type.INVOICE_REMINDER,
                            'channel': rule.channel,
                            'title': f'Invoice {invoice.invoice_number} - {offset_label}',
                            'message': (
                                f'Invoice {invoice.invoice_number} for {invoice.customer.name} '
                                f'({invoice.balance_due} {invoice.currency}) is {offset_label.lower()} '
                                f'(due {invoice.due_date}).'
                            ),
                        },
                    )
                    if not was_created:
                        continue

                    created_count += 1
                    if rule.channel == Notification.Channel.EMAIL and recipient.email:
                        send_mail(
                            subject=notification.title,
                            message=notification.message,
                            from_email=None,
                            recipient_list=[recipient.email],
                            fail_silently=True,
                        )

        self.stdout.write(self.style.SUCCESS(f'Created {created_count} reminder notification(s).'))
