from collections.abc import Iterable, Iterator

from fastapi import HTTPException
from folkugat_web.dal.sql.temes import scores as scores_dal
from folkugat_web.model import temes as model
from folkugat_web.services import lilypond
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.utils import FnChain


def add_scores_to_tema(tema: model.Tema) -> model.Tema:
    if tema.id is not None:
        tema.scores = list(scores_dal.get_scores(tema_id=tema.id))
    return tema


def add_scores_to_temes(temes: Iterable[model.Tema]) -> Iterator[model.Tema]:
    return map(add_scores_to_tema, temes)


def get_score_by_id(score_id: int, tema_id: int | None = None) -> model.Score | None:
    return next(iter(scores_dal.get_scores(score_id=score_id, tema_id=tema_id)), None)


def update_score(score: model.Score):
    scores_dal.update_score(score=score)


def delete_score(score_id: int, tema_id: int | None = None):
    scores_dal.delete_score(score_id=score_id, tema_id=tema_id)


def create_score(tema_id: int) -> model.Score:
    new_score = model.Score(
        id=None,
        tema_id=tema_id,
        title="",
        source="",
        errors=[],
        img_url=None,
        pdf_url=None,
        hidden=True,
    )
    return scores_dal.insert_score(score=new_score)


def build_single_tune_full_source(tema_id: int, source: str) -> str:
    tema = temes_q.get_tema_by_id(tema_id)
    if not tema:
        raise HTTPException(status_code=404, detail="Could not find tema!")
    tema = (
        FnChain.transform(tema) |
        properties_service.add_properties_to_tema |
        lyrics_service.add_lyrics_to_tema
    ).result()
    return lilypond.source_to_single_score(source=source, tema=tema)
