"""Queue an approved WordPress mutation plan for WP AI Assist pickup (PULL model).

Flow:
  1. Load the approved AssistantActionSession.
  2. Create WpMutationAction rows (one per operation, all status=pending).
  3. Advance the session to 'executing' so it won't be re-queued.
  4. Return immediately — the companion polls Core for pending operations via
     POST /v1/wp-ai/companion/mutations/poll, executes them locally, and
     reports results via POST /v1/wp-ai/companion/mutations/report.
"""
from __future__ import annotations

from uuid import UUID

import structlog

from src.core.database import async_session_factory
from src.domain.external_admin.models import (
    ACTION_SESSION_STATUS_EXECUTING,
    WP_MUTATION_ACTION_STATUS_PENDING,
    WpMutationAction,
)
from src.domain.external_admin.repository import (
    AssistantActionSessionRepository,
    ExternalAdminInstallationRepository,
    WpMutationActionRepository,
)

logger = structlog.get_logger()


async def execute_wp_mutation_plan(ctx: dict, session_id: str) -> dict:
    """Create WpMutationAction rows and hand off to the WP plugin PULL model.

    The AI Assist WP plugin picks up operations on its next poll cycle and reports
    results back through the gateway. Core advances the session to 'applied'
    or 'failed' as reports arrive.
    """
    db_factory = ctx.get("db_factory", async_session_factory)
    try:
        action_session_id = UUID(session_id)
    except ValueError:
        logger.warning("execute_wp_mutation_invalid_session_id", session_id=session_id)
        return {"status": "invalid_session_id"}

    async with db_factory() as db:
        session_repo = AssistantActionSessionRepository(db)
        session = await session_repo.get(action_session_id)
        if not session:
            logger.warning("execute_wp_mutation_session_not_found", session_id=session_id)
            return {"status": "not_found"}
        if session.status != "approved":
            return {"status": f"not_runnable: {session.status}"}

        installation = await ExternalAdminInstallationRepository(db).get_by_id(
            session.installation_id
        )
        if not installation:
            logger.warning("execute_wp_mutation_no_installation", session_id=session_id)
            return {"status": "installation_not_found"}

        plan = session.payload or {}
        operations = plan.get("operations") if isinstance(plan.get("operations"), list) else []

        mutation_repo = WpMutationActionRepository(db)
        for i, op in enumerate(operations):
            row = WpMutationAction(
                action_session_id=session.id,
                installation_id=session.installation_id,
                project_id=session.project_id,
                sequence_number=i,
                action=str(op.get("action") or ""),
                description=str(op.get("description") or ""),
                payload=op.get("payload") or {},
                status=WP_MUTATION_ACTION_STATUS_PENDING,
            )
            await mutation_repo.create(row)

        session.status = ACTION_SESSION_STATUS_EXECUTING
        await session_repo.save(session)
        await db.commit()

    logger.info(
        "execute_wp_mutation_queued",
        session_id=session_id,
        operation_count=len(operations),
    )
    return {"status": "queued_for_wp_apply", "operations": len(operations)}
