from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional


@dataclass(frozen=True)
class Periodo:
    inicio: datetime
    fim: Optional[datetime] = None

    @property
    def ativo(self) -> bool:
        return self.fim is None

    @property
    def anos_decorridos(self) -> float:
        fim = self.fim if self.fim else datetime.now()
        dias = (fim - self.inicio).days
        return round(dias / 365.25, 1)

    def anos_completos(self, data_referencia: Optional[datetime] = None) -> int:
        """
        Retorna apenas anos completos entre início e fim (ou data de referência).
        Usado para pontuação que desconsidera frações de ano.
        """
        fim = self.fim or data_referencia or datetime.now()
        if fim < self.inicio:
            return 0
        return int((fim - self.inicio).days // 365)

    def __post_init__(self) -> None:
        if self.fim and self.fim < self.inicio:
            object.__setattr__(self, "fim", None)


def mesclar_periodos(periodos: List[Periodo]) -> List[Periodo]:
    if not periodos:
        return []
    periodos_ordenados = sorted(
        periodos, key=lambda p: p.inicio if p.inicio else datetime.min
    )
    mesclados: List[Periodo] = []
    for p in periodos_ordenados:
        if not mesclados:
            mesclados.append(p)
            continue
        ultimo = mesclados[-1]
        ultimo_fim = ultimo.fim or datetime.now()
        atual_fim = p.fim or datetime.now()
        if p.inicio and p.inicio <= ultimo_fim:
            novo_fim = max(ultimo_fim, atual_fim)
            mesclados[-1] = Periodo(
                inicio=ultimo.inicio,
                fim=None if (ultimo.ativo or p.ativo) else novo_fim
            )
        else:
            mesclados.append(p)
    return mesclados


def anos_completos_periodos(periodos: List[Periodo], data_ref: Optional[datetime] = None) -> int:
    ref = data_ref or datetime.now()
    return sum(p.anos_completos(ref) for p in periodos)
