#!/usr/bin/env python3
import json
import shutil
import subprocess
import sys
from datetime import datetime, timezone, timedelta
from pathlib import Path

ARTIFACTS_FILENAME = '__MY_ARTIFACTS__.json'
IMAGE_EXTS = {'.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico'}
# 最后注册的排 UI 最前，顺序：其他 → 图片 → student-view → index
ARTIFACTS_TAIL_ORDER = ['__student-view__.html', 'index.html']


def _now_iso():
    tz = timezone(timedelta(hours=8))
    return datetime.now(tz).isoformat()


def _get_file_type(path: str) -> str:
    ext = Path(path).suffix.lower()
    return {'.html': 'html', '.htm': 'html', '.json': 'json', '.js': 'js',
            '.css': 'css', '.png': 'image', '.jpg': 'image', '.jpeg': 'image',
            '.gif': 'image', '.svg': 'image', '.mp3': 'audio', '.mp4': 'video'}.get(ext, 'file')


def _gen_id():
    import random, string
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))


def _register_file(artifacts_path: Path, workspace_id: str, rel_path: str):
    """向 __MY_ARTIFACTS__.json 注册/更新一个文件，更新 updated_at"""
    now = _now_iso()
    if artifacts_path.exists():
        try:
            data = json.loads(artifacts_path.read_text(encoding='utf-8'))
        except Exception:
            data = None
    else:
        data = None

    if data is None:
        data = {
            'workspace_id': workspace_id,
            'title': '我的资源库',
            'release_version': 1,
            'created_at': now,
            'updated_at': now,
            'version': 1,
            'base_url': '',
            'preview_path': 'index.html',
            'assets': [],
        }

    found = False
    for asset in data.get('assets', []):
        if asset.get('path') == rel_path:
            asset.setdefault('created_at', now)
            asset['updated_at'] = now
            asset['type'] = _get_file_type(rel_path)
            found = True
            break

    if not found:
        data['assets'].append({
            'id': _gen_id(),
            'type': _get_file_type(rel_path),
            'path': rel_path,
            'created_at': now,
            'updated_at': now,
        })

    data['updated_at'] = now
    artifacts_path.parent.mkdir(parents=True, exist_ok=True)
    artifacts_path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')


def register_instance_files(workspace: Path, target_dir: Path):
    """B 阶段结束后，按顺序注册所有文件到 __MY_ARTIFACTS__.json。
    注册顺序（后注册 = updated_at 最新 = UI 排前）：
      其他资源 → 图片资源 → __student-view__.html → index.html
    """
    workspace_id = workspace.name
    artifacts_path = workspace / '.myclaw' / ARTIFACTS_FILENAME

    all_files = sorted(f for f in target_dir.rglob('*') if f.is_file())
    rel_paths = [f.as_posix().replace(workspace.as_posix() + '/', '') for f in all_files]

    def is_tail(p):
        return any(p.endswith('/' + name) or p == name for name in ARTIFACTS_TAIL_ORDER)

    def is_image(p):
        return Path(p).suffix.lower() in IMAGE_EXTS

    others = [p for p in rel_paths if not is_tail(p) and not is_image(p)]
    images = [p for p in rel_paths if is_image(p)]
    tail = [p for name in ARTIFACTS_TAIL_ORDER
            for p in rel_paths if p.endswith('/' + name) or p == name]

    for rel in others + images + tail:
        _register_file(artifacts_path, workspace_id, rel)

PROMPT_TEMPLATE_PATH = Path(__file__).resolve().parent.parent / 'prompts' / 'remix-handoff.txt'


def fail(payload, code=1):
    print(json.dumps(payload, ensure_ascii=False))
    raise SystemExit(code)


