#!/usr/bin/env python3
"""Hermes 工作台实时API服务器
端口 8765 — 静态文件 + MCP实时数据代理
"""

import http.server
import subprocess, json, os, re, time
from datetime import datetime
from urllib.parse import urlparse, parse_qs

TK = "m-abfb29e8-3104-434f-9944-8d0bb592f8cd"
MCP_URL = "https://project.feishu.cn/mcp_server/v1"
WORK_DIR = "/Users/liuxinyuan/Desktop/Hermes输出-工作类"
SALES_PK = "6593cd71471290e3cc6be6e6"
COMPLAINTS_PK = "658288abfb8bd616b17025f1"
CLIENT_PK = "658bb60520ea78a2125f1b99"
USER_CACHE = {}  # user_key → name
API_CACHE = {}   # path → (data, expiry_time)

def mcp_call(method, args, timeout=15):
    r = subprocess.run(['curl','-s','-X','POST', MCP_URL,
        '-H',f'X-Mcp-Token: {TK}','-H','Content-Type: application/json',
        '-d', json.dumps({"jsonrpc":"2.0","method":"tools/call","params":{"name":method,"arguments":args},"id":1})],
        capture_output=True, text=True, timeout=timeout)
    raw = json.loads(r.stdout)
    result = []
    for c in raw.get('result',{}).get('content',[]):
        t = c.get('text','')
        if 'log_id' in t: continue
        if t.startswith('{'): result.append(json.loads(t))
    return result

def parse_mql_items(result_list):
    """Parse moql_field_list into flat dicts"""
    items = []
    for r in result_list:
        for gid, gitems in r.get('data', {}).items():
            for item in gitems:
                fields = {}
                for f in item.get('moql_field_list', []):
                    k = f['name']
                    vdict = f.get('value', {})
                    vals = list(vdict.values()) if vdict else ['']
                    v = vals[0] if vals else ''
                    if isinstance(v, dict): v = list(v.values())[0] if v else ''
                    fields[k] = str(v) if v else ''
                items.append(fields)
    return items

# ===== API Handlers =====

def api_activities():
    """拉取销售管理活动（分页拉全量7月）"""
    all_items = []
    page = 0
    while page < 10:  # Max 10 pages = 500 items
        mql = f"SELECT name, description, `创建时间`, `创建者`, work_item_id FROM `销售管理`.`活动` WHERE `创建时间` >= \"2026-07-01\" ORDER BY `创建时间` DESC LIMIT 50 OFFSET {page*50}"
        result = mcp_call("search_by_mql", {"project_key": SALES_PK, "mql": mql})
        items = parse_mql_items(result)
        if not items:
            break
        all_items.extend(items)
        page += 1
        if len(items) < 50:
            break
    
    items = all_items
    
    # Resolve user keys to names (cache + batch)
    uncached = set()
    for item in items:
        uk = item.get('创建者','')
        if uk and uk.isdigit() and uk not in USER_CACHE:
            uncached.add(uk)
    
    if uncached:
        # Try resolving via get_workitem_brief for more items (up to 20)
        sample = items[:20]
        for item in sample:
            wid = item.get('工作项id','') or item.get('work_item_id','')
            if not wid: continue
            brief_list = mcp_call("get_workitem_brief", {"project_key": SALES_PK, "work_item_id": wid}, timeout=10)
            if brief_list:
                brief = brief_list[0] if isinstance(brief_list, list) else brief_list
                if isinstance(brief, dict):
                    attr = brief.get('work_item_attribute',{})
                cb = attr.get('create_by',{})
                uk = cb.get('user_key','') or cb.get('id','')
                uname = cb.get('name','') or cb.get('display_name','')
                if uk and uname and uk not in USER_CACHE:
                    USER_CACHE[uk] = uname
                if cb.get('key') and cb.get('name'):
                    USER_CACHE[cb['key']] = cb['name']
    
    activities = []
    for item in items:
        name = item.get('name','') or item.get('名称','')
        created = item.get('创建时间','')
        wid = item.get('工作项id','') or item.get('work_item_id','')
        is_pi = '课题组' in name
        creator = item.get('创建者','')
        if creator.isdigit() and creator in USER_CACHE:
            creator = USER_CACHE[creator]
        # Infer activity type
        desc = (item.get('description','') or '')[:200]
        atype = '拜访'
        if '线上' in desc or '电话' in desc: atype = '线上跟进'
        elif '测试' in desc or '送样' in desc: atype = '测试跟进'
        elif '拜访' not in desc and '跟进' in desc: atype = '线上跟进'
        activities.append({
            'client': name[:80],
            'name': name[:80],
            'desc': desc,
            'sales': creator,
            'dept': '生命科学销售部' if is_pi else '诊断原料销售部',
            'type': atype,
            'date': created[:10] if created else '',
            'url': f'https://project.feishu.cn/xsguanli/65ae1e5d44338dbe7c39a29a/detail/{wid}' if wid else '',
            'is_pi': is_pi
        })
    
    return {'items': activities, 'count': len(activities), 'updated': datetime.now().strftime('%H:%M')}

