"""30-minute slot math: convert between datetimes, slot indexes, and exam durations."""

import calendar
import math
from datetime import datetime, timedelta, timezone

from api.views.admin.session_generate import _find_matching_session


SLOT_MINUTES = 30
SLOT_SECONDS = SLOT_MINUTES * 60
EPOCH_START = datetime(1970, 1, 1)


def _duration_time(requirement):
	total_duration = timedelta()

	if requirement.writing_time:
		total_duration += timedelta(
			hours=requirement.writing_time.hour,
			minutes=requirement.writing_time.minute,
			seconds=requirement.writing_time.second,
		)
	if requirement.reading_time:
		total_duration += timedelta(
			hours=requirement.reading_time.hour,
			minutes=requirement.reading_time.minute,
			seconds=requirement.reading_time.second,
		)

	if total_duration == timedelta():
		total_duration = timedelta(hours=1)

	return (datetime.min + total_duration).time()


def _duration_slots(requirement):
	duration = _duration_time(requirement)
	total_seconds = duration.hour * 3600 + duration.minute * 60 + duration.second
	return max(1, math.ceil(total_seconds / (SLOT_MINUTES * 60)))


def _slot_to_datetime(exam_period, time_slot):
	if time_slot is None:
		return None
	return EPOCH_START + timedelta(seconds=int(time_slot) * SLOT_SECONDS)


def _existing_session_for_slot(exam_period, time_slot, location):
	if exam_period is None:
		return None
	start_time = _slot_to_datetime(exam_period, time_slot)
	if start_time is None:
		return None
	location_id = location.id if location is not None else None
	return _find_matching_session(start_time, location_id, exam_period.id)


def _datetime_to_slot(exam_period, value):
	if value.tzinfo is not None:
		value = value.astimezone(timezone.utc).replace(tzinfo=None)
	epoch_seconds = calendar.timegm(value.timetuple())
	if epoch_seconds < 0:
		return None
	if epoch_seconds % SLOT_SECONDS != 0:
		return None
	return int(epoch_seconds // SLOT_SECONDS)