def parse_args(argv):
    if len(argv) < 2:
        fail({'ok': False, 'error': 'usage', 'message': '用法: python3 scripts/deploy_to_workspace.py <template_path> <workspace_path> [--with-tui]'})

    source_dir = Path(argv[0])
    workspace = Path(argv[1])
    do_tui = False

    extra = argv[2:]
    if extra:
        if extra == ['--with-tui']:
            do_tui = True
        else:
            fail({'ok': False, 'error': 'unknown_argument', 'message': f'未知参数: {extra}'})

    ws_name = workspace.name
    agent = ws_name[len('workspace-'):] if ws_name.startswith('workspace-') else ''
    return source_dir, workspace, agent, do_tui


def run(cmd):
    return subprocess.run(cmd, capture_output=True, text=True)


def choose_entry_file(target_dir: Path):
    for preferred in ['index.html', '__demo__.html', '__student-view__.html']:
        candidate = target_dir / preferred
        if candidate.exists():
            return candidate
    html_files = sorted(list(target_dir.rglob('*.html')) + list(target_dir.rglob('*.htm')))
    return html_files[0] if html_files else None


def build_instance_name(source_dir: Path, remix_dir: Path):
    import re
    folder_name = source_dir.parent.name if re.match(r'^v\d+$', source_dir.name) else source_dir.name
    # 去掉 a104_ 这样的系列编号前缀，只保留业务名
    name = re.sub(r'^[a-z]+\d+_', '', folder_name) or folder_name
    base = f"{name}_{datetime.now().strftime('%H%M')}"
    candidate = base
    suffix = 2
    while (remix_dir / candidate).exists():
        candidate = f"{base}_{suffix}"
        suffix += 1
    return candidate


def build_message(folder_rel_path: str, entry_rel_path: str):
    if not PROMPT_TEMPLATE_PATH.exists():
        fail({'ok': False, 'error': 'prompt_template_not_found', 'path': str(PROMPT_TEMPLATE_PATH)})
    prompt_template = PROMPT_TEMPLATE_PATH.read_text(encoding='utf-8')
    return prompt_template.replace('{{FOLDER_REL_PATH}}', folder_rel_path).replace('{{ENTRY_REL_PATH}}', entry_rel_path)


def main():
    source_dir, workspace, agent, do_tui = parse_args(sys.argv[1:])
    if not source_dir.exists() or not source_dir.is_dir():
        fail({'ok': False, 'error': 'source_dir_not_found', 'source_dir': str(source_dir)})

    workspace.mkdir(parents=True, exist_ok=True)
    remix_dir = workspace / 'remix'
    remix_dir.mkdir(parents=True, exist_ok=True)

    instance_name = build_instance_name(source_dir, remix_dir)
    target_dir = remix_dir / instance_name
    shutil.copytree(source_dir, target_dir)

    register_instance_files(workspace, target_dir)

    entry_file = choose_entry_file(target_dir)
    if not entry_file:
        fail({'ok': False, 'error': 'entry_html_not_found', 'target_dir': str(target_dir)})

    folder_rel_path = f'remix/{instance_name}'
    entry_rel_path = entry_file.as_posix().replace(workspace.as_posix() + '/', '')

    message = ''
    tui_started = False
    if do_tui:
        if not agent:
            fail({'ok': False, 'error': 'workspace_agent_not_inferable', 'message': 'workspace 路径必须形如 workspace-xxx，才能启用 --with-tui'})
        message = build_message(folder_rel_path, entry_rel_path)
        result = run(['mc', 'tui', agent, '--session', instance_name, '--message', message])
        if result.returncode != 0:
            fail({'ok': False, 'error': 'mc_tui_failed', 'agent': agent, 'session': instance_name, 'details': result.stderr or result.stdout})
        tui_started = True

    print(json.dumps({
        'ok': True,
        'mode': 'B+C' if do_tui else 'B',
        'workspace': str(workspace),
        'agent': agent,
        'instance_name': instance_name,
        'target_dir': str(target_dir),
        'folder_rel_path': folder_rel_path,
        'entry_rel_path': entry_rel_path,
        'tui_started': tui_started,
        'session': instance_name,
        'message': message,
    }, ensure_ascii=False))


if __name__ == '__main__':
    main()
