import dataclasses
from typing import Annotated

from fastapi import HTTPException, Request
from fastapi.params import Form
from fastapi.responses import HTMLResponse
from folkugat_web.api.router import get_router
from folkugat_web.fragments import tema, temes
from folkugat_web.model.temes import Tema
from folkugat_web.services import auth
from folkugat_web.services import files as files_service
from folkugat_web.services.temes import links as links_service
from folkugat_web.services.temes import lyrics as lyrics_service
from folkugat_web.services.temes import properties as properties_service
from folkugat_web.services.temes import query as temes_q
from folkugat_web.services.temes import scores as scores_service
from folkugat_web.services.temes import write as temes_w
from folkugat_web.templates import templates
from folkugat_web.utils import FnChain

router = get_router()


def _build_page_description(tema: Tema) -> str:
    info_lines = []
    if composer := tema.composer():
        info_lines.append(f"Autor: {composer}")
    if origin := tema.origin():
        info_lines.append(f"Orígen: {origin}")
    return "\n".join(info_lines)


@router.get("/tema/{tema_id}")
def page(request: Request, logged_in: auth.LoggedIn, tema_id: int):
    tema = temes_q.get_tema_by_id(tema_id)
    if not tema:
        raise HTTPException(status_code=404, detail="Could not find tune")
    tema = (
        FnChain.transform(tema) |
        scores_service.add_scores_to_tema |
        properties_service.add_properties_to_tema
    ).result()
    return templates.TemplateResponse(
        "index.html",
        {
            "request": request,
            "page_title": f"Folkugat - {tema.title}",
            "page_description": _build_page_description(tema),
            "page_card": "",
            "content": f"/api/tema/{tema_id}",
            "logged_in": logged_in,
        }
    )


def augment_played_with(tema: Tema) -> Tema:
    if tema.played_with:
        tema.played_with = [
            dataclasses.replace(
                co_tema,
                tema=(
                    FnChain.transform(co_tema.tema) |
                    scores_service.add_scores_to_tema |
                    properties_service.add_properties_to_tema
                ).result()
            ) for co_tema in tema.played_with
        ]
    return tema


@router.get("/api/tema/{tema_id}")
def contingut(request: Request, logged_in: auth.LoggedIn, tema_id: int):
    tema = temes_q.get_tema_by_id(tema_id)
    if not tema:
        raise HTTPException(status_code=404, detail="Could not find tune")
    tema = (
        FnChain.transform(tema) |
        temes_q.tema_compute_stats |
        temes_q.tema_compute_played_with |
        augment_played_with |
        links_service.add_links_to_tema |
        lyrics_service.add_lyrics_to_tema |
        scores_service.add_scores_to_tema |
        properties_service.add_properties_to_tema
    ).result()
    return temes.tema(request, logged_in, tema)


@router.delete("/api/tema/{tema_id}")
def delete_tema(_: auth.RequireLogin, tema_id: int):
    tema = temes_q.get_tema_by_id(tema_id)
    if not tema:
        raise HTTPException(status_code=404, detail="Could not find tune")
    tema = temes_q.tema_compute_stats(tema=tema)
    if tema.stats:
        raise HTTPException(status_code=400, detail="Can't delete a tune that has been played in a set!")
    temes_w.delete_tema(tema_id=tema_id)
    files_service.clean_orphan_files()
    return HTMLResponse(headers={
        'HX-Redirect': '/temes'
    })


@router.post("/api/tema")
def create_tema(_: auth.RequireLogin, title: Annotated[str, Form()] = ""):
    new_tema = temes_w.create_tema(title=title)
    return HTMLResponse(headers={
        'HX-Redirect': f'/tema/{new_tema.id}'
    })


@router.get("/api/tema/{tema_id}/title")
def title(request: Request, logged_in: auth.LoggedIn, tema_id: int):
    return tema.title(request=request, tema_id=tema_id, logged_in=logged_in)


@router.put("/api/tema/{tema_id}/title")
def set_title(
    request: Request,
    logged_in: auth.RequireLogin,
    tema_id: int,
    title: Annotated[str, Form()],
):
    new_tema = temes_w.update_title(tema_id=tema_id, title=title)
    return tema.title(request=request, tema=new_tema, logged_in=logged_in)


@router.put("/api/tema/{tema_id}/visible")
def set_visible(request: Request, logged_in: auth.RequireLogin, tema_id: int):
    new_tema = temes_w.set_visibility(tema_id=tema_id, hidden=False)
    return tema.visibility(
        request=request,
        logged_in=logged_in,
        tema=new_tema,
    )


@router.put("/api/tema/{tema_id}/invisible")
def set_invisible(request: Request, logged_in: auth.RequireLogin, tema_id: int):
    new_tema = temes_w.set_visibility(tema_id=tema_id, hidden=True)
    return tema.visibility(
        request=request,
        logged_in=logged_in,
        tema=new_tema,
    )
