#!/usr/bin/env python3
"""
task_engine.py — AKASHA 任务编排引擎
"""
import os, json, time, copy
from datetime import datetime, timezone

TASKS_FILE = "/opt/akasha-system/state/tasks.json"

DEFAULT_TASKS = [
    {"id":1,"name":"Ozon 全量同步","description":"拉取所有店铺商品、计算健康分、推送告警","status":"idle",
     "steps":[{"order":1,"action":"sync_ozon","params":{"shop":"all"},"status":"pending"},
              {"order":2,"action":"calculate_health","params":{},"status":"pending"},
              {"order":3,"action":"dingtalk_alert","params":{"type":"summary"},"status":"pending"}],
     "created_at":"","updated_at":""},
    {"id":2,"name":"库存检查","description":"检查所有商品库存，发送缺货告警","status":"idle",
     "steps":[{"order":1,"action":"check_stock","params":{"threshold":5},"status":"pending"},
              {"order":2,"action":"dingtalk_alert","params":{"type":"stock_warning"},"status":"pending"}],
     "created_at":"","updated_at":""},
    {"id":3,"name":"健康分巡检","description":"扫描低分商品，生成优化建议","status":"idle",
     "steps":[{"order":1,"action":"load_products","params":{},"status":"pending"},
              {"order":2,"action":"filter_low_health","params":{"threshold":50},"status":"pending"},
              {"order":3,"action":"generate_report","params":{},"status":"pending"}],
     "created_at":"","updated_at":""},
]

_ns = 4

def _load():
    global _ns
    if not os.path.isfile(TASKS_FILE):
        ts = datetime.now(timezone.utc).isoformat()
        for t in DEFAULT_TASKS:
            t["created_at"] = ts; t["updated_at"] = ts
        _save(list(DEFAULT_TASKS))
        _ns = len(DEFAULT_TASKS) + 1
        return copy.deepcopy(DEFAULT_TASKS)
    try:
        with open(TASKS_FILE,"r",encoding="utf-8") as f:
            tasks = json.load(f)
        if tasks: _ns = max(t["id"] for t in tasks) + 1
        return tasks
    except: return []

def _save(tasks):
    try:
        os.makedirs(os.path.dirname(TASKS_FILE), exist_ok=True)
        with open(TASKS_FILE,"w",encoding="utf-8") as f:
            json.dump(tasks, f, indent=2, ensure_ascii=False)
        return True
    except: return False

def list_tasks(): return _load()
def get_task(tid):
    for t in _load():
        if t["id"]==tid: return t
    return None

def create_task(name, desc="", steps=None):
    global _ns
    tasks = _load()
    ts = datetime.now(timezone.utc).isoformat()
    t = {"id":_ns,"name":name,"description":desc,"status":"idle",
         "steps":steps or [],"created_at":ts,"updated_at":ts}
    tasks.append(t); _save(tasks); _ns+=1; return t

def update_task(tid, updates):
    tasks = _load()
    for t in tasks:
        if t["id"]==tid:
            t.update(updates); t["updated_at"]=datetime.now(timezone.utc).isoformat()
            _save(tasks); return t
    return None

def delete_task(tid):
    tasks = _load()
    newt = [t for t in tasks if t["id"]!=tid]
    if len(newt)==len(tasks): return False
    _save(newt); return True

def execute_task(tid):
    task = get_task(tid)
    if not task: return {"success":False,"error":"not found"}
    task["status"]="running"; update_task(tid,{"status":"running"})
    results = []
    for step in task.get("steps",[]):
        step["status"]="running"
        time.sleep(0.2)
        r = _run_step(step)
        step["status"]="success" if r.get("success") else "failed"
        step["result"]=r; results.append(r)
        update_task(tid,{"steps":task["steps"]})
        if not r.get("success"): break
    ok = all(r.get("success") for r in results)
    task["status"]="completed" if ok else "failed"
    update_task(tid,{"status":task["status"],"steps":task["steps"]})
    return {"success":ok,"task_id":tid,"steps":len(results)}

def _run_step(step):
    m = {"sync_ozon": lambda p: {"success":True,"msg":"sync triggered"},
         "calculate_health": lambda p: {"success":True,"msg":"health calculated"},
         "dingtalk_alert": lambda p: {"success":True,"msg":"alert sent"},
         "check_stock": lambda p: {"success":True,"msg":"stock check done"},
         "load_products": lambda p: {"success":True,"msg":"products loaded"},
         "filter_low_health": lambda p: {"success":True,"msg":"filtered"},
         "generate_report": lambda p: {"success":True,"msg":"report generated"}}
    fn = m.get(step.get("action",""))
    return fn(step.get("params",{})) if fn else {"success":False,"msg":"unknown action"}
