from datetime import datetime, timezone

from ninja import NinjaAPI, Schema

from allianceauth.services.hooks import get_extension_logger

from incursions.api.helpers.sse import SSEClient, SSEEvent
from incursions.api.schema import CharacterSchema
from incursions.app_settings import SSE_SECRET, SSE_SITE_URL
from incursions.models.waitlist import Announcement


class RequestPayloadSchema(Schema):
    message: str
    is_alert: bool
    pages: str | None


class AnnouncementSchema(Schema):
    id: int
    message: str
    is_alert: bool
    pages: str | None
    created_by: CharacterSchema | None
    created_at: datetime
    revoked_by: CharacterSchema | None
    revoked_at: datetime | None


sse_client = SSEClient(SSE_SITE_URL, SSE_SECRET)

logger = get_extension_logger(__name__)

api = NinjaAPI()


def setup(api: NinjaAPI) -> None:
    AnnouncementAPIEndpoints(api)


class AnnouncementAPIEndpoints:

    tags = ["Announcements"]

    def __init__(self, api: NinjaAPI) -> None:

        @api.get("/announcements", response={200: list[AnnouncementSchema], 403: dict}, tags=self.tags)
        def list_announcements(request):
            if not request.user.has_perm("incursions.basic_waitlist"):
                return 403, {"error": "Permission denied"}

            return Announcement.objects.filter(revoked_at__isnull=True)

        @api.post("/announcements", tags=self.tags, response={200: dict, 403: dict})
        def create_announcement(request, payload: RequestPayloadSchema):
            if not request.user.has_perm("incursions.manage_announcements"):
                return 403, {"error": "Permission denied"}

            announcement = Announcement.objects.create(
                message=payload.message,
                is_alert=payload.is_alert,
                pages=payload.pages,
                created_by=request.user,
                created_at=datetime.now(timezone.utc),
            )
            sse_client.submit([SSEEvent.new_json(topic="announcements", event="announcement;new", data=AnnouncementSchema.from_orm(announcement))])
            return 200, {"id": announcement.pk, "status": "Created"}

        @api.put("/announcements/{announcement_id}", response={200: dict, 403: dict, 404: dict}, tags=self.tags)
        def update_announcement(request, announcement_id: int, payload: RequestPayloadSchema):
            if not request.user.has_perm("incursions.manage_announcements"):
                return 403, {"error": "Permission denied"}

            announcement = Announcement.objects.filter(id=announcement_id, revoked_at__isnull=True).first()
            if not announcement:
                return 404, {"error": "Announcement not found"}

            announcement.message = payload.message
            announcement.is_alert = payload.is_alert
            announcement.pages = payload.pages
            announcement.created_by = request.user
            announcement.save()

            sse_client.submit([SSEEvent.new_json(topic="announcements", event="announcement;updated", data=AnnouncementSchema.from_orm(announcement))])
            return 200, {"status": "Updated"}

        @api.delete("/announcements/{announcement_id}",response={200: dict, 403: dict, 404: dict}, tags=self.tags)
        def revoke_announcement(request, announcement_id: int):
            if not request.user.has_perm("incursions.manage_announcements"):
                return 403, {"error": "Permission denied"}

            announcement = Announcement.objects.filter(id=announcement_id, revoked_at__isnull=True).first()
            if not announcement:
                return 404, {"error": "Announcement not found or already revoked"}

            announcement.revoked_by = request.user
            announcement.revoked_at = datetime.now(timezone.utc)
            announcement.save()

            sse_client.submit([SSEEvent.new_json(topic="announcements", event="announcement;updated", data=AnnouncementSchema.from_orm(announcement))])
            return 200, {"status": "Revoked"}
