from __future__ import annotations

import asyncio
from collections import defaultdict

from flask import Flask, jsonify, request

from .auto_draw import auto_draw_preview
from .logger import setup_logger
from .orchestrator import Orchestrator
from .rules import extract_image_urls
from .runtime_switch import is_listen_only, set_listen_only
from .task_manager import TaskManager


def create_http_app(task_manager: TaskManager | None = None) -> Flask:
    app = Flask(__name__)
    logger = setup_logger()
    tm = task_manager or TaskManager()
    sim_orch = Orchestrator()
    sim_pending_images: dict[str, list[str]] = defaultdict(list)
    sim_recent_dialogue: dict[str, list[dict]] = defaultdict(list)

    def _sim_append_dialogue(key: str, role: str, text: str) -> None:
        t = str(text or "").strip()
        if not t:
            return
        sim_recent_dialogue[key].append({"role": role, "text": t})
        if len(sim_recent_dialogue[key]) > 24:
            sim_recent_dialogue[key] = sim_recent_dialogue[key][-24:]

    @app.get('/api/health')
    def health():
        return jsonify({'ok': True})

    @app.get('/api/runtime/listen_only')
    def get_listen_only():
        return jsonify({'ok': True, 'listen_only': is_listen_only()})

    @app.post('/api/runtime/listen_only')
    def set_listen_only_mode():
        body = request.get_json(silent=True) or {}
        if "enabled" not in body:
            return jsonify({'ok': False, 'error': 'enabled required'}), 400
        enabled = bool(body.get("enabled"))
        current = set_listen_only(enabled)
        logger.info('[运行时] listen_only=%s', current)
        return jsonify({'ok': True, 'listen_only': current})

    @app.post('/api/task/receive')
    def receive_task():
        payload = request.get_json(silent=True) or {}
        task_id = tm.create_task(payload)
        logger.info('[任务] receive task_id=%s', task_id)
        return jsonify({'ok': True, 'task_id': task_id})

    @app.post('/api/task/cancel')
    def cancel_task():
        body = request.get_json(silent=True) or {}
        task_id = str(body.get('task_id', '')).strip()
        if not task_id:
            return jsonify({'ok': False, 'error': 'task_id required'}), 400
        ok = tm.cancel_task(task_id)
        return jsonify({'ok': ok, 'task_id': task_id})

    @app.get('/api/task/status/<task_id>')
    def task_status(task_id: str):
        task = tm.get_task(task_id)
        if not task:
            return jsonify({'ok': False, 'error': 'not found'}), 404
        return jsonify({'ok': True, 'task': task})

    @app.get('/api/task/list')
    def task_list():
        limit = int(request.args.get('limit', 100))
        return jsonify({'ok': True, 'tasks': tm.list_tasks(limit=limit)})

    @app.get('/debug/simulator')
    def debug_simulator():
        return """
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>链路测试页</title>
  <style>
    :root { --bg:#f6f8fb; --card:#fff; --ink:#1f2937; --line:#dbe3ef; --brand:#0f766e; }
    body { margin:0; background:var(--bg); color:var(--ink); font-family:"Microsoft YaHei UI", "PingFang SC", sans-serif; }
    .wrap { max-width:900px; margin:24px auto; padding:0 16px; }
    .card { background:var(--card); border:1px solid var(--line); border-radius:14px; padding:16px; }
    h2 { margin:0 0 14px; font-size:20px; }
    .row { display:grid; grid-template-columns:140px 1fr; gap:8px; margin:8px 0; align-items:center; }
    input, textarea { width:100%; box-sizing:border-box; border:1px solid #c7d3e3; border-radius:8px; padding:8px 10px; font-size:14px; }
    textarea { min-height:100px; resize:vertical; }
    .btns { display:flex; gap:10px; margin-top:12px; }
    button { border:0; border-radius:8px; padding:9px 14px; cursor:pointer; color:#fff; background:var(--brand); }
    button.secondary { background:#475569; }
    pre { margin-top:12px; background:#0f172a; color:#e2e8f0; padding:12px; border-radius:8px; overflow:auto; }
    label.chk { display:flex; gap:8px; align-items:center; font-size:14px; }
  </style>
</head>
<body>
  <div class="wrap">
    <div class="card">
      <h2>AI链路模拟测试</h2>
      <div class="row"><div>店铺acc_id</div><input id="acc_id" value="demo_shop:cs" /></div>
      <div class="row"><div>客户customer_id</div><input id="customer_id" value="demo_user_001" /></div>
      <div class="row"><div>商品标题</div><input id="goods_name" value="模糊图清晰处理专业代找原图素材淘宝图片找图修复服务" /></div>
      <div class="row"><div>订单信息</div><input id="goods_order" value="" placeholder="可空" /></div>
      <div class="row"><div>客户消息</div><textarea id="msg" placeholder="可直接粘贴图片URL，支持 #*# 拼接"></textarea></div>
      <div class="row"><div>选项</div><label class="chk"><input type="checkbox" id="simulate_draw" />quote时顺带模拟作图</label></div>
      <div class="btns">
        <button onclick="sendMsg()">发送模拟消息</button>
        <button class="secondary" onclick="resetCtx()">清空该客户上下文</button>
      </div>
      <pre id="out">等待发送...</pre>
    </div>
  </div>
  <script>
    async function sendMsg() {
      const body = {
        acc_id: document.getElementById('acc_id').value.trim(),
        customer_id: document.getElementById('customer_id').value.trim(),
        goods_name: document.getElementById('goods_name').value.trim(),
        goods_order: document.getElementById('goods_order').value.trim(),
        msg: document.getElementById('msg').value.trim(),
        simulate_draw: document.getElementById('simulate_draw').checked
      };
      const res = await fetch('/api/simulate/message', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(body),
      });
      const data = await res.json();
      document.getElementById('out').textContent = JSON.stringify(data, null, 2);
    }
    async function resetCtx() {
      const body = {
        acc_id: document.getElementById('acc_id').value.trim(),
        customer_id: document.getElementById('customer_id').value.trim(),
      };
      const res = await fetch('/api/simulate/reset', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(body),
      });
      const data = await res.json();
      document.getElementById('out').textContent = JSON.stringify(data, null, 2);
    }
  </script>
</body>
</html>
"""

    @app.post('/api/simulate/reset')
    def sim_reset():
        body = request.get_json(silent=True) or {}
        acc_id = str(body.get("acc_id", "")).strip()
        customer_id = str(body.get("customer_id", "")).strip()
        if not acc_id or not customer_id:
            return jsonify({'ok': False, 'error': 'acc_id and customer_id required'}), 400
        key = f"{acc_id}:{customer_id}"
        sim_pending_images.pop(key, None)
        sim_recent_dialogue.pop(key, None)
        try:
            sim_orch.store.upsert_session(key, acc_id, customer_id, "pre_sales", {"after_sales_stage": "new"})
        except Exception:
            pass
        return jsonify({'ok': True, 'customer_key': key, 'message': '上下文已清空'})

    @app.post('/api/simulate/message')
    def sim_message():
        body = request.get_json(silent=True) or {}
        acc_id = str(body.get("acc_id", "")).strip()
        customer_id = str(body.get("customer_id", "")).strip()
        goods_name = str(body.get("goods_name", "")).strip()
        goods_order = str(body.get("goods_order", "")).strip()
        msg = str(body.get("msg", "")).strip()
        simulate_draw = bool(body.get("simulate_draw"))
        if not acc_id or not customer_id or not msg:
            return jsonify({'ok': False, 'error': 'acc_id, customer_id, msg required'}), 400

        key = f"{acc_id}:{customer_id}"
        urls = extract_image_urls(msg)
        for u in urls:
            if u not in sim_pending_images[key]:
                sim_pending_images[key].append(u)
        _sim_append_dialogue(key, "user", msg)
        latest_image_url = urls[-1] if urls else (sim_pending_images[key][-1] if sim_pending_images[key] else "")

        context = {
            "customer_key": key,
            "acc_id": acc_id,
            "customer_id": customer_id,
            "goods_name": goods_name,
            "goods_order": goods_order,
            "msg": msg,
            "intent": "unknown",
            "pending_images": len(sim_pending_images[key]),
            "pending_image_urls": sim_pending_images[key][-5:],
            "current_image_urls": urls[-3:],
            "latest_image_url": latest_image_url,
            "auto_quote_trigger": False,
            "last_reply": "",
            "recent_dialogue": sim_recent_dialogue[key][-12:],
        }

        route, decision, state = asyncio.run(sim_orch.decide(context))
        if decision.reply:
            _sim_append_dialogue(key, "assistant", decision.reply)

        draw_result: dict = {}
        if simulate_draw and decision.action == "quote" and latest_image_url:
            draw_result = asyncio.run(
                auto_draw_preview(
                    image_url=latest_image_url,
                    customer_id=customer_id,
                    requirement=msg,
                )
            )

        logger.info("[模拟] key=%s route=%s action=%s", key, route, decision.action)
        return jsonify(
            {
                "ok": True,
                "customer_key": key,
                "route": route,
                "decision": {
                    "action": decision.action,
                    "reply": decision.reply,
                    "transfer_msg": decision.transfer_msg,
                    "quote_mode": decision.quote_mode,
                    "reason": decision.reason,
                },
                "state": state,
                "pending_images": sim_pending_images[key],
                "draw_result": draw_result,
            }
        )

    return app


def run_http_server(host: str, port: int, task_manager: TaskManager | None = None) -> None:
    app = create_http_app(task_manager=task_manager)
    app.run(host=host, port=port, debug=False, use_reloader=False)
