#!/usr/bin/env python3
"""ASUCB Repush Transform — safe bulk cosmetic re-push of live Canvas pages.

MUST-2 guardrail: transform the LIVE Canvas body, never re-push a stale local
source. Whole-body diff verification is unreliable on Canvas (it strips markers
and re-encodes entities), so only field-targeted (substring / count) verification
is meaningful. Use this script for deterministic bulk transforms.

Usage
-----
  python scripts/repush_transform.py \\
      --course-id 123456 \\
      --type page \\
      --slugs m1-overview,m1-lesson \\
      --transform dedash \\
      [--confirm-verb push] \\
      [--dry-run]

Options
-------
  --course-id       Canvas course ID.
  --type            Object type. Currently only "page" is supported.
  --slugs           Comma-separated list of page slugs to transform.
  --transform       Transform to apply. Choices: dedash.
  --confirm-verb    Explicit confirmation verb (push/approved/deploy/ship).
                    Required unless --dry-run.
  --dry-run         Report per-slug change counts without staging/pushing.

Exit codes
----------
  0   All slugs processed (or dry-run complete).
  1   Error (Canvas API failure, missing confirm-verb, etc.).
"""

import argparse
import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

_VALID_CONFIRM_VERBS = {"push", "approved", "deploy", "ship it", "ship", "looks good push"}

# ── Transform registry ─────────────────────────────────────────────────────

def _transform_dedash(html: str):
    """Apply fix_dashes to the given HTML. Returns (new_html, n_changes)."""
    from content_remediation import fix_dashes
    return fix_dashes(html)


_TRANSFORMS = {
    "dedash": _transform_dedash,
}


# ── Main logic ─────────────────────────────────────────────────────────────

def run(course_id: str, object_type: str, slugs: list, transform_name: str,
        confirm_verb: str = None, dry_run: bool = False) -> int:
    """Execute the transform on each slug.

    Returns exit code (0 = success, 1 = error).
    """
    if object_type != "page":
        print(f"repush_transform: only --type page is currently supported "
              f"(got '{object_type}')", file=sys.stderr)
        return 1

    if transform_name not in _TRANSFORMS:
        print(f"repush_transform: unknown transform '{transform_name}'. "
              f"Choose from: {', '.join(_TRANSFORMS)}", file=sys.stderr)
        return 1

    if not dry_run:
        if not confirm_verb or confirm_verb.lower() not in _VALID_CONFIRM_VERBS:
            print(
                "repush_transform: --confirm-verb required unless --dry-run.\n"
                f"  Accepted verbs: {', '.join(sorted(_VALID_CONFIRM_VERBS))}\n"
                "  (Do NOT use 'ok', 'yes', 'sure', 'confirm' alone.)",
                file=sys.stderr,
            )
            return 1

    transform_fn = _TRANSFORMS[transform_name]

    import canvas_api
    import staging_manager

    config = canvas_api.get_config(course_id=course_id)

    changed = []
    skipped = []
    errors = []

    for slug in slugs:
        slug = slug.strip()
        if not slug:
            continue

        # Fetch LIVE body (not stale staging).
        page = canvas_api.get_page(config, slug)
        if page is None:
            print(f"  ERROR: could not fetch page '{slug}'", file=sys.stderr)
            errors.append(slug)
            continue

        live_body = page.get("body") or ""
        new_body, n = transform_fn(live_body)

        if n == 0:
            print(f"  SKIP  {slug}: no changes ({transform_name})")
            skipped.append(slug)
            continue

        print(f"  {'DRY-RUN' if dry_run else 'STAGE '} {slug}: {n} change(s)")
        if dry_run:
            changed.append(slug)
            continue

        # Stage the transformed body.
        stage_result = staging_manager.stage(course_id, "pages", slug, new_body)
        if not stage_result.get("ok"):
            print(f"  ERROR staging {slug}: {stage_result.get('error')}", file=sys.stderr)
            errors.append(slug)
            continue

        # Push via push_to_canvas (backup -> push -> verify -> clear staging).
        import push_to_canvas
        result = push_to_canvas.push_page(config, slug, course_id)
        if result.get("ok"):
            print(f"  PUSHED {slug} -> {result.get('canvas_url', '')}")
            changed.append(slug)
        else:
            print(f"  ERROR pushing {slug}: {result.get('error')}", file=sys.stderr)
            errors.append(slug)

    # Summary.
    print(
        f"\nrepush_transform summary: "
        f"{len(changed)} changed, {len(skipped)} skipped, {len(errors)} error(s)"
        + (" [DRY-RUN]" if dry_run else "")
    )
    return 1 if errors else 0


def main():
    parser = argparse.ArgumentParser(
        prog="repush_transform",
        description="Safe bulk cosmetic re-push: transform LIVE Canvas body then push.",
    )
    parser.add_argument("--course-id", required=True, help="Canvas course ID.")
    parser.add_argument(
        "--type",
        dest="object_type",
        default="page",
        choices=["page"],
        help="Object type (default: page).",
    )
    parser.add_argument(
        "--slugs",
        required=True,
        help="Comma-separated page slugs.",
    )
    parser.add_argument(
        "--transform",
        required=True,
        choices=list(_TRANSFORMS.keys()),
        help="Transform to apply.",
    )
    parser.add_argument(
        "--confirm-verb",
        default=None,
        help="Explicit push verb. Required unless --dry-run.",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Report changes without staging or pushing.",
    )
    args = parser.parse_args()

    slugs = [s.strip() for s in args.slugs.split(",") if s.strip()]
    if not slugs:
        parser.error("--slugs must be a non-empty comma-separated list.")

    sys.exit(
        run(
            course_id=args.course_id,
            object_type=args.object_type,
            slugs=slugs,
            transform_name=args.transform,
            confirm_verb=args.confirm_verb,
            dry_run=args.dry_run,
        )
    )


if __name__ == "__main__":
    main()
