# subscriptions/management/commands/process_subscriptions.py
"""
Management command: process subscription lifecycle tasks.

Run daily via cron/Task Scheduler:
  python manage.py process_subscriptions

Tasks:
1. Apply pending downgrades (when current subscription has expired)
2. Deactivate expired subscriptions
3. Send expiry warning emails (3 days before)
4. Send trial expiry warnings (1 day before)
"""
import logging
from datetime import date, timedelta

from django.core.management.base import BaseCommand
from django.db import transaction as db_transaction

from subscriptions.models import Subscription

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = "Process subscription lifecycle: downgrades, expiry deactivation, email warnings"

    def handle(self, *args, **options):
        today = date.today()
        self.stdout.write(f"[{today}] Processing subscriptions...")

        self._apply_pending_downgrades(today)
        self._deactivate_expired(today)
        self._send_expiry_warnings(today)

        self.stdout.write(self.style.SUCCESS(f"[{today}] Subscription processing complete."))

    # ──────────────────────────────────────────────────────────────────────────
    # 1. APPLY PENDING DOWNGRADES
    # ──────────────────────────────────────────────────────────────────────────
    @db_transaction.atomic
    def _apply_pending_downgrades(self, today):
        """Apply scheduled downgrades where current subscription has expired."""
        subs = Subscription.objects.filter(
            is_active=True,
            pending_downgrade_plan__isnull=False,
            expiry_date__lt=today,
        ).select_related('company', 'plan', 'pending_downgrade_plan')

        count = 0
        for sub in subs:
            new_plan = sub.pending_downgrade_plan
            company = sub.company

            # Deactivate current subscription
            sub.is_active = False
            sub.save(update_fields=['is_active'])

            # Create new subscription for the downgraded plan
            from datetime import timedelta
            from subscriptions.models import BILLING_CYCLE_DAYS
            new_expiry = today + timedelta(days=BILLING_CYCLE_DAYS.get(sub.billing_cycle, 30))
            
            new_sub = Subscription.objects.create(
                company=company,
                plan=new_plan,
                billing_cycle=sub.billing_cycle,
                start_date=today,
                expiry_date=new_expiry,
                is_trial=False,
                is_active=True,
                payment_status='paid',  # Downgrade at end of cycle, no new payment
            )

            # Sync company
            company.plan = new_plan
            company.expiry_date = new_expiry
            company.save(update_fields=['plan', 'expiry_date'])

            logger.info(
                f"⬇️ Downgrade applied: company={company.slug}, "
                f"from={sub.plan.name}, to={new_plan.name}"
            )
            count += 1

        self.stdout.write(f"  Applied {count} pending downgrade(s).")

    # ──────────────────────────────────────────────────────────────────────────
    # 2. DEACTIVATE EXPIRED SUBSCRIPTIONS
    # ──────────────────────────────────────────────────────────────────────────
    def _deactivate_expired(self, today):
        """Deactivate expired subscriptions (no pending downgrade)."""
        expired = Subscription.objects.filter(
            is_active=True,
            expiry_date__lt=today,
            pending_downgrade_plan__isnull=True,
        ).select_related('company')

        count = 0
        for sub in expired:
            sub.is_active = False
            sub.save(update_fields=['is_active'])
            # Also deactivate the company if no active subscription
            company = sub.company
            if not Subscription.objects.filter(company=company, is_active=True).exists():
                company.is_active = False
                company.save(update_fields=['is_active'])
                logger.warning(f"🔴 Company deactivated (expired): {company.slug}")
            count += 1
        self.stdout.write(f"  Deactivated {count} expired subscription(s).")

    # ──────────────────────────────────────────────────────────────────────────
    # 3. SEND EXPIRY WARNINGS
    # ──────────────────────────────────────────────────────────────────────────
    def _send_expiry_warnings(self, today):
        """Email companies whose subscription expires in 3 days or 1 day."""
        warning_days = [3, 1]
        count = 0

        for days in warning_days:
            target_date = today + timedelta(days=days)
            subs = Subscription.objects.filter(
                is_active=True,
                expiry_date=target_date,
            ).select_related('company', 'plan')

            for sub in subs:
                self._send_expiry_email(sub, days)
                count += 1

        self.stdout.write(f"  Sent {count} expiry warning email(s).")

    def _send_expiry_email(self, sub, days_left):
        """Send expiry warning email to company admin using the SwiftPOS pro email template."""
        company = sub.company
        admin_user = company.users.filter(role='admin').first()
        if not admin_user or not admin_user.email:
            return

        label = "trial" if sub.is_trial else "subscription"
        label_cap = label.capitalize()

        try:
            from django.conf import settings as djsettings
            from core.email_utils import _render_email_html, _make_email

            site_url = getattr(djsettings, 'SITE_URL', '').rstrip('/')
            manage_url = f"{site_url}/{company.slug}/subscription/manage/"
            wa_number = getattr(djsettings, 'WHATSAPP_NUMBER', '')
            first_name = admin_user.first_name or admin_user.username
            urgency_color = '#dc2626' if days_left == 1 else '#d97706'

            subject = f"⚠️ Your SwiftPOS {label_cap} expires in {days_left} day{'s' if days_left != 1 else ''} — {company.name}"

            body_html = f"""
            <p style="margin:0 0 16px;font-size:15px;color:#334155;">
              Hi <strong>{first_name}</strong>,
            </p>
            <p style="margin:0 0 24px;font-size:15px;color:#475569;line-height:1.6;">
              Your SwiftPOS <strong>{label}</strong> for <strong>{company.name}</strong>
              will expire in
              <span style="color:{urgency_color};font-weight:700;">{days_left} day{'s' if days_left != 1 else ''}</span>
              on <strong>{sub.expiry_date.strftime('%d %B %Y')}</strong>.
            </p>

            <!-- Info card -->
            <table border="0" cellpadding="0" cellspacing="0" width="100%"
                   style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;margin-bottom:28px;">
              <tr><td style="padding:20px 24px;">
                <table width="100%" border="0" cellpadding="0" cellspacing="0">
                  <tr><td style="padding:8px 0;border-bottom:1px solid #f1f5f9;">
                    <table width="100%"><tr>
                      <td style="font-size:13px;color:#64748b;">Company</td>
                      <td align="right" style="font-size:13px;font-weight:700;color:#1e293b;">{company.name}</td>
                    </tr></table>
                  </td></tr>
                  <tr><td style="padding:8px 0;border-bottom:1px solid #f1f5f9;">
                    <table width="100%"><tr>
                      <td style="font-size:13px;color:#64748b;">Current Plan</td>
                      <td align="right" style="font-size:13px;font-weight:700;color:#1e293b;">{sub.plan.name}</td>
                    </tr></table>
                  </td></tr>
                  <tr><td style="padding:8px 0;">
                    <table width="100%"><tr>
                      <td style="font-size:13px;color:#64748b;">Expiry Date</td>
                      <td align="right" style="font-size:13px;font-weight:700;color:{urgency_color};">
                        {sub.expiry_date.strftime('%d %B %Y')}
                      </td>
                    </tr></table>
                  </td></tr>
                </table>
              </td></tr>
            </table>

            <!-- CTA Button -->
            <table border="0" cellpadding="0" cellspacing="0" width="100%" style="margin-bottom:20px;">
              <tr>
                <td align="center">
                  <a href="{manage_url}"
                     style="display:inline-block;background:linear-gradient(135deg,#4F46E5,#7C3AED);
                            color:#ffffff;text-decoration:none;font-weight:700;font-size:15px;
                            padding:14px 36px;border-radius:12px;
                            box-shadow:0 4px 12px rgba(79,70,229,0.3);">
                    Renew My Subscription &rarr;
                  </a>
                </td>
              </tr>
            </table>

            {f'<p style="margin:0;font-size:13px;color:#94a3b8;text-align:center;">Need help? Contact us on <a href="https://wa.me/{wa_number}" style="color:#4F46E5;">WhatsApp</a>.</p>' if wa_number else ''}
            """

            text_body = (
                f"Hi {first_name},\n\n"
                f"Your SwiftPOS {label} for {company.name} expires in {days_left} day(s) "
                f"on {sub.expiry_date.strftime('%d %B %Y')}.\n\n"
                f"Plan: {sub.plan.name}\n\n"
                f"Renew here: {manage_url}\n\n"
                f"— SwiftPOS"
            )

            html = _render_email_html(
                company_name=company.name,
                title=f"Your {label_cap} Expires Soon",
                subtitle=f"{days_left} day{'s' if days_left != 1 else ''} remaining — {company.name}",
                header_color=urgency_color,
                body_html=body_html,
                footer_note='You are receiving this because you are an admin of a SwiftPOS account. Do not reply.',
            )

            msg = _make_email(subject, text_body, html, [admin_user.email])
            msg.send(fail_silently=True)
            logger.info(f"📧 Expiry warning sent to {admin_user.email} ({days_left} days)")
        except Exception as e:
            logger.error(f"Failed to send expiry email to {company.slug}: {e}")