def api_complaints():
    """拉取客诉数据"""
    todo = mcp_call("list_todo", {"action": "todo", "page_size": 50})
    result = todo[0] if todo else {}
    complaints = []
    today = datetime.now()
    
    for wi in result.get('list', []):
        if wi.get('project_key') != COMPLAINTS_PK: continue
        name = wi['work_item_info']['work_item_name']
        # Extract date from name (first 8 consecutive digits = YYYYMMDD)
        days = 0
        m = re.search(r'(\d{8})', name.replace('.','').replace('-','').replace('/',''))
        if m:
            try:
                dt = datetime.strptime(m.group(1), '%Y%m%d')
                days = (today - dt).days
            except ValueError:
                pass
        complaints.append({
            'id': str(wi['work_item_info']['work_item_id']),
            'name': name[:80], 'days': days,
            'url': f'https://project.feishu.cn/br-shgl/detail/{wi["work_item_info"]["work_item_id"]}'
        })
    
    return {'items': sorted(complaints, key=lambda x: -x['days']), 'total': len(complaints)}

def api_sales():
    """拉取今日销售单"""
    today_str = datetime.now().strftime('%Y-%m-%d')
    mql = f'SELECT `单据编号`, `创建时间`, `金额`, `货号#` FROM `销售管理`.`销售订单` WHERE `创建时间` >= "{today_str}" LIMIT 100'
    result = mcp_call("search_by_mql", {"project_key": SALES_PK, "mql": mql}, timeout=30)
    items = parse_mql_items(result)
    
    sales = []
    total = 0
    for item in items:
        amt = float(item.get('金额',0) or 0)
        total += amt
        sales.append({
            'order_no': item.get('单据编号',''),
            'product_code': item.get('货号#',''),
            'amount': amt,
            'date': (item.get('创建时间','') or '')[:10]
        })
    
    return {'items': sales, 'total': len(sales), 'amount': total, 'date': today_str}


class APIHandler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=WORK_DIR, **kwargs)
    
    def do_GET(self):
        parsed = urlparse(self.path)
        
        # API routes
        if parsed.path == '/api/activities':
            self.send_json(self.cached('activities', api_activities, ttl=120))
            return
        elif parsed.path == '/api/complaints':
            self.send_json(self.cached('complaints', api_complaints, ttl=120))
            return
        elif parsed.path == '/api/sales':
            self.send_json(self.cached('sales', api_sales, ttl=60))
            return
        elif parsed.path == '/api/ping':
            self.send_json({'ok': True, 'time': datetime.now().isoformat()})
            return
        
        # Static files
        super().do_GET()
    
    def send_json(self, data):
        body = json.dumps(data, ensure_ascii=False).encode('utf-8')
        self.send_response(200)
        self.send_header('Content-Type', 'application/json; charset=utf-8')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)
    
    def cached(self, path, fn, ttl=60):
        """缓存API结果 ttl秒"""
        now = time.time()
        if path in API_CACHE and API_CACHE[path][1] > now:
            return API_CACHE[path][0]
        data = fn()
        API_CACHE[path] = (data, now + ttl)
        return data
    
    def log_message(self, format, *args):
        # Only log API calls
        if '/api/' in (args[0] if args else ''):
            print(f"[{datetime.now().strftime('%H:%M:%S')}] {args[0]}")

if __name__ == '__main__':
    port = 8765
    print(f"🚀 Hermes工作台API服务器")
    print(f"   静态文件: {WORK_DIR}")
    print(f"   API:  http://127.0.0.1:{port}/api/activities")
    print(f"         http://127.0.0.1:{port}/api/complaints")
    print(f"         http://127.0.0.1:{port}/api/sales")
    print(f"   页面: http://127.0.0.1:{port}/工具/宝锐统一工作平台.html")
    
    server = http.server.HTTPServer(('127.0.0.1', port), APIHandler)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\n👋 已停止")
        server.shutdown()

# === Task Status API ===
TASK_STATUS_FILE = os.path.join(ROOT, '数据', 'task_status.json')

class TaskStatusHandler:
    @staticmethod
    def get_status():
        try:
            with open(TASK_STATUS_FILE) as f:
                return json.load(f)
        except:
            return {"tasks": [], "updated": ""}
    
    @staticmethod
    def update_task(task_id, **kwargs):
        try:
            with open(TASK_STATUS_FILE) as f:
                data = json.load(f)
        except:
            data = {"tasks": [], "updated": ""}
        
        for t in data.get('tasks', []):
            if t['id'] == task_id:
                t.update(kwargs)
                break
        
        data['updated'] = time.strftime('%Y-%m-%d %H:%M:%S')
        with open(TASK_STATUS_FILE, 'w') as f:
            json.dump(data, f, ensure_ascii=False)

