# Generated by Django 5.2.7 on 2025-11-21 08:16

import django.db.models.deletion
import netbox.models.deletion
import taggit.managers
import utilities.json
from decimal import Decimal
from django.db import migrations, models


def migrate_financial_info_to_contract(apps, schema_editor):
    """
    Migrate data from SegmentFinancialInfo to ContractInfo.
    Creates one ContractInfo per SegmentFinancialInfo and links it to the segment.
    """
    SegmentFinancialInfo = apps.get_model("cesnet_service_path_plugin", "SegmentFinancialInfo")
    ContractInfo = apps.get_model("cesnet_service_path_plugin", "ContractInfo")
    ContractSegmentMapping = apps.get_model("cesnet_service_path_plugin", "ContractSegmentMapping")
    Segment = apps.get_model("cesnet_service_path_plugin", "Segment")
    TaggedItem = apps.get_model("extras", "TaggedItem")
    ContentType = apps.get_model("contenttypes", "ContentType")

    from django.utils import timezone

    # Get content types for tag copying
    old_content_type = ContentType.objects.get_for_model(SegmentFinancialInfo)
    new_content_type = ContentType.objects.get_for_model(ContractInfo)

    for old_financial_info in SegmentFinancialInfo.objects.all():
        segment = old_financial_info.segment

        # Determine start_date from segment's install_date or use current date
        start_date = segment.install_date if segment.install_date else timezone.now().date()

        # Determine end_date from segment's termination_date
        end_date = segment.termination_date if segment.termination_date else None

        # Determine number_of_recurring_charges (convert commitment_period_months to number of charges)
        number_of_recurring_charges = old_financial_info.commitment_period_months if old_financial_info.commitment_period_months else None

        # Create new ContractInfo
        contract = ContractInfo.objects.create(
            previous_version=None,
            superseded_by=None,
            contract_number="",
            contract_type="new",
            charge_currency=old_financial_info.charge_currency,
            non_recurring_charge=old_financial_info.non_recurring_charge or Decimal("0"),
            recurring_charge=old_financial_info.monthly_charge,
            recurring_charge_period="monthly",
            number_of_recurring_charges=number_of_recurring_charges,
            start_date=start_date,
            end_date=end_date,
            notes=old_financial_info.notes or "",
            created=old_financial_info.created,
            last_updated=old_financial_info.last_updated,
            custom_field_data=old_financial_info.custom_field_data,
        )

        # Copy tags
        old_tags = TaggedItem.objects.filter(content_type=old_content_type, object_id=old_financial_info.pk)
        for old_tag in old_tags:
            TaggedItem.objects.create(tag=old_tag.tag, content_type=new_content_type, object_id=contract.pk)

        # Create M2M relationship
        ContractSegmentMapping.objects.create(
            contract=contract, segment=segment, notes=f"Migrated from SegmentFinancialInfo on {timezone.now().date()}"
        )


def reverse_migrate_contract_to_financial_info(apps, schema_editor):
    """Reverse migration"""
    SegmentFinancialInfo = apps.get_model("cesnet_service_path_plugin", "SegmentFinancialInfo")
    ContractInfo = apps.get_model("cesnet_service_path_plugin", "ContractInfo")
    ContractSegmentMapping = apps.get_model("cesnet_service_path_plugin", "ContractSegmentMapping")
    TaggedItem = apps.get_model("extras", "TaggedItem")
    ContentType = apps.get_model("contenttypes", "ContentType")

    old_content_type = ContentType.objects.get_for_model(SegmentFinancialInfo)
    new_content_type = ContentType.objects.get_for_model(ContractInfo)

    for contract in ContractInfo.objects.all():
        mapping = ContractSegmentMapping.objects.filter(contract=contract).first()
        if not mapping:
            continue

        segment = mapping.segment

        # Convert number_of_recurring_charges back to commitment_period_months
        commitment_period_months = (
            contract.number_of_recurring_charges if contract.recurring_charge_period == "monthly" else None
        )

        financial_info = SegmentFinancialInfo.objects.create(
            segment=segment,
            monthly_charge=contract.recurring_charge or Decimal("0"),
            charge_currency=contract.charge_currency,
            non_recurring_charge=contract.non_recurring_charge if contract.non_recurring_charge and contract.non_recurring_charge > 0 else None,
            commitment_period_months=commitment_period_months,
            notes=contract.notes,
            created=contract.created,
            last_updated=contract.last_updated,
            custom_field_data=contract.custom_field_data,
        )

        # Copy tags back
        contract_tags = TaggedItem.objects.filter(content_type=new_content_type, object_id=contract.pk)
        for contract_tag in contract_tags:
            TaggedItem.objects.create(tag=contract_tag.tag, content_type=old_content_type, object_id=financial_info.pk)


