"""Revisions domain - business logic."""
from uuid import UUID

from src.core.exceptions import ForbiddenError, NotFoundError
from src.domain.revisions.interfaces import ProjectFacade
from src.domain.revisions.models import ProjectRevision
from src.domain.revisions.repository import RevisionRepository, RevisionTagRepository


class RevisionService:
    def __init__(
        self,
        revision_repo: RevisionRepository,
        tag_repo: RevisionTagRepository,
        project_facade: ProjectFacade,
    ):
        self._revision_repo = revision_repo
        self._tag_repo = tag_repo
        self._project_facade = project_facade

    async def list_revisions(self, project_id: UUID) -> list[ProjectRevision]:
        return await self._revision_repo.list_for_project(project_id)

    async def get_revision(self, revision_id: UUID) -> ProjectRevision:
        rev = await self._revision_repo.get_by_id(revision_id)
        if not rev:
            raise NotFoundError("Revision not found")
        return rev

    async def restore_revision(self, project_id: UUID, revision_id: UUID, user_id: UUID) -> ProjectRevision:
        """Non-destructive restore: creates new revision N+1 pointing to restored SHA."""
        original = await self._revision_repo.get_by_id(revision_id)
        if not original or original.project_id != project_id:
            raise NotFoundError("Revision not found")

        return await self._revision_repo.create(
            project_id=project_id,
            git_sha=original.git_sha,
            source="restore",
            source_id=revision_id,
            commit_message=f"Restored from revision #{original.revision_number}",
            created_by=user_id,
        )

    async def tag_revision(self, revision_id: UUID, tag: str, user_id: UUID):
        rev = await self._revision_repo.get_by_id(revision_id)
        if not rev:
            raise NotFoundError("Revision not found")
        return await self._tag_repo.create(revision_id, tag, user_id)

    async def get_diff(self, project_id: UUID, revision_id: UUID, to_revision_id: UUID) -> dict:
        """Get diff between two revisions. Returns raw diff info."""
        rev_from = await self._revision_repo.get_by_id(revision_id)
        rev_to = await self._revision_repo.get_by_id(to_revision_id)
        if not rev_from or not rev_to:
            raise NotFoundError("Revision not found")
        if rev_from.project_id != project_id or rev_to.project_id != project_id:
            raise NotFoundError("Revision not in this project")

        repo_name = await self._project_facade.get_project_repo_full_name(project_id)
        if not repo_name:
            raise NotFoundError("Project repo not found")

        return {
            "from_revision": rev_from.revision_number,
            "to_revision": rev_to.revision_number,
            "from_sha": rev_from.git_sha,
            "to_sha": rev_to.git_sha,
            "repo": repo_name,
        }
