"""Shared labels, id helpers, response payloads, and activity writes."""

from datetime import datetime, timedelta

from rest_framework.exceptions import ValidationError

from api.models import EsExamActivity
from api.services.exam_scheduler.slots import SLOT_MINUTES, _duration_slots, _duration_time, _slot_to_datetime


def _raise_validation_error(message, field="id"):
	raise ValidationError({
		"error": message,
		"errors": {
			field: [message],
		},
	})


def _normalize_ids(values):
	return [int(value) for value in dict.fromkeys(values or [])]


def _normalize_int_values(values):
	return [int(value) for value in values or []]


def _activity_label(activity):
	return f"{activity.id} - {activity.name}"


def _activity_needs_schedule(activity):
	return not activity.is_scheduled or activity.time_slot is None


def _skipped_activity_labels(activities):
	return [_activity_label(activity) for activity in activities if not _activity_needs_schedule(activity)]


def _activity_labels(activities):
	return [_activity_label(activity) for activity in activities]


def _activity_label_text(activities):
	return "\n".join(_activity_labels(activities))


def _format_scheduled_activity_error(activities):
	return "; ".join(
		f"{activity.id} - {activity.name}"
		for activity in activities
	)


def _build_response_payload(activities, student_map):
	flat_activities = []

	for activity in activities:
		requirement = activity.exam_requirement
		duration = _duration_time(requirement)
		duration_slots = _duration_slots(requirement)
		student_count = len(student_map.get(requirement.id, set()))
		location = activity.location
		start_at = _slot_to_datetime(requirement.exam_period, activity.time_slot)
		end_at = start_at + timedelta(minutes=duration_slots * SLOT_MINUTES) if start_at else None
		flat_activities.append({
			"id": activity.id,
			"code": activity.code,
			"name": activity.name,
			# "exam_requirement_id": requirement.id,
			# "exam_requirement_code": requirement.code,
			# "exam_requirement_name": requirement.name,
			# "exam_period_id": requirement.exam_period_id,
			# "exam_period": requirement.exam_period.name if requirement.exam_period else None,
			# "planned_size": requirement.planned_size,
			# "student_count": student_count,
			# "writing_time": requirement.writing_time,
			# "reading_time": requirement.reading_time,
			"duration": duration,
			"duration_slots": duration_slots,
			# "fixed_start_date": requirement.fixed_start_date,
			# "fixed_start_time": requirement.fixed_start_time,
			"location_required": requirement.location_required,
			# "exclusive_use": requirement.exclusive_use,
			# "minimum_split_size": requirement.minimum_split_size,
			# "earliest_start": requirement.earliest_start,
			# "latest_end": requirement.latest_end,
			"location_id": activity.location_id,
			"location": location.name if location else None,
			"location_code": location.code if location else None,
			# "location_capacity": _location_capacity(location) if location else None,
			# "location_is_partition": location.is_partition if location else None,
			"time_slot": activity.time_slot,
			# "is_scheduled": activity.is_scheduled,
			"scheduled_start_at": start_at,
			"scheduled_end_at": end_at,
		})

	return {
		"activities": flat_activities,
	}


def _apply_activity_changes(changed_activities, user_id):
	if not changed_activities:
		return

	now = datetime.now()
	for activity in changed_activities:
		activity.updated_by = user_id
		activity.updated_at = now

	EsExamActivity.objects.bulk_update(
		changed_activities,
		["time_slot", "location", "session", "is_scheduled", "updated_by", "updated_at"],
	)
