"""
Proposal Manager - CRUD operations for proposals.

Proposals are wiki-style change requests for ontology modifications,
linking a source branch to a target branch.
"""

from __future__ import annotations

import uuid
from typing import Any

from pycharter.wiki.shared.errors import CollaborationError


class ProposalManager:
    """
    Manages proposals for ontology changes.

    Args:
        session: SQLAlchemy session
    """

    def __init__(self, session=None):
        self._session = session

    def _require_session(self):
        if self._session is None:
            raise CollaborationError("No database session configured")

    def create_proposal(
        self,
        contract_id: str,
        title: str,
        author: str,
        description: str | None = None,
        source_branch_id: str | None = None,
        target_branch_id: str | None = None,
    ) -> str:
        """
        Create a new proposal.

        Args:
            contract_id: Contract identifier
            title: Proposal title
            author: Author name
            description: Detailed description
            source_branch_id: Branch with changes
            target_branch_id: Branch to merge into

        Returns:
            UUID string of the created proposal
        """
        self._require_session()

        from pycharter.db.models.wiki.proposal import ProposalModel

        proposal = ProposalModel(
            contract_id=contract_id,
            title=title,
            author=author,
            description=description,
            source_branch_id=uuid.UUID(source_branch_id) if source_branch_id else None,
            target_branch_id=uuid.UUID(target_branch_id) if target_branch_id else None,
            created_by=author,
        )
        self._session.add(proposal)
        self._session.flush()
        return str(proposal.id)

    def get_proposal(self, proposal_id: str) -> dict[str, Any]:
        """
        Get a proposal by ID.

        Args:
            proposal_id: UUID of the proposal

        Returns:
            Proposal dict or None
        """
        self._require_session()

        from pycharter.db.models.wiki.proposal import ProposalModel

        row = (
            self._session.query(ProposalModel)
            .filter(ProposalModel.id == uuid.UUID(proposal_id))
            .first()
        )
        if row is None:
            return None
        return {
            "id": str(row.id),
            "contract_id": row.contract_id,
            "title": row.title,
            "description": row.description,
            "source_branch_id": (
                str(row.source_branch_id) if row.source_branch_id else None
            ),
            "target_branch_id": (
                str(row.target_branch_id) if row.target_branch_id else None
            ),
            "status": row.status,
            "author": row.author,
            "created_at": str(row.created_at) if row.created_at else None,
        }

    def list_proposals(
        self, contract_id: str, status: str | None = None
    ) -> list[dict[str, Any]]:
        """
        List proposals for a contract.

        Args:
            contract_id: Contract identifier
            status: Optional status filter

        Returns:
            List of proposal dicts
        """
        self._require_session()

        from pycharter.db.models.wiki.proposal import ProposalModel

        query = self._session.query(ProposalModel).filter(
            ProposalModel.contract_id == contract_id
        )
        if status:
            query = query.filter(ProposalModel.status == status)
        return [
            {
                "id": str(row.id),
                "contract_id": row.contract_id,
                "title": row.title,
                "status": row.status,
                "author": row.author,
            }
            for row in query.all()
        ]

    def update_status(
        self, proposal_id: str, status: str, updated_by: str | None = None
    ) -> None:
        """
        Update a proposal's status.

        Args:
            proposal_id: UUID of the proposal
            status: New status (open, merged, closed)
            updated_by: Who is updating
        """
        self._require_session()

        from pycharter.db.models.wiki.proposal import ProposalModel

        row = (
            self._session.query(ProposalModel)
            .filter(ProposalModel.id == uuid.UUID(proposal_id))
            .first()
        )
        if row is None:
            raise CollaborationError(f"Proposal {proposal_id} not found")
        row.status = status
        if updated_by:
            row.updated_by = updated_by
        self._session.flush()

    def merge_proposal(self, proposal_id: str, merged_by: str) -> None:
        """
        Merge a proposal (mark as merged).

        Args:
            proposal_id: UUID of the proposal
            merged_by: Who is merging
        """
        self.update_status(proposal_id, "merged", updated_by=merged_by)
