# retoor <retoor@molodetz.nl>

from typing import Annotated

from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse

from devplacepy.models import GameSlotForm
from devplacepy.responses import respond, wants_json
from devplacepy.schemas import GameFarmViewOut
from devplacepy.services.game import GameError, store
from devplacepy.services.audit import record as audit
from devplacepy.utils import (
    create_notification,
    get_current_user,
    require_user,
    track_action,
)

from ._shared import action_error, game_seo, notify_farm, owner_by_username

router = APIRouter()


@router.get("/farm/{username}", response_class=HTMLResponse)
async def view_farm(request: Request, username: str):
    viewer = get_current_user(request)
    owner = owner_by_username(username)
    if not owner:
        raise HTTPException(status_code=404, detail="Farm not found")
    farm = store.ensure_farm(owner["uid"])
    data = store.serialize_farm(farm, viewer=viewer, owner=owner)
    seo_ctx = game_seo(
        request,
        f"{owner['username']}'s Code Farm",
        f"Visit {owner['username']}'s Code Farm on DevPlace and water their builds.",
    )
    return respond(
        request,
        "game_farm.html",
        {
            **seo_ctx,
            "request": request,
            "user": viewer,
            "viewer": viewer,
            "farm": data,
            "game_error": request.query_params.get("error", ""),
        },
        model=GameFarmViewOut,
    )


@router.post("/farm/{username}/water")
async def water_farm(
    request: Request, username: str, data: Annotated[GameSlotForm, Form()]
):
    viewer = require_user(request)
    owner = owner_by_username(username)
    if not owner:
        raise HTTPException(status_code=404, detail="Farm not found")
    try:
        result = store.water(viewer, owner, data.slot)
    except GameError as exc:
        return action_error(request, str(exc), f"/game/farm/{username}")
    track_action(viewer["uid"], "water")
    audit.record(
        request,
        "game.water",
        user=viewer,
        target_type="user",
        target_uid=owner["uid"],
        target_label=owner["username"],
        metadata=result,
        summary=(
            f"{viewer['username']} watered {owner['username']}'s build on plot "
            f"{result['slot']} and earned {result['reward_coins']} coins"
        ),
        links=[audit.target("user", owner["uid"], owner["username"])],
    )
    await notify_farm(owner["username"])
    if wants_json(request):
        payload = store.serialize_farm(
            store.ensure_farm(owner["uid"]), viewer=viewer, owner=owner
        )
        return JSONResponse(GameFarmViewOut(farm=payload).model_dump(mode="json"))
    return RedirectResponse(url=f"/game/farm/{username}", status_code=302)


@router.post("/farm/{username}/steal")
async def steal_farm(
    request: Request, username: str, data: Annotated[GameSlotForm, Form()]
):
    viewer = require_user(request)
    owner = owner_by_username(username)
    if not owner:
        raise HTTPException(status_code=404, detail="Farm not found")
    try:
        result = store.steal(viewer, owner, data.slot)
    except GameError as exc:
        return action_error(request, str(exc), f"/game/farm/{username}")
    track_action(viewer["uid"], "harvest_stolen")
    track_action(owner["uid"], "got_stolen_from")
    if result.get("underdog_triggered"):
        track_action(viewer["uid"], "underdog_raid")
    audit.record(
        request,
        "game.steal",
        user=viewer,
        target_type="user",
        target_uid=owner["uid"],
        target_label=owner["username"],
        metadata={
            "thief_uid": viewer["uid"],
            "thief_username": viewer["username"],
            "owner_uid": owner["uid"],
            "owner_username": owner["username"],
            "slot": result["slot"],
            "crop": result["crop"],
            "coins": result["coins"],
            "share": result["share"],
            "underdog_triggered": result.get("underdog_triggered", False),
        },
        summary=(
            f"{viewer['username']} raided {owner['username']}'s Code Farm and took "
            f"{result['coins']} coins ({round(result['share'] * 100)}%) from their "
            f"{result['crop_name']} build"
        ),
        links=[audit.target("user", owner["uid"], owner["username"])],
    )
    create_notification(
        owner["uid"],
        "harvest_stolen",
        (
            f"{viewer['username']} raided your Code Farm and took "
            f"{result['coins']} coins ({round(result['share'] * 100)}%) "
            f"from your {result['crop_name']} build. You keep the rest - harvest it."
        ),
        viewer["uid"],
        "/game",
    )
    await notify_farm(owner["username"])
    await notify_farm(viewer["username"])
    if wants_json(request):
        payload = store.serialize_farm(
            store.ensure_farm(owner["uid"]), viewer=viewer, owner=owner
        )
        return JSONResponse(
            GameFarmViewOut(farm=payload, stole_coins=result["coins"]).model_dump(
                mode="json"
            )
        )
    return RedirectResponse(url=f"/game/farm/{username}", status_code=302)
