from typing import Annotated

from fastapi import (
    APIRouter,
    BackgroundTasks,
    Cookie,
    File,
    Form,
    Request,
)
from fastapi.templating import Jinja2Templates

from rvpc.auth.device import MatchingDevice
from rvpc.auth.text_fields import encrypt_field
from rvpc.auth.tokens.capture_tokens import CaptureEnabled
from rvpc.auth.tokens.user_tokens import AuthentifiedUser, generate_user_token
from rvpc.auth.users import (
    SelectedCardContent,
    UserFromMail,
    UserVideo,
    decrypt_user_key,
)
from rvpc.celery.celery_app import count_cards
from rvpc.db import SessionDep
from rvpc.models.models import CardContent, TokenInfo, Video
from rvpc.moderation.mistral import Moderated
from rvpc.pydantic_models import CardData
from rvpc.routers.cards.tasks import convert_and_notify
from rvpc.routers.cards.video import edit_and_save
from rvpc.routers.map.messages import new_card_message
from rvpc.routers.utils import HXRequest, hx_redirect, page_refresh, smart


def make_cards(prefix: str, templates: Jinja2Templates):
    cards = APIRouter(prefix=prefix)

    @cards.get("/new")
    @smart("cards/new.html")
    async def render_new(
        capture_enabled: CaptureEnabled,
        matching_device: MatchingDevice,
        location: Annotated[str, Cookie()],
    ):
        if capture_enabled and (matching_device is not None):
            return {"location": location}

        response = hx_redirect(path="/device/menu")
        return response

    @cards.get("/your_card")
    @smart("cards/card.html")
    async def render_card(
        video: UserVideo,
        card_content: SelectedCardContent,
    ):
        return CardData(
            sender=card_content.sender,
            recipient=card_content.recipient,
            msg=card_content.msg,
            video_url=video.raw,
        )

    @cards.get("/test_new")
    async def test_new(
        request: Request,
    ):
        await new_card_message(request, "Paris")

    lorem_ipsum = """Lorem ipsum dolor sit amet,
    consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris 
    nisi ut aliquip ex ea commodo consequat.
    Duis aute irure dolor in reprehenderit in
    voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    Excepteur sint occaecat cupidatat non proident,
    sunt in culpa qui officia deserunt mollit anim id est laborum."""

    @cards.get("/test_card")
    async def render_test_card(
        request: Request,
        HX_Request: HXRequest = None,
    ):
        if HX_Request:
            return templates.TemplateResponse(
                request=request,
                name="/cards/card.html",
                context=CardData(
                    sender="Test",
                    recipient="Test",
                    msg=lorem_ipsum,
                    video_url="raw__Iv2zHrJEfsi1hKPtQntfA.webm",
                ).model_dump(),
            )
        else:
            return page_refresh(
                request=request,
            )

    @cards.get("/add_content")
    @smart("cards/content_form.html")
    async def render_content_form(
        video: UserVideo,
        capture_enabled: CaptureEnabled,
        location: Annotated[str, Cookie()],
    ):
        if capture_enabled:
            return {"id": video.id, "location": location}
        response = hx_redirect(path="/admin/login")
        response.status_code = 403
        return response

    @cards.post("/add_content")
    async def process_content(
        video: UserVideo,
        moderated: Moderated,
        capture_enabled: CaptureEnabled,
        current_user: AuthentifiedUser,
        background_tasks: BackgroundTasks,
        session: SessionDep,
        sender: Annotated[str, Form()],
        recipient: Annotated[str, Form()],
        msg: Annotated[str, Form()],
        location: str,
    ):
        if moderated:
            if capture_enabled:
                user_key = decrypt_user_key(current_user.encrypted_key)
                content = CardContent(
                    from_enc=encrypt_field(
                        user_key=user_key, plaintext=sender
                    ),
                    to_enc=encrypt_field(
                        user_key=user_key, plaintext=recipient
                    ),
                    msg_enc=encrypt_field(user_key=user_key, plaintext=msg),
                    video_id=video.id,
                )

                session.add(content)
                session.commit()
                session.refresh(content)

                background_tasks.add_task(
                    convert_and_notify,
                    video=video,
                    user=current_user,
                    session=session,
                )

                count_cards.delay()
                return hx_redirect(
                    path=f"/cards/your_card?id={video.id}&location={location}"
                )
            response = hx_redirect(path="/admin/login")
            response.status_code = 403

            return response

        response = hx_redirect(path="/cards/warning")
        response.status_code = 403

        return response

    @cards.get("/warning")
    @smart("moderation/warning.html")
    async def warn_user(location: Annotated[str, Cookie()]):
        return {"location": location}

    @cards.post("/new")
    async def process_form(
        capture_enabled: CaptureEnabled,
        current_user: UserFromMail,
        start: Annotated[float, Form()],
        end: Annotated[float, Form()],
        content_option: Annotated[str, Form()],
        video_file: Annotated[bytes, File()],
        session: SessionDep,
        request: Request,
        location: Annotated[str, Cookie()],
    ):
        if capture_enabled:
            raw_file = edit_and_save(
                video_file=video_file, start=start, end=end
            )

            video = Video(
                raw=raw_file,
                user_hashid=current_user.hashid,
                length=(end - start),
                location_name=location,
            )

            session.add(video)
            session.commit()
            session.refresh(video)

            token, generic_token = generate_user_token(
                user=current_user, expires_in=1800
            )

            session.add(
                TokenInfo(
                    nonce=generic_token.nonce,
                    expires_at=generic_token.expires_at,
                    token_type=generic_token.token_type,
                )
            )
            session.commit()

            if content_option == "here":
                response = hx_redirect(
                    path=f"/cards/add_content?id={video.id}&location={location}",
                    target="main",
                )
                response.set_cookie(
                    "user_session", value=token, httponly=True, secure=False
                )

                return response

            elif content_option == "there":
                response = templates.TemplateResponse(
                    request=request, name="cards/notify.html"
                )

                return response

        response = hx_redirect(path="/admin/login")
        response.status_code = 403
        return response

    return cards
