"""taskctl_start — lock 파일 갱신 helper.

worktree_manager.cmd_create() 등 워크트리 생성 진입점에서 호출하여
.tasks/locks/<task_id>.lock 파일에 lock_sha 필드를 additive하게 기록한다.

task-2575: lock_sha schema fix
"""
from __future__ import annotations

import json
import logging
import subprocess
from pathlib import Path
from typing import Optional

logger = logging.getLogger(__name__)


def record_lock_sha(
    workspace_root: str | Path,
    task_id: str,
    lock_sha: str,
) -> dict:
    """`.tasks/locks/<task_id>.lock` 파일에 lock_sha 필드를 additive로 기록.

    파일이 이미 존재하면 기존 키를 보존하면서 lock_sha만 갱신/추가.
    파일이 없으면 minimal lock 파일을 생성 (lock_sha + task_id만).

    Args:
        workspace_root: workspace 루트 디렉토리 경로.
        task_id: 태스크 ID (예: "task-2575").
        lock_sha: 기록할 SHA40 문자열.

    Returns:
        {"status": "updated"|"created"|"skipped", "lock_path": str, "lock_sha": str}
    """
    workspace = Path(workspace_root)
    locks_dir = workspace / ".tasks" / "locks"
    lock_path = locks_dir / f"{task_id}.lock"

    # SHA40 검증 (defensive)
    if not (isinstance(lock_sha, str) and len(lock_sha) == 40 and all(c in "0123456789abcdef" for c in lock_sha)):
        return {"status": "skipped", "lock_path": str(lock_path), "lock_sha": "", "reason": "invalid_sha"}

    locks_dir.mkdir(parents=True, exist_ok=True)

    existing: dict = {}
    status = "created"
    if lock_path.exists():
        try:
            parsed = json.loads(lock_path.read_text(encoding="utf-8"))
            if isinstance(parsed, dict):
                existing = parsed
            status = "updated"
        except (json.JSONDecodeError, OSError) as exc:
            logger.warning("lock 파일 파싱 실패 — 새로 생성: %s", exc)
            existing = {}
            status = "created"

    # additive: 기존 키 보존 + lock_sha 추가/갱신. task_id가 없으면 채움.
    existing.setdefault("task_id", task_id)
    existing["lock_sha"] = lock_sha

    # atomic write: tmp 파일 → rename
    tmp_path = lock_path.with_suffix(lock_path.suffix + ".tmp")
    tmp_path.write_text(json.dumps(existing, indent=2, ensure_ascii=False), encoding="utf-8")
    tmp_path.replace(lock_path)

    return {"status": status, "lock_path": str(lock_path), "lock_sha": lock_sha}


def resolve_lock_sha(worktree_path: str | Path) -> Optional[str]:
    """worktree 디렉토리에서 `git rev-parse HEAD`로 lock_sha 추출.

    Args:
        worktree_path: worktree 디렉토리 경로.

    Returns:
        SHA40 문자열 또는 None (실패 시).
    """
    try:
        result = subprocess.run(
            ["git", "rev-parse", "HEAD"],
            cwd=str(worktree_path),
            check=True,
            capture_output=True,
            text=True,
            timeout=10,
        )
        sha = result.stdout.strip()
        if len(sha) == 40 and all(c in "0123456789abcdef" for c in sha):
            return sha
    except (subprocess.CalledProcessError, subprocess.TimeoutExpired, OSError) as exc:
        logger.warning("lock_sha 추출 실패: %s", exc)
    return None


def _cli() -> int:
    """CLI 진입점: `python3 taskctl_start.py record <workspace_root> <task_id> <worktree_path>`

    Returns:
        exit code (0 성공, 1 실패).
    """
    import argparse

    parser = argparse.ArgumentParser(prog="taskctl_start.py")
    sub = parser.add_subparsers(dest="command", required=True)

    p_record = sub.add_parser("record", help="lock_sha 기록")
    p_record.add_argument("workspace_root", help="workspace 루트 경로")
    p_record.add_argument("task_id", help="태스크 ID")
    p_record.add_argument("worktree_path", help="worktree 경로 (HEAD SHA 추출 대상)")

    args = parser.parse_args()

    if args.command == "record":
        sha = resolve_lock_sha(args.worktree_path)
        if not sha:
            print(json.dumps({"status": "error", "message": "lock_sha 추출 실패"}, ensure_ascii=False))
            return 1
        result = record_lock_sha(args.workspace_root, args.task_id, sha)
        print(json.dumps(result, ensure_ascii=False, indent=2))
        return 0

    return 1


if __name__ == "__main__":
    import sys
    sys.exit(_cli())
