"""Reflection API endpoints.

Agent reflections are auto-generated (daily/weekly synthesis).
User reflections are user-written personal reflections.
"""

from __future__ import annotations

from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel

router = APIRouter(prefix="/reflections", tags=["reflections"])


class UserReflectionRequest(BaseModel):
    text: str
    date: str | None = None


@router.get("")
async def list_reflections(request: Request, limit: int = 20) -> list[dict]:
    """List recent reflections (both user and agent)."""
    reflection_svc = request.app.state.reflection_service
    return reflection_svc.list_reflections(limit=limit)


@router.post("/daily")
async def run_daily_reflection(request: Request, date: str | None = None) -> dict:
    """Run agent daily reflection for a given date (defaults to today)."""
    reflection_svc = request.app.state.reflection_service
    return await reflection_svc.run_daily_reflection(date)


@router.post("/weekly")
async def run_weekly_reflection(request: Request, week_end: str | None = None) -> dict:
    """Run agent weekly reflection (defaults to current week)."""
    reflection_svc = request.app.state.reflection_service
    return await reflection_svc.run_weekly_reflection(week_end)


@router.post("/batch-approve")
async def batch_approve_reflections(request: Request) -> dict:
    """Batch approve pending reflections.

    Body: ``{"paths": ["journal/agnt/daily-reflection_2026-04-15.md"]}``
    If ``paths`` is empty or omitted, approves ALL pending reflections.
    """
    try:
        body = await request.json()
    except Exception:
        body = {}
    paths = body.get("paths", []) if isinstance(body, dict) else []

    reflection_svc = request.app.state.reflection_service
    all_reflections = reflection_svc.list_reflections(limit=200)
    pending = [r for r in all_reflections if r.get("status") == "pending"]

    if paths:
        pending = [r for r in pending if r.get("path") in paths]

    approved = 0
    skipped = 0
    errors: list[str] = []
    approved_paths: list[str] = []

    for item in pending:
        path = item.get("path", "")
        try:
            await reflection_svc.approve_reflection(path)
            approved += 1
            approved_paths.append(path)
        except FileNotFoundError:
            skipped += 1
        except Exception as exc:
            errors.append(f"{path}: {exc}")

    # Record ONE batch feedback event
    activity = getattr(request.app.state, "activity_logger", None)
    if activity and approved:
        activity.record_feedback("approval", f"Batch approved {approved} reflections")

    # Record in review history
    review_history = getattr(request.app.state, "review_history", None)
    if review_history and approved:
        await review_history.record(
            "reflection", ",".join(approved_paths), "batch_approved",
            details={"approved": approved, "skipped": skipped},
        )

    return {"approved": approved, "skipped": skipped, "errors": errors}


@router.post("/{path:path}/approve")
async def approve_reflection(request: Request, path: str) -> dict:
    """Approve an agent reflection and apply MEMORY.md updates.

    Accepts an optional JSON body with ``content`` to rewrite the
    reflection body before approving (edit-then-approve).
    """
    try:
        body = await request.json()
    except Exception:
        body = {}
    edited = body.get("content") if isinstance(body, dict) else None

    # Capture correlation_id BEFORE approve mutates the frontmatter.
    reader = request.app.state.vault
    _reflection_corr_id = ""
    try:
        if reader.exists(path):
            _ref_doc = reader.read(path)
            _reflection_corr_id = str((_ref_doc.metadata or {}).get("correlation_id", ""))
    except Exception:
        pass

    if edited is not None:
        writer = request.app.state.vault_writer
        if not reader.exists(path):
            raise HTTPException(status_code=404, detail=f"Reflection not found: {path}")
        doc = reader.read(path)
        import frontmatter
        post = frontmatter.Post(edited, handler=None, **(doc.metadata or {}))
        writer.write(path, frontmatter.dumps(post), trust_reason="reflection_edited_before_approve")

    reflection_svc = request.app.state.reflection_service
    try:
        await reflection_svc.approve_reflection(path)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc

    # Record feedback for relationship learning
    activity = getattr(request.app.state, "activity_logger", None)
    if activity:
        activity.record_feedback("approval", f"Reflection: {path}")

    review_history = getattr(request.app.state, "review_history", None)
    if review_history:
        await review_history.record("reflection", path, "approved")

    # Evolution feedback — positive signal on the reflection run's outcome.
    evolution = getattr(request.app.state, "evolution", None)
    if evolution is not None and _reflection_corr_id:
        await evolution.record_feedback_by_correlation(_reflection_corr_id, 1.0)

    return {"status": "approved", "path": path}


@router.post("/{path:path}/reject")
async def reject_reflection(request: Request, path: str) -> dict:
    """Reject a reflection — marks it as rejected with optional reason."""
    reader = request.app.state.vault
    writer = request.app.state.vault_writer

    if not reader.exists(path):
        raise HTTPException(status_code=404, detail=f"Reflection not found: {path}")

    try:
        body = await request.json()
    except Exception:
        body = {}
    reason = body.get("reason", "") if isinstance(body, dict) else ""

    doc = reader.read(path)
    content = doc.raw
    # Update status to rejected
    for old in ("status: pending", "status: approved"):
        content = content.replace(old, "status: rejected")
    if reason:
        content = content.replace("---\n", f"---\nrejection_reason: {reason}\n", 1)
    writer.write(path, content, trust_reason="reflection_rejected")

    activity = getattr(request.app.state, "activity_logger", None)
    if activity:
        activity.record_feedback("rejection", f"Reflection: {path}" + (f" — {reason}" if reason else ""))

    review_history = getattr(request.app.state, "review_history", None)
    if review_history:
        await review_history.record("reflection", path, "rejected", reason=reason)

    # Evolution feedback — rejection signal (score 0.0).
    evolution = getattr(request.app.state, "evolution", None)
    reflection_corr_id = str((doc.metadata or {}).get("correlation_id", ""))
    if evolution is not None and reflection_corr_id:
        await evolution.record_feedback_by_correlation(reflection_corr_id, 0.0)

    return {"status": "rejected", "path": path}


@router.post("/{path:path}/unapprove")
async def unapprove_reflection(request: Request, path: str) -> dict:
    """Revert an approved reflection back to pending status."""
    reader = request.app.state.vault
    writer = request.app.state.vault_writer

    if not reader.exists(path):
        raise HTTPException(status_code=404, detail=f"Reflection not found: {path}")

    doc = reader.read(path)
    content = doc.raw.replace("status: approved", "status: pending")
    writer.write(path, content, trust_reason="reflection_unapproved")

    activity = getattr(request.app.state, "activity_logger", None)
    if activity:
        activity.log("memory", "unapproved", f"Reflection reverted to pending: {path}",
                     importance="medium")

    review_history = getattr(request.app.state, "review_history", None)
    if review_history:
        await review_history.record("reflection", path, "unapproved")

    return {"status": "unapproved", "path": path}


@router.post("/user")
async def write_user_reflection(request: Request, body: UserReflectionRequest) -> dict:
    """Write a personal reflection to today's journal Reflections section.

    User reflections now live in the journal, not as separate files.
    """
    journal = request.app.state.journal
    journal.append_reflection(body.text)
    return {"status": "ok", "section": "Reflections", "author": "user"}
