#!/usr/bin/env python3
import json
from pathlib import Path
from datetime import datetime, timezone

ROOT = Path("/home/yeff/public_html/devon")
CANON_EXEC = ROOT / "canon" / "execution"
MASTER = CANON_EXEC / "master_execution_contract.json"
VALIDATION_REPORT = CANON_EXEC / "state" / "execution_contract_validation_report.json"
PLAN = CANON_EXEC / "state" / "contract_expansion_plan.json"

FORBIDDEN_ABSOLUTE_PATHS = [
    str(ROOT / "panel"),
    str(ROOT / "panel" / "data"),
]

def utc_now():
    return datetime.now(timezone.utc).isoformat()

def read_json(path):
    return json.loads(path.read_text(encoding="utf-8"))

def category_score(phase, category):
    phase_id = phase.get("phase_id", "")
    category_id = category.get("category_id", "")

    if category_id == "panel_canonical_tree":
        return 999999

    status_weight = {
        "MISSING": 0,
        "DRAFT": 10,
        "FAIL": 20,
        "ACTIVE": 9999
    }.get(category.get("category_contract_status", "MISSING"), 0)

    phase_order = phase.get("phase_order", 9999)

    return (status_weight * 10000) + (phase_order * 100) + len(category_id)

def main():
    master = read_json(MASTER)
    validation = read_json(VALIDATION_REPORT)

    serialized_master = MASTER.read_text(encoding="utf-8")
    forbidden_found = [p for p in FORBIDDEN_ABSOLUTE_PATHS if p in serialized_master]

    phases = master.get("phases", [])
    candidates = []
    active_categories = []
    blocked_categories = []

    for phase in phases:
        for category in phase.get("categories", []):
            category_id = category.get("category_id", "")
            status = category.get("category_contract_status", "MISSING")
            source_path = category.get("source", {}).get("source_path", "")
            contract_path = category.get("category_contract_path", "")

            row = {
                "phase_id": phase.get("phase_id", ""),
                "phase_title": phase.get("phase_title", ""),
                "phase_order": phase.get("phase_order", 9999),
                "category_id": category_id,
                "category_title": category.get("category_title", ""),
                "category_contract_status": status,
                "source_path": source_path,
                "category_contract_path": contract_path,
                "execution_items_status": category.get("execution_items_status", "MISSING"),
                "monitoring_items_status": category.get("monitoring_items_status", "MISSING"),
                "progress_rules_status": category.get("progress_rules_status", "MISSING"),
                "scan_contract_status": category.get("scan_contract_status", "MISSING"),
                "refresh_contract_status": category.get("refresh_contract_status", "MISSING"),
                "blocks_phase_progress": category.get("blocks_phase_progress", True),
                "next_contract_action": category.get("next_contract_action", ""),
                "score": category_score(phase, category)
            }

            if status == "ACTIVE":
                active_categories.append(row)
            elif status in ("MISSING", "DRAFT", "FAIL"):
                candidates.append(row)
            else:
                blocked_categories.append(row)

    candidates = sorted(candidates, key=lambda x: (x["score"], x["phase_order"], x["category_id"]))

    next_category = candidates[0] if candidates else None

    blocking_reasons = []

    if validation.get("final_status") != "PASS":
        blocking_reasons.append("foundation_validator_not_pass")

    if forbidden_found:
        blocking_reasons.append("forbidden_absolute_path_in_master")

    total_category_count = sum(len(p.get("categories", [])) for p in phases)
    expansion_complete = len(candidates) == 0 and len(active_categories) == total_category_count and total_category_count > 0

    if not next_category and not expansion_complete:
        blocking_reasons.append("no_candidate_category_found")

    final_status = "PASS" if not blocking_reasons else "FAIL"
    expansion_status = "COMPLETE" if expansion_complete else ("READY" if final_status == "PASS" else "BLOCKED")

    plan = {
        "plan_id": "contract_expansion_plan",
        "version": "v1",
        "generated_at": utc_now(),
        "planner": "contract_expansion_planner.py",
        "final_status": final_status,
        "expansion_status": expansion_status,
        "blocking_reasons": blocking_reasons,
        "source": {
            "master_execution_contract": str(MASTER),
            "validation_report": str(VALIDATION_REPORT),
            "phase_count": len(phases),
            "category_count": sum(len(p.get("categories", [])) for p in phases),
            "active_category_count": len(active_categories),
            "candidate_category_count": len(candidates)
        },
        "selection_policy": {
            "rule": "Select the first non-ACTIVE category from the DH-driven master contract, ordered by phase_order and contract status.",
            "manual_choice_forbidden": True,
            "layout_choice_forbidden": True,
            "legacy_panel_directory_forbidden": True
        },
        "next_category": next_category,
        "candidate_preview": candidates[:20],
        "active_categories": active_categories,
        "blocked_categories": blocked_categories,
        "next_required_action": "contract_expansion_complete" if expansion_complete else ("create_category_execution_contract_from_plan" if final_status == "PASS" else "fix_contract_expansion_planner_blockers")
    }

    PLAN.write_text(json.dumps(plan, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")

    print("CONTRACT_EXPANSION_PLANNER_STATUS=PASS")
    print("PLAN=", PLAN)
    print("FINAL_STATUS=", final_status)
    print("PHASE_COUNT=", plan["source"]["phase_count"])
    print("CATEGORY_COUNT=", plan["source"]["category_count"])
    print("ACTIVE_CATEGORY_COUNT=", plan["source"]["active_category_count"])
    print("CANDIDATE_CATEGORY_COUNT=", plan["source"]["candidate_category_count"])

    if next_category:
        print("NEXT_PHASE_ID=", next_category.get("phase_id"))
        print("NEXT_CATEGORY_ID=", next_category.get("category_id"))
        print("NEXT_CATEGORY_TITLE=", next_category.get("category_title"))
        print("NEXT_CATEGORY_STATUS=", next_category.get("category_contract_status"))
        print("NEXT_SOURCE_PATH=", next_category.get("source_path"))
        print("NEXT_CONTRACT_PATH=", next_category.get("category_contract_path"))

    print("BLOCKING_REASONS=", ",".join(blocking_reasons))
    print("NEXT_REQUIRED_ACTION=", plan["next_required_action"])

if __name__ == "__main__":
    main()
