import dataclasses
import re
from collections.abc import Iterable, Iterator
from typing import Callable

from folkugat_web.dal.sql.temes import lyrics as lyrics_dal
from folkugat_web.model import temes as model
from folkugat_web.utils import FnChain


def _sub(pattern: str, sub: str) -> Callable[[str], str]:
    def _inner_sub(text: str) -> str:
        return re.sub(pattern, sub, text)
    return _inner_sub


def _clean_string(lyrics_str: str) -> str:
    return (
        FnChain.transform(lyrics_str) |
        # _sub(r"~", "") |
        _sub(r"\t", " ") |
        _sub(r" +", " ") |
        _sub(r" \n", "\n") |
        _sub(r"\n ", "\n") |
        _sub(r"\n\n+", "\n\n")
    ).result()


def add_lyrics_to_tema(tema: model.Tema) -> model.Tema:
    if tema.id is not None:
        tema.lyrics = list(lyrics_dal.get_lyrics(tema_id=tema.id))
    return tema


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


def get_lyric_by_id(lyric_id: int, tema_id: int | None = None) -> model.Lyrics | None:
    return next(iter(lyrics_dal.get_lyrics(lyric_id=lyric_id, tema_id=tema_id)), None)


def update_lyric(lyric: model.Lyrics, title: str, content: str, max_columns: int | None = None):
    # Validate max_columns if provided
    if max_columns is not None:
        if not isinstance(max_columns, int) or max_columns < 1 or max_columns > 10:
            raise ValueError("max_columns must be an integer between 1 and 10")

    lyric = dataclasses.replace(lyric, title=title.strip(), content=_clean_string(content), max_columns=max_columns)
    lyrics_dal.update_lyric(lyric=lyric)
    return lyric


def delete_lyric(lyric_id: int, tema_id: int | None = None):
    lyrics_dal.delete_lyric(lyric_id=lyric_id, tema_id=tema_id)


def create_lyric(tema_id: int) -> model.Lyrics:
    return lyrics_dal.create_lyric(tema_id=tema_id)
