"""Base profile client — shared operations across all Tower Agent profiles.

Handles the agent lifecycle, suggestion retrieval, feedback submission,
score queries, and tick triggering that every profile needs.
Profile-specific clients (Dominion, Grid, Stillpoint) extend this with
domain-specific context ingestion methods.
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional, Sequence

from tower._http import HttpTransport


class BaseProfileClient:
    """Shared agent operations used by every profile client.

    All methods talk to the Tower Agent REST API under /api/agents.
    """

    def __init__(self, transport: HttpTransport, *, profile: str = "") -> None:
        self._t = transport
        self._profile = profile

    @property
    def profile_name(self) -> str:
        return self._profile

    # ── Agent CRUD ────────────────────────────────────────────────────

    def create(
        self,
        *,
        employee_id: str,
        project_id: str,
        role: str = "standard",
        department: str = "",
        config: Dict[str, Any] | None = None,
    ) -> Dict[str, Any]:
        """Mint a new agent for this profile type.

        Returns the created agent dict (agent_id, state, config, etc.).
        """
        payload: Dict[str, Any] = {
            "employee_id": employee_id,
            "project_id": project_id,
            "role": role,
            "department": department,
        }
        if config:
            payload["config"] = config
        if self._profile:
            payload["profile"] = self._profile

        resp = self._t.post("/api/agents", json=payload)
        return resp.json().get("data", resp.json())

    def get(self, agent_id: str) -> Dict[str, Any]:
        """Get agent status, config, and summary."""
        resp = self._t.get(f"/api/agents/{agent_id}")
        return resp.json().get("data", resp.json())

    def update_config(
        self,
        agent_id: str,
        *,
        proactivity_level: float | None = None,
        suggestion_threshold: float | None = None,
        autonomy_level: float | None = None,
        observation_scopes: List[str] | None = None,
        learning_rate: float | None = None,
        context_window_hours: int | None = None,
        max_suggestions_per_hour: int | None = None,
    ) -> Dict[str, Any]:
        """Update agent configuration. Only provided fields are changed."""
        patch: Dict[str, Any] = {}
        if proactivity_level is not None:
            patch["proactivity_level"] = proactivity_level
        if suggestion_threshold is not None:
            patch["suggestion_threshold"] = suggestion_threshold
        if autonomy_level is not None:
            patch["autonomy_level"] = autonomy_level
        if observation_scopes is not None:
            patch["observation_scopes"] = observation_scopes
        if learning_rate is not None:
            patch["learning_rate"] = learning_rate
        if context_window_hours is not None:
            patch["context_window_hours"] = context_window_hours
        if max_suggestions_per_hour is not None:
            patch["max_suggestions_per_hour"] = max_suggestions_per_hour

        resp = self._t.patch(f"/api/agents/{agent_id}", json=patch)
        return resp.json().get("data", resp.json())

    def suspend(self, agent_id: str, *, reason: str = "manual") -> Dict[str, Any]:
        """Suspend an agent (leave, policy hold, etc.)."""
        resp = self._t.post(f"/api/agents/{agent_id}/suspend", params={"reason": reason})
        return resp.json().get("data", resp.json())

    def resume(self, agent_id: str) -> Dict[str, Any]:
        """Resume a suspended agent."""
        resp = self._t.post(f"/api/agents/{agent_id}/resume")
        return resp.json().get("data", resp.json())

    # ── Tick ──────────────────────────────────────────────────────────

    def tick(
        self,
        agent_id: str,
        *,
        context: Dict[str, Any] | None = None,
    ) -> Dict[str, Any]:
        """Trigger an agent tick with optional context.

        Returns suggestions and/or actions from this cycle.
        """
        payload = {"context": context or {}}
        resp = self._t.post(f"/api/agents/{agent_id}/tick", json=payload)
        return resp.json().get("data", resp.json())

    # ── Suggestions ───────────────────────────────────────────────────

    def suggestions(
        self,
        agent_id: str,
        *,
        status: str | None = None,
        suggestion_type: str | None = None,
        limit: int = 20,
        offset: int = 0,
    ) -> List[Dict[str, Any]]:
        """List recent suggestions for an agent."""
        params: Dict[str, Any] = {"limit": limit, "offset": offset}
        if status:
            params["status"] = status
        if suggestion_type:
            params["type"] = suggestion_type

        resp = self._t.get(f"/api/agents/{agent_id}/suggestions", params=params)
        data = resp.json()
        return data.get("data", data) if isinstance(data, dict) else data

    def feedback(
        self,
        agent_id: str,
        suggestion_id: str,
        *,
        feedback_type: str,
        payload: Dict[str, Any] | None = None,
        rating: int | None = None,
        correction_delta: str | None = None,
    ) -> Dict[str, Any]:
        """Submit feedback on a suggestion.

        Args:
            feedback_type: One of accept, reject, correct, rate, ignore.
            payload: Arbitrary context for the feedback event.
            rating: Explicit 1-5 rating (for feedback_type="rate").
            correction_delta: What the employee changed (for "correct").
        """
        body: Dict[str, Any] = {"feedback_type": feedback_type}
        if payload:
            body["payload"] = payload
        if rating is not None:
            body["rating"] = rating
        if correction_delta is not None:
            body["correction_delta"] = correction_delta

        resp = self._t.post(
            f"/api/agents/{agent_id}/suggestions/{suggestion_id}/feedback",
            json=body,
        )
        return resp.json().get("data", resp.json())

    def suggestion_stats(self, agent_id: str) -> Dict[str, Any]:
        """Get suggestion acceptance stats for an agent."""
        resp = self._t.get(f"/api/agents/{agent_id}/suggestions/stats")
        return resp.json().get("data", resp.json())

    # ── Scores ────────────────────────────────────────────────────────

    def scores(self, agent_id: str) -> Dict[str, Any]:
        """Get all scoring dimensions for an agent."""
        resp = self._t.get(f"/api/agents/{agent_id}/scores")
        return resp.json().get("data", resp.json())

    # ── Lifecycle (admin) ─────────────────────────────────────────────

    def onboard(
        self,
        *,
        employee_id: str,
        project_id: str,
        role: str,
        department: str = "",
        profile: str | None = None,
    ) -> Dict[str, Any]:
        """Onboard a new employee — mints agent, binds SnapChore, syncs Lattice."""
        body: Dict[str, Any] = {
            "employee_id": employee_id,
            "project_id": project_id,
            "role": role,
            "department": department,
        }
        if profile or self._profile:
            body["profile"] = profile or self._profile

        resp = self._t.post("/api/lifecycle/onboard", json=body)
        return resp.json().get("data", resp.json())

    def offboard(self, agent_id: str, *, retain_knowledge: bool = True) -> Dict[str, Any]:
        """Offboard an employee — archives agent, revokes consents."""
        resp = self._t.post(
            f"/api/lifecycle/offboard/{agent_id}",
            json={"retain_knowledge": retain_knowledge},
        )
        return resp.json().get("data", resp.json())

    def daily_log(self, agent_id: str) -> Dict[str, Any]:
        """Get the daily activity log for an agent."""
        resp = self._t.get(f"/api/lifecycle/daily-log/{agent_id}")
        return resp.json().get("data", resp.json())

    def review_data(self, agent_id: str) -> Dict[str, Any]:
        """Get the performance review data package."""
        resp = self._t.get(f"/api/lifecycle/review-data/{agent_id}")
        return resp.json().get("data", resp.json())
