# Generated by Django 5.2.4 on 2026-09-21 17:10

import json

import django.db.models.deletion
from django.db import migrations, models

SETTING_PARAM = "invigilator_setting"
SCOPE_SESSION = 1
QUANTITY_MODE_FIXED = 1
QUANTITY_MODE_RATIO = 2
DEFAULT_INVIGILATOR_SETTING = {
	"fixed_invigilators": [{"quantity": 0, "role_ids": []}],
	"students_count": 0,
	"invigilators_count": 0,
	"include_fixed_invigilators": False,
}


def _as_int(value, default=0):
	try:
		if isinstance(value, bool):
			return default
		return int(value)
	except (TypeError, ValueError):
		return default


def migrate_invigilator_setting(apps, schema_editor):
	EsSetting = apps.get_model("api", "EsSetting")
	EsInvigilatorSetting = apps.get_model("api", "EsInvigilatorSetting")
	EsInvigilatorSettingRole = apps.get_model("api", "EsInvigilatorSettingRole")
	EsInvigilatorRole = apps.get_model("api", "EsInvigilatorRole")

	row = EsSetting.objects.filter(param=SETTING_PARAM).first()
	if not row:
		return

	try:
		data = json.loads(row.value) if row.value else {}
	except (TypeError, ValueError, json.JSONDecodeError):
		data = {}
	if not isinstance(data, dict):
		data = {}

	valid_role_ids = set(EsInvigilatorRole.objects.values_list("id", flat=True))
	sort_order = 0

	students_count = max(_as_int(data.get("students_count"), 0), 0)
	invigilators_count = max(_as_int(data.get("invigilators_count"), 0), 0)
	if students_count > 0 and invigilators_count > 0:
		EsInvigilatorSetting.objects.create(
			scope=SCOPE_SESSION,
			quantity_mode=QUANTITY_MODE_RATIO,
			quantity=invigilators_count,
			students_count=students_count,
			sort_order=sort_order,
		)
		sort_order += 1

	fixed_rows = data.get("fixed_invigilators")
	if not isinstance(fixed_rows, list):
		fixed_rows = []
	for fixed in fixed_rows:
		if not isinstance(fixed, dict):
			continue
		quantity = max(_as_int(fixed.get("quantity"), 0), 0)
		if quantity <= 0:
			continue
		role_ids = fixed.get("role_ids") or []
		if not isinstance(role_ids, list):
			role_ids = []
		setting = EsInvigilatorSetting.objects.create(
			scope=SCOPE_SESSION,
			quantity_mode=QUANTITY_MODE_FIXED,
			quantity=quantity,
			students_count=None,
			sort_order=sort_order,
		)
		sort_order += 1
		seen = set()
		for role_id in role_ids:
			parsed = _as_int(role_id, None)
			if parsed is None or parsed in seen or parsed not in valid_role_ids:
				continue
			seen.add(parsed)
			EsInvigilatorSettingRole.objects.create(setting=setting, role_id=parsed)

	row.delete()


def reverse_migrate_invigilator_setting(apps, schema_editor):
	EsSetting = apps.get_model("api", "EsSetting")
	EsInvigilatorSetting = apps.get_model("api", "EsInvigilatorSetting")
	EsInvigilatorSetting.objects.all().delete()
	EsSetting.objects.update_or_create(
		param=SETTING_PARAM,
		defaults={
			"value": json.dumps(DEFAULT_INVIGILATOR_SETTING),
			"comment": "Fixed invigilators, student-to-invigilator ratio, and include/exclude fixed staff",
		},
	)


class Migration(migrations.Migration):

    dependencies = [
        ('api', '0071_invigilator_setting'),
    ]

    operations = [
        migrations.CreateModel(
            name='EsInvigilatorSetting',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('scope', models.SmallIntegerField()),
                ('quantity_mode', models.SmallIntegerField()),
                ('quantity', models.IntegerField()),
                ('students_count', models.IntegerField(null=True)),
                ('sort_order', models.IntegerField()),
                ('created_by', models.BigIntegerField(null=True)),
                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
                ('updated_by', models.BigIntegerField(null=True)),
                ('updated_at', models.DateTimeField(auto_now=True, null=True)),
            ],
            options={
                'db_table': 'es_invigilator_setting',
                'ordering': ['sort_order', 'id'],
            },
        ),
        migrations.CreateModel(
            name='EsInvigilatorSettingRole',
            fields=[
                ('id', models.BigAutoField(primary_key=True, serialize=False)),
                ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.esinvigilatorrole')),
                ('setting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.esinvigilatorsetting')),
            ],
            options={
                'db_table': 'es_invigilator_setting_role',
            },
        ),
        migrations.AddField(
            model_name='esinvigilatorsetting',
            name='role',
            field=models.ManyToManyField(through='api.EsInvigilatorSettingRole', to='api.esinvigilatorrole'),
        ),
        migrations.AddConstraint(
            model_name='esinvigilatorsettingrole',
            constraint=models.UniqueConstraint(fields=('setting', 'role'), name='unique_invigilator_setting_role'),
        ),
        migrations.RunPython(migrate_invigilator_setting, reverse_migrate_invigilator_setting),
    ]
