"""Cleave library integration for P.I.G. Farm.

Provides direct access to cleave algorithms without SDK round-trips:
- Offline complexity assessment
- Workspace file watching
- Post-execution reunification
- Permission pre-checking
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from cleave import (
    AssessmentResult,
    assess_directive,
    check_missing_permissions,
    detect_conflicts,
    infer_permissions,
    match_pattern,
    reunify_workspace,
)

if TYPE_CHECKING:
    from cleave import Conflict


def assess_offline(directive: str, threshold: float = 2.0) -> dict:
    """Assess directive complexity without API calls.

    This is a quick pre-screening before expensive SDK invocation.

    Args:
        directive: The directive text to assess.
        threshold: Complexity threshold for cleave decision.

    Returns:
        dict with:
        - complexity: float score
        - decision: "execute" | "cleave" | "needs_assessment"
        - pattern: matched pattern name or None
        - confidence: pattern match confidence
        - tier: 0 (skip), 1 (execute), or 2 (cleave)
    """
    result = assess_directive(directive, threshold)

    return {
        "complexity": result.complexity,
        "systems": result.systems,
        "modifiers": result.modifiers,
        "decision": result.decision,
        "pattern": result.pattern,
        "confidence": result.confidence,
        "method": result.method,
        "reasoning": result.reasoning,
        "skip_interrogation": result.skip_interrogation,
        "tier": 0 if result.skip_interrogation else (1 if result.decision == "execute" else 2),
    }


def check_permissions_for_directive(directive: str) -> dict:
    """Check if required permissions are configured for fire-and-forget execution.

    Args:
        directive: The directive to check.

    Returns:
        dict with:
        - all_covered: bool - True if all permissions are configured
        - missing: list of missing permission strings
        - covered: list of covered permission strings
        - bundles: list of matched permission bundle names
    """
    match = match_pattern(directive)
    pattern_id = match.pattern_id if match else None

    inferred = infer_permissions(directive, pattern_id)
    check_result = check_missing_permissions(inferred)

    return {
        "all_covered": check_result["all_covered"],
        "missing": check_result["missing"],
        "covered": check_result["covered"],
        "missing_count": check_result["missing_count"],
        "bundles": inferred["bundles"],
        "descriptions": inferred["descriptions"],
    }


def reunify_cleave_workspace(workspace_path: str | Path) -> dict:
    """Reunify all child tasks after SDK execution completes.

    Generates merge.md (conflicts) and review.md (adversarial validation).

    Args:
        workspace_path: Path to the .cleave directory.

    Returns:
        dict with reunification results including:
        - rollup_status: SUCCESS/PARTIAL/FAILED/PENDING
        - conflicts_found: int
        - conflicts: list of conflict details
        - verification: coverage summary
        - ready_to_close: bool
    """
    return reunify_workspace(str(workspace_path))


def watch_workspace_status(workspace_path: str | Path) -> dict:
    """Get current status of a cleave workspace.

    Useful for polling workspace progress during execution.

    Args:
        workspace_path: Path to the .cleave directory.

    Returns:
        dict with:
        - exists: bool
        - task_count: number of task files
        - status_breakdown: dict of status -> count
        - has_merge: bool - merge.md exists
        - has_review: bool - review.md exists
    """
    workspace = Path(workspace_path)

    if not workspace.exists():
        return {"exists": False}

    # Count task files
    task_files = list(workspace.glob("[0-9]*-task.md"))

    # Check for status markers in task files
    status_breakdown = {"PENDING": 0, "SUCCESS": 0, "PARTIAL": 0, "FAILED": 0}
    for task_file in task_files:
        content = task_file.read_text()
        if "**Status:** SUCCESS" in content:
            status_breakdown["SUCCESS"] += 1
        elif "**Status:** PARTIAL" in content:
            status_breakdown["PARTIAL"] += 1
        elif "**Status:** FAILED" in content:
            status_breakdown["FAILED"] += 1
        else:
            status_breakdown["PENDING"] += 1

    return {
        "exists": True,
        "task_count": len(task_files),
        "status_breakdown": status_breakdown,
        "completed": status_breakdown["SUCCESS"] + status_breakdown["PARTIAL"] + status_breakdown["FAILED"],
        "pending": status_breakdown["PENDING"],
        "has_merge": (workspace / "merge.md").exists(),
        "has_review": (workspace / "review.md").exists(),
        "has_manifest": (workspace / "manifest.yaml").exists(),
    }


def get_suggested_children(directive: str) -> list[str]:
    """Get suggested child task labels based on matched pattern.

    WARNING: This function uses internal API (cleave.core.assessment.PATTERNS)
    which is not exported in the public API. This is fragile and could break
    if the package structure changes. Consider one of:
    - Request this functionality be added to public API
    - Use alternative implementation
    - Accept technical debt and monitor for breaking changes

    Args:
        directive: The directive text.

    Returns:
        list of suggested child task labels, or empty list if no pattern matched.
    """
    # FRAGILE: Accessing internal API that could break without warning
    from cleave.core.assessment import PATTERNS

    match = match_pattern(directive)
    if match:
        return PATTERNS[match.pattern_id].get("split_strategy", [])
    return []