class Migration(migrations.Migration):

    dependencies = [
        ("cesnet_service_path_plugin", "0032_segment_ownership_type"),
        ("circuits", "0052_extend_circuit_abs_distance_upper_limit"),
        ("extras", "0133_make_cf_minmax_decimal"),
        ("contenttypes", "0002_remove_content_type_name"),  # Add this dependency
    ]

    operations = [
        migrations.CreateModel(
            name="ContractInfo",
            fields=[
                ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
                ("created", models.DateTimeField(auto_now_add=True, null=True)),
                ("last_updated", models.DateTimeField(auto_now=True, null=True)),
                (
                    "custom_field_data",
                    models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
                ),
                ("contract_number", models.CharField(blank=True, help_text="Provider's contract reference number", max_length=100)),
                ("contract_type", models.CharField(default="new", editable=False, help_text="Type of contract (set automatically)", max_length=20)),
                ("charge_currency", models.CharField(blank=True, default="CZK", help_text="Currency for all charges (defaults to CZK if not specified, cannot be changed in amendments)", max_length=3)),
                (
                    "non_recurring_charge",
                    models.DecimalField(blank=True, decimal_places=2, default=Decimal("0"), help_text="One-time fees for this version (setup, installation, etc.)", max_digits=10, null=True),
                ),
                ("recurring_charge", models.DecimalField(blank=True, decimal_places=2, help_text="Recurring fee amount (optional for amendments)", max_digits=10, null=True)),
                ("recurring_charge_period", models.CharField(blank=True, help_text="Frequency of recurring charges (optional for amendments)", max_length=20, null=True)),
                ("number_of_recurring_charges", models.PositiveIntegerField(blank=True, help_text="Number of recurring charge periods in this contract (optional for amendments)", null=True)),
                ("start_date", models.DateField(blank=True, help_text="When this contract version starts (optional)", null=True)),
                ("end_date", models.DateField(blank=True, help_text="When this contract version ends (optional)", null=True)),
                ("notes", models.TextField(blank=True, help_text="Notes specific to this version")),
                (
                    "previous_version",
                    models.OneToOneField(
                        blank=True,
                        editable=False,
                        help_text="Previous version of this contract (creates linear chain)",
                        null=True,
                        on_delete=django.db.models.deletion.PROTECT,
                        related_name="next_version_relation",
                        to="cesnet_service_path_plugin.contractinfo",
                    ),
                ),
                (
                    "superseded_by",
                    models.OneToOneField(
                        blank=True,
                        editable=False,
                        help_text="Newer version that supersedes this contract",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="supersedes",
                        to="cesnet_service_path_plugin.contractinfo",
                    ),
                ),
                ("tags", taggit.managers.TaggableManager(through="extras.TaggedItem", to="extras.Tag")),
            ],
            options={
                "verbose_name": "Contract Info",
                "verbose_name_plural": "Contract Infos",
                "ordering": ("contract_number", "end_date"),
            },
            bases=(netbox.models.deletion.DeleteMixin, models.Model),
        ),
        migrations.CreateModel(
            name="ContractSegmentMapping",
            fields=[
                ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
                ("added_date", models.DateField(auto_now_add=True, help_text="When this segment was added to the contract")),
                ("notes", models.TextField(blank=True, help_text="Notes about this segment-contract relationship")),
                (
                    "contract",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE, to="cesnet_service_path_plugin.contractinfo"
                    ),
                ),
                (
                    "segment",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE, to="cesnet_service_path_plugin.segment"
                    ),
                ),
            ],
            options={
                "verbose_name": "Contract-Segment Mapping",
                "verbose_name_plural": "Contract-Segment Mappings",
                "ordering": ("contract", "segment"),
                "unique_together": {("contract", "segment")},
            },
        ),
        migrations.AddField(
            model_name="contractinfo",
            name="segments",
            field=models.ManyToManyField(
                help_text="Network segments covered by this contract",
                related_name="contracts",
                through="cesnet_service_path_plugin.ContractSegmentMapping",
                to="cesnet_service_path_plugin.segment",
            ),
        ),
        migrations.RunPython(migrate_financial_info_to_contract, reverse_migrate_contract_to_financial_info),
        migrations.DeleteModel(
            name="SegmentFinancialInfo",
        ),
    ]
