from __future__ import annotations

import unittest
from datetime import datetime, timezone

from govoplan_core.core.poll import (
    CAPABILITY_POLL_SCHEDULING,
    PollAnswerRef,
    PollOptionUpdateCommand,
    PollResponseRef,
    PollResponseRetirementCommand,
    PollResponseRetirementProvider,
    poll_response_retirement_provider,
)


class _RetirementProvider:
    def retire_responses(self, *args, **kwargs):
        raise NotImplementedError


class _Registry:
    def __init__(self, capability: object | None) -> None:
        self.capability_value = capability

    def has_capability(self, name: str) -> bool:
        return (
            name == CAPABILITY_POLL_SCHEDULING
            and self.capability_value is not None
        )

    def capability(self, name: str) -> object:
        if not self.has_capability(name):
            raise KeyError(name)
        return self.capability_value


class PollContractTests(unittest.TestCase):
    def test_response_ref_remains_backwards_compatible_and_can_carry_answers(self) -> None:
        submitted_at = datetime(2026, 7, 20, tzinfo=timezone.utc)

        legacy = PollResponseRef(None, submitted_at)
        detailed = PollResponseRef(
            invitation_id="invitation-1",
            submitted_at=submitted_at,
            respondent_id="person-1",
            answers=(PollAnswerRef(option_id="option-1", option_key="slot-1", value="available"),),
        )

        self.assertEqual(legacy.answers, ())
        self.assertEqual(detailed.answers[0].value, "available")

    def test_option_update_command_is_a_complete_immutable_snapshot(self) -> None:
        command = PollOptionUpdateCommand(
            label="Tuesday 10:00",
            value={"slot_id": "slot-1"},
            metadata={"source": "scheduling"},
        )

        self.assertEqual(command.label, "Tuesday 10:00")
        self.assertEqual(command.value, {"slot_id": "slot-1"})

    def test_response_retirement_is_an_optional_idempotent_extension(self) -> None:
        command = PollResponseRetirementCommand(
            respondent_ids=("account-1", "alice@example.test"),
            invitation_id="invitation-1",
            reason="scheduling_participant_removed",
            idempotency_key="scheduling:request-1:participant-1:removed",
            metadata={"source_module": "scheduling"},
        )
        provider = _RetirementProvider()

        self.assertEqual(command.respondent_ids[0], "account-1")
        self.assertIsInstance(provider, PollResponseRetirementProvider)
        self.assertIs(
            poll_response_retirement_provider(_Registry(provider)),
            provider,
        )
        self.assertIsNone(poll_response_retirement_provider(_Registry(object())))
        self.assertIsNone(poll_response_retirement_provider(None))


if __name__ == "__main__":
    unittest.main()
