"""M2: prosty resolver studia.

Ścieżka 1: exact external ref → update.
Ścieżka 2: name_normalized exact match → reuse + dopnij external_ref.
Ścieżka 3: insert nowego.

(Fuzzy alias matching dochodzi w M3.)
"""
from __future__ import annotations

import logging
import uuid

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.studio import Studio, StudioAlias, StudioExternalRef
from app.normalize.scenes import NormalizedStudio
from app.normalize.text import slugify

log = logging.getLogger(__name__)


def resolve_studio(
    session: Session,
    *,
    norm: NormalizedStudio,
    source_id: uuid.UUID,
) -> Studio:
    if norm.external_id:
        ref = session.execute(
            select(StudioExternalRef).where(
                StudioExternalRef.source_id == source_id,
                StudioExternalRef.external_id == norm.external_id,
            )
        ).scalar_one_or_none()
        if ref is not None:
            studio = session.get(Studio, ref.studio_id)
            assert studio is not None
            _update_studio_fields(studio, norm)
            return studio

    studio = session.execute(
        select(Studio).where(Studio.name_normalized == norm.name_normalized)
    ).scalar_one_or_none()
    if studio is None:
        studio = Studio(
            name=norm.name,
            name_normalized=norm.name_normalized,
            slug=_unique_slug(session, norm.slug or slugify(norm.name) or "studio"),
            network=norm.network,
            homepage_url=norm.homepage_url,
        )
        session.add(studio)
        session.flush()
        log.debug("studio create id=%s name=%s", studio.id, studio.name)
    else:
        _update_studio_fields(studio, norm)

    if norm.external_id:
        existing_ref = session.execute(
            select(StudioExternalRef).where(
                StudioExternalRef.source_id == source_id,
                StudioExternalRef.external_id == norm.external_id,
            )
        ).scalar_one_or_none()
        if existing_ref is None:
            session.add(
                StudioExternalRef(
                    source_id=source_id,
                    external_id=norm.external_id,
                    studio_id=studio.id,
                    confidence=1.0,
                )
            )

    return studio


def _update_studio_fields(studio: Studio, norm: NormalizedStudio) -> None:
    if norm.network and not studio.network:
        studio.network = norm.network
    if norm.homepage_url and not studio.homepage_url:
        studio.homepage_url = norm.homepage_url


def _unique_slug(session: Session, base: str) -> str:
    candidate = base
    n = 1
    while session.execute(select(Studio.id).where(Studio.slug == candidate)).first():
        n += 1
        candidate = f"{base}-{n}"
    return candidate


def add_alias_if_missing(
    session: Session,
    *,
    studio_id: uuid.UUID,
    alias: str,
    alias_normalized: str,
    source_id: uuid.UUID | None,
) -> None:
    existing = session.execute(
        select(StudioAlias).where(
            StudioAlias.studio_id == studio_id,
            StudioAlias.alias_normalized == alias_normalized,
        )
    ).scalar_one_or_none()
    if existing is None:
        session.add(
            StudioAlias(
                studio_id=studio_id,
                alias=alias,
                alias_normalized=alias_normalized,
                source_id=source_id,
            )
        )
