"""
Management command to update email templates, replacing 'tenant_' with 'business_'.

This updates both PuckEmailTemplate and CustomEmailTemplate across all tenants.
"""
import json
import re
from django.core.management.base import BaseCommand
from django_tenants.utils import schema_context, get_tenant_model

from smoothschedule.communication.messaging.models import PuckEmailTemplate, CustomEmailTemplate


class Command(BaseCommand):
    help = 'Replace tenant_ with business_ in all email templates'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Show what would be changed without actually changing it',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']

        if dry_run:
            self.stdout.write(self.style.WARNING('DRY RUN - no changes will be made'))

        Tenant = get_tenant_model()
        tenants = Tenant.objects.exclude(schema_name='public')

        total_puck_updated = 0
        total_custom_updated = 0

        for tenant in tenants:
            self.stdout.write(f'\nProcessing tenant: {tenant.name} ({tenant.schema_name})')

            with schema_context(tenant.schema_name):
                # Update PuckEmailTemplate
                puck_count = self._update_puck_templates(dry_run)
                total_puck_updated += puck_count

                # Update CustomEmailTemplate
                custom_count = self._update_custom_templates(dry_run)
                total_custom_updated += custom_count

        self.stdout.write(self.style.SUCCESS(
            f'\nTotal updated: {total_puck_updated} PuckEmailTemplates, '
            f'{total_custom_updated} CustomEmailTemplates'
        ))

    def _replace_tenant_with_business(self, text):
        """Replace tenant_ with business_ in a string."""
        if not text:
            return text, False

        # Pattern to match tenant_ prefix (e.g., tenant_name, tenant_email)
        pattern = r'\{\{\s*tenant_(\w+)\s*\}\}'
        replacement = r'{{ business_\1 }}'

        new_text = re.sub(pattern, replacement, text)
        changed = new_text != text
        return new_text, changed

    def _replace_in_json(self, data):
        """Recursively replace tenant_ with business_ in JSON structure."""
        changed = False

        if isinstance(data, str):
            new_data, was_changed = self._replace_tenant_with_business(data)
            return new_data, was_changed
        elif isinstance(data, dict):
            new_dict = {}
            for key, value in data.items():
                new_value, was_changed = self._replace_in_json(value)
                new_dict[key] = new_value
                if was_changed:
                    changed = True
            return new_dict, changed
        elif isinstance(data, list):
            new_list = []
            for item in data:
                new_item, was_changed = self._replace_in_json(item)
                new_list.append(new_item)
                if was_changed:
                    changed = True
            return new_list, changed
        else:
            return data, False

    def _update_puck_templates(self, dry_run):
        """Update PuckEmailTemplate records."""
        updated_count = 0

        for template in PuckEmailTemplate.objects.all():
            subject_changed = False
            puck_changed = False

            # Check and update subject
            new_subject, subject_changed = self._replace_tenant_with_business(
                template.subject_template
            )

            # Check and update puck_data
            new_puck_data, puck_changed = self._replace_in_json(template.puck_data)

            if subject_changed or puck_changed:
                self.stdout.write(
                    f'  PuckEmailTemplate [{template.email_type}]: '
                    f'subject_changed={subject_changed}, puck_changed={puck_changed}'
                )

                if subject_changed:
                    self.stdout.write(f'    Subject: {template.subject_template}')
                    self.stdout.write(f'         -> {new_subject}')

                if not dry_run:
                    template.subject_template = new_subject
                    template.puck_data = new_puck_data
                    # Skip validation to allow any changes
                    PuckEmailTemplate.objects.filter(pk=template.pk).update(
                        subject_template=new_subject,
                        puck_data=new_puck_data
                    )

                updated_count += 1

        return updated_count

    def _update_custom_templates(self, dry_run):
        """Update CustomEmailTemplate records."""
        updated_count = 0

        for template in CustomEmailTemplate.objects.all():
            subject_changed = False
            puck_changed = False

            # Check and update subject
            new_subject, subject_changed = self._replace_tenant_with_business(
                template.subject_template
            )

            # Check and update puck_data
            new_puck_data, puck_changed = self._replace_in_json(template.puck_data)

            if subject_changed or puck_changed:
                self.stdout.write(
                    f'  CustomEmailTemplate [{template.slug}]: '
                    f'subject_changed={subject_changed}, puck_changed={puck_changed}'
                )

                if subject_changed:
                    self.stdout.write(f'    Subject: {template.subject_template}')
                    self.stdout.write(f'         -> {new_subject}')

                if not dry_run:
                    CustomEmailTemplate.objects.filter(pk=template.pk).update(
                        subject_template=new_subject,
                        puck_data=new_puck_data
                    )

                updated_count += 1

        return updated_count
