import React from "react";
import { fmtClock, fmtDate } from "./time";
import { LoadingTitle } from "./loading-indicator";
import { errorMessage, requestJson as requestUniDeskJson } from "./unidesk-error";
import { UniDeskErrorBanner } from "./unidesk-error-banner";
import { useNotification } from "./notification-context";

type AnyRecord = Record<string, any>;

const h = React.createElement;
const { useEffect } = React;
const useState: any = React.useState;
const PRIMARY_PRIVATE_CHAT = { label: "主用户私聊账号", userId: 645275593 };


function numberText(value: any): string {
  const number = Number(value);
  return Number.isFinite(number) ? number.toLocaleString("zh-CN") : "--";
}

async function requestJson(path: string, options: AnyRecord = {}): Promise<any> {
  return requestUniDeskJson(path, { failureFields: ["ok", "success"], ...options });
}

async function requestHealthJson(path: string): Promise<any> {
  const response = await fetch(path, { credentials: "same-origin" });
  const text = await response.text();
  try {
    return text ? JSON.parse(text) : { ok: response.ok, status: response.status };
  } catch {
    return { ok: response.ok, status: response.status, text };
  }
}

function StatusBadge({ status, children }: AnyRecord) {
  const normalized = String(status || "unknown").toLowerCase();
  return h("span", { className: `status-badge ${normalized}` }, children || status || "unknown");
}

function MetricCard({ label, value, hint, tone }: AnyRecord) {
  return h("article", { className: `metric-card ${tone || ""}` },
    h("div", { className: "metric-label" }, label),
    h("div", { className: "metric-value" }, value),
    h("div", { className: "metric-hint" }, hint),
  );
}

function Panel({ title, eyebrow, actions, children, className, loading }: AnyRecord) {
  return h("section", { className: `panel ${className || ""}` },
    h("div", { className: "panel-head" },
      h("div", null,
        eyebrow ? h("p", { className: "panel-eyebrow" }, eyebrow) : null,
        h(LoadingTitle, { title, loading }),
      ),
      actions ? h("div", { className: "panel-actions" }, actions) : null,
    ),
    h("div", { className: "panel-body" }, children),
  );
}

function RawButton({ title, data, onOpen, testId }: AnyRecord) {
  return h("button", {
    type: "button",
    className: "ghost-btn",
    "data-testid": testId,
    onClick: (event: any) => {
      event?.stopPropagation?.();
      onOpen(title, data);
    },
  }, "查看原始JSON");
}

function EmptyState({ title, text }: AnyRecord) {
  return h("div", { className: "empty-state" }, h("strong", null, title), h("span", null, text));
}

function microserviceRuntime(service: any): AnyRecord {
  return service?.runtime && typeof service.runtime === "object" && !Array.isArray(service.runtime) ? service.runtime : {};
}

function microserviceBackend(service: any): AnyRecord {
  return service?.backend && typeof service.backend === "object" && !Array.isArray(service.backend) ? service.backend : {};
}

function microserviceRepository(service: any): AnyRecord {
  return service?.repository && typeof service.repository === "object" && !Array.isArray(service.repository) ? service.repository : {};
}

function claudeqqApi(apiBaseUrl: string, path: string): string {
  return `${apiBaseUrl}/microservices/claudeqq/proxy${path}`;
}

function eventRows(payload: any): any[] {
  return Array.isArray(payload?.events) ? payload.events.slice(0, 80) : [];
}

function subscriptionRows(payload: any): any[] {
  return Array.isArray(payload?.subscriptions) ? payload.subscriptions.slice(0, 50) : [];
}

function sentRows(payload: any): any[] {
  return Array.isArray(payload?.messages) ? payload.messages.slice(0, 30) : [];
}

function eventText(event: any): string {
  const text = event?.text ?? event?.message ?? event?.raw?.raw_message;
  if (typeof text !== "string") return "--";
  return text.length > 180 ? `${text.slice(0, 177)}...` : text;
}

function targetText(record: any): string {
  const groupId = record?.groupId ?? record?.group_id ?? (record?.message_type === "group" ? record?.target_id : undefined);
  const userId = record?.userId ?? record?.user_id ?? (record?.message_type === "private" ? record?.target_id : undefined);
  if (groupId) return `群 ${groupId}`;
  if (userId) return `私聊 ${userId}`;
  return "--";
}

export function ClaudeQqPage({ microservices, onRaw, apiBaseUrl = "/api" }: AnyRecord) {
  const service = microservices.find((item: any) => item.id === "claudeqq") || null;
  const [state, setState] = useState({ loading: false, qrLoading: false, error: "", health: null, status: null, napcatLogin: null, napcatQrcode: null, qrcodeFetched: false, qrcodeRefreshedAt: null, events: null, subscriptions: null, sent: null, refreshedAt: null });
  const [pushForm, setPushForm] = useState({ targetType: "private", targetId: String(PRIMARY_PRIVATE_CHAT.userId), message: "" });
  const [subscriptionForm, setSubscriptionForm] = useState({ name: "unidesk-callback", targetUrl: "", eventTypes: "message", secret: "" });
  const [actionMessage, setActionMessage] = useState("");
  const { addNotification } = useNotification();

  async function load(): Promise<void> {
    if (!service) return;
    setState((prev: any) => ({ ...prev, loading: true, error: "" }));
    try {
      const [health, status, events, subscriptions, sent] = await Promise.all([
        requestHealthJson(`${apiBaseUrl}/microservices/claudeqq/health`),
        requestJson(claudeqqApi(apiBaseUrl, "/api/server/status")),
        requestJson(claudeqqApi(apiBaseUrl, "/api/events/recent?limit=60")),
        requestJson(claudeqqApi(apiBaseUrl, "/api/events/subscriptions")),
        requestJson(claudeqqApi(apiBaseUrl, "/api/messages/sent?limit=20")),
      ]);
      setState((prev: any) => ({ ...prev, loading: false, error: "", health, status, events, subscriptions, sent, refreshedAt: new Date() }));
      if (!state.qrcodeFetched) {
        void refreshNapcatQrcode(false);
      }
    } catch (err) {
      setState((prev: any) => ({ ...prev, loading: false, error: errorMessage(err, "ClaudeQQ 加载失败") }));
    }
  }

  async function refreshNapcatQrcode(manual = true): Promise<void> {
    if (!service) return;
    setState((prev: any) => ({ ...prev, qrLoading: true, error: manual ? "" : prev.error }));
    try {
      const napcatLogin = await requestJson(claudeqqApi(apiBaseUrl, "/api/napcat/login"));
      const napcatQrcode = napcatLogin?.napcat?.qrcode || napcatLogin?.qrcode || null;
      setState((prev: any) => ({
        ...prev,
        qrLoading: false,
        error: "",
        napcatLogin,
        napcatQrcode,
        qrcodeFetched: true,
        qrcodeRefreshedAt: new Date(),
      }));
    } catch (err) {
      setState((prev: any) => ({
        ...prev,
        qrLoading: false,
        error: manual || !prev.napcatQrcode ? errorMessage(err, "NapCat 二维码加载失败") : prev.error,
      }));
    }
  }

  async function sendPush(event: any): Promise<void> {
    event.preventDefault();
    setActionMessage("");
    const targetId = Number(pushForm.targetId);
    if (!Number.isFinite(targetId) || targetId <= 0 || pushForm.message.trim().length === 0) {
      setState((prev: any) => ({ ...prev, error: "请填写 QQ 目标和消息内容" }));
      return;
    }
    try {
      await requestJson(claudeqqApi(apiBaseUrl, "/api/push/text"), {
        method: "POST",
        body: JSON.stringify({
          userId: pushForm.targetType === "private" ? targetId : undefined,
          groupId: pushForm.targetType === "group" ? targetId : undefined,
          message: pushForm.message,
        }),
      });
      const msg = "消息推送请求已提交";
      setPushForm((prev: any) => ({ ...prev, targetType: "private", targetId: String(PRIMARY_PRIVATE_CHAT.userId), message: "" }));
      setActionMessage(msg);
      addNotification("success", msg);
      await load();
    } catch (err) {
      setState((prev: any) => ({ ...prev, error: errorMessage(err, "发送失败") }));
    }
  }

  async function createSubscription(event: any): Promise<void> {
    event.preventDefault();
    setActionMessage("");
    if (subscriptionForm.targetUrl.trim().length === 0) {
      setState((prev: any) => ({ ...prev, error: "请填写订阅回调 URL" }));
      return;
    }
    try {
      await requestJson(claudeqqApi(apiBaseUrl, "/api/events/subscriptions"), {
        method: "POST",
        body: JSON.stringify({
          name: subscriptionForm.name,
          targetUrl: subscriptionForm.targetUrl,
          eventTypes: subscriptionForm.eventTypes.split(",").map((item: string) => item.trim()).filter(Boolean),
          secret: subscriptionForm.secret || undefined,
          enabled: true,
        }),
      });
      const msg = "事件订阅已创建";
      setActionMessage(msg);
      addNotification("success", msg);
      await load();
    } catch (err) {
      setState((prev: any) => ({ ...prev, error: errorMessage(err, "订阅失败") }));
    }
  }

  async function deleteSubscription(id: string): Promise<void> {
    if (!id) return;
    setActionMessage("");
    try {
      await requestJson(claudeqqApi(apiBaseUrl, `/api/events/subscriptions/${encodeURIComponent(id)}`), { method: "DELETE" });
      const msg = "事件订阅已删除";
      setActionMessage(msg);
      addNotification("success", msg);
      await load();
    } catch (err) {
      setState((prev: any) => ({ ...prev, error: errorMessage(err, "删除订阅失败") }));
    }
  }

  useEffect(() => {
    if (!service) return undefined;
    load();
    return undefined;
  }, [service?.id, service?.runtime?.providerStatus]);

  if (!service) return h(EmptyState, { title: "ClaudeQQ 未登记", text: "请在 config.json 的 microservices 中登记用户服务 id=claudeqq" });

  const runtime = microserviceRuntime(service);
  const repository = microserviceRepository(service);
  const backend = microserviceBackend(service);
  const health = state.health || {};
  const status = state.status || {};
  const napcatLogin = state.napcatLogin || {};
  const napcatStatus = health.napcat || status.napcat || {};
  const napcat = { ...(napcatLogin.napcat || {}), ...napcatStatus, qrcode: state.napcatQrcode || {}, webui: napcatStatus.webui || napcatLogin.napcat?.webui };
  const login = napcatLogin.login || {};
  const qrcode = state.napcatQrcode || {};
  const events = eventRows(state.events);
  const subscriptions = subscriptionRows(state.subscriptions);
  const sent = sentRows(state.sent);
  const loginReady = Boolean(napcat.httpConnected || login.ready);
  const loginState = String(napcat.loginState || login.state || (loginReady ? "logged_in" : "unknown"));
  const qrAvailable = Boolean(qrcode.available && qrcode.dataUrl);

  return h("div", { className: "claudeqq-page", "data-testid": "claudeqq-page" },
    h(Panel, {
      title: "ClaudeQQ 工作台",
      eyebrow: "D601 QQ Event Gateway",
      loading: state.loading,
      actions: h("div", { className: "panel-actions" },
        h("button", { type: "button", className: "ghost-btn", onClick: load, disabled: state.loading, "data-testid": "claudeqq-refresh-button" }, state.loading ? "刷新中" : "刷新"),
        h(RawButton, { title: "ClaudeQQ 用户服务", data: service, onOpen: onRaw, testId: "raw-claudeqq-service" }),
      ),
    },
      h("div", { className: "findjob-hero" },
        h("div", null,
          h("div", { className: "node-version-line" },
            h(StatusBadge, { status: runtime.providerStatus === "online" ? "online" : "warn" }, runtime.providerStatus || "unknown"),
            h("span", null, service.providerId),
            h("span", null, backend.public ? "公网暴露" : "仅 UniDesk frontend 代理访问"),
          ),
          h("p", { className: "muted paragraph" }, service.description),
        ),
        h("div", { className: "microservice-ref-card" },
          h("span", null, "Repo"),
          h("strong", null, repository.url || "--"),
          h("code", null, repository.commitId || "--"),
        ),
        h("div", { className: "microservice-ref-card" },
          h("span", null, "D601 k3s Service"),
          h("strong", null, `${backend.nodeBindHost || "--"}:${backend.nodePort || "--"}`),
          h("code", null, `${backend.proxyMode || "--"} / ${repository.composeFile || "--"}`),
        ),
      ),
      h(UniDeskErrorBanner, { error: state.error, wide: true }),
    ),
    h("div", { className: "metric-grid" },
      h(MetricCard, { label: "Health", value: health.ok || health.status === "ok" ? "OK" : "--", hint: "D601 /health", tone: health.ok || health.status === "ok" ? "ok" : "warn" }),
      h(MetricCard, { label: "NapCat HTTP", value: napcat.httpConnected || napcat.http?.connected ? "OK" : "离线", hint: `${napcat.httpHost || health.napcat?.httpHost || "--"}:${napcat.httpPort || health.napcat?.httpPort || "--"}` }),
      h(MetricCard, { label: "NapCat WS", value: napcat.wsConnected || napcat.ws?.connected ? "OK" : "离线", hint: `${napcat.wsHost || health.napcat?.wsHost || "--"}:${napcat.wsPort || health.napcat?.wsPort || "--"}` }),
      h(MetricCard, { label: "事件缓存", value: numberText(state.events?.count ?? events.length), hint: "recent QQ events" }),
      h(MetricCard, { label: "订阅", value: numberText(state.subscriptions?.count ?? subscriptions.length), hint: "webhook subscribers" }),
      h(MetricCard, { label: "已发送", value: numberText(state.sent?.count ?? sent.length), hint: "sent message log" }),
    ),
    h("div", { className: "findjob-grid" },
      h(Panel, {
        title: "NapCat 容器登录",
        eyebrow: "QR Login",
        className: "claudeqq-login-panel",
        loading: state.qrLoading,
        actions: h("div", { className: "panel-actions inline-actions" },
          h("button", { type: "button", className: "ghost-btn", onClick: () => refreshNapcatQrcode(true), disabled: state.qrLoading, "data-testid": "claudeqq-napcat-refresh" }, state.qrLoading ? "刷新中" : "手动刷新二维码"),
          h(RawButton, { title: "NapCat Login", data: state.napcatLogin, onOpen: onRaw, testId: "raw-claudeqq-napcat-login" }),
        ),
      },
        h("div", { className: "claudeqq-login-card", "data-testid": "claudeqq-napcat-login" },
          h("div", { className: "claudeqq-qr-frame" },
            qrAvailable
              ? h("img", { src: qrcode.dataUrl, alt: "NapCat QQ 登录二维码", "data-testid": "claudeqq-napcat-qrcode" })
              : h(EmptyState, { title: "等待二维码", text: "NapCat 容器启动后会把登录二维码写入 cache/qrcode.png" }),
          ),
          h("div", { className: "claudeqq-login-copy" },
            h("div", { className: "node-version-line" },
              h(StatusBadge, { status: loginReady ? "online" : qrAvailable ? "warn" : "unknown" }, loginReady ? "已登录" : qrAvailable ? "待扫码" : "等待二维码"),
              h("span", null, loginState),
              h("span", null, "D601 containerized"),
            ),
            h("p", { className: "muted paragraph" }, loginReady
              ? "NapCat 已登录，ClaudeQQ 可通过容器内 HTTP/WS 链路收发 QQ 消息。"
              : "用手机 QQ 扫描二维码授权登录。二维码只在首次加载或手动刷新时更新，D601 的 NapCat 端口仍只绑定 127.0.0.1。"),
            h("div", { className: "microservice-ref-card" },
              h("span", null, "NapCat WebUI"),
              h("strong", null, napcat.webui?.url || "http://napcat:6099/webui"),
              h("code", null, "local-only / proxied QR login"),
            ),
            h("div", { className: "microservice-ref-card" },
              h("span", null, "QR Source"),
              h("strong", null, qrcode.modifiedAt ? fmtDate(qrcode.modifiedAt) : state.qrcodeRefreshedAt ? fmtDate(state.qrcodeRefreshedAt) : "--"),
              h("code", null, qrcode.file || "/napcat/cache/qrcode.png"),
            ),
          ),
        ),
      ),
      h(Panel, { title: "消息推送", eyebrow: "Push API" },
        h("div", { className: "microservice-ref-card" },
          h("span", null, PRIMARY_PRIVATE_CHAT.label),
          h("strong", null, String(PRIMARY_PRIVATE_CHAT.userId)),
          h("code", null, "private userId / 默认推送测试目标"),
        ),
        h("form", { className: "stack-form", onSubmit: sendPush, "data-testid": "claudeqq-push-form" },
          h("label", null, "目标类型",
            h("select", { value: pushForm.targetType, onChange: (event: any) => setPushForm((prev: any) => ({ ...prev, targetType: event.target.value })) },
              h("option", { value: "private" }, "私聊 userId"),
              h("option", { value: "group" }, "群 groupId"),
            ),
          ),
          h("label", null, "QQ ID", h("input", { value: pushForm.targetId, onChange: (event: any) => setPushForm((prev: any) => ({ ...prev, targetId: event.target.value })), placeholder: String(PRIMARY_PRIVATE_CHAT.userId) })),
          h("label", null, "消息内容", h("textarea", { value: pushForm.message, onChange: (event: any) => setPushForm((prev: any) => ({ ...prev, message: event.target.value })), rows: 4, placeholder: "通过 ClaudeQQ 推送一条 QQ 消息" })),
          h("button", { type: "submit", className: "primary-btn" }, "发送 QQ 消息"),
        ),
        h("p", { className: "muted paragraph" }, `主 server 和其他用户服务可通过 UniDesk 同源代理调用 /api/push/text；当前人工推送测试默认使用 ${PRIMARY_PRIVATE_CHAT.label} ${PRIMARY_PRIVATE_CHAT.userId}，不需要暴露 D601 后端端口。`),
      ),
      h(Panel, { title: "QQ 事件订阅", eyebrow: "Webhook Subscription", loading: state.loading },
        h("form", { className: "stack-form", onSubmit: createSubscription, "data-testid": "claudeqq-subscription-form" },
          h("label", null, "订阅名称", h("input", { value: subscriptionForm.name, onChange: (event: any) => setSubscriptionForm((prev: any) => ({ ...prev, name: event.target.value })) })),
          h("label", null, "回调 URL", h("input", { value: subscriptionForm.targetUrl, onChange: (event: any) => setSubscriptionForm((prev: any) => ({ ...prev, targetUrl: event.target.value })), placeholder: "http://host.docker.internal:18080/..." })),
          h("label", null, "事件类型", h("input", { value: subscriptionForm.eventTypes, onChange: (event: any) => setSubscriptionForm((prev: any) => ({ ...prev, eventTypes: event.target.value })), placeholder: "message,notice" })),
          h("label", null, "签名密钥", h("input", { value: subscriptionForm.secret, onChange: (event: any) => setSubscriptionForm((prev: any) => ({ ...prev, secret: event.target.value })), placeholder: "可选，生成 x-claudeqq-signature" })),
          h("button", { type: "submit", className: "primary-btn" }, "创建订阅"),
        ),
        subscriptions.length === 0 ? h(EmptyState, { title: "暂无订阅", text: "可以为 main server 或其他用户服务注册 HTTP webhook" }) :
          h("div", { className: "table-wrap", "data-testid": "claudeqq-subscription-table" }, h("table", null,
            h("thead", null, h("tr", null, h("th", null, "名称"), h("th", null, "状态"), h("th", null, "事件"), h("th", null, "回调"), h("th", null, "最近投递"), h("th", null, "操作"))),
            h("tbody", null, subscriptions.map((item: any) => h("tr", { key: item.id },
              h("td", null, h("strong", null, item.name || item.id), h("code", null, item.id || "--")),
              h("td", null, h(StatusBadge, { status: item.enabled ? "online" : "warn" }, item.enabled ? "enabled" : "disabled")),
              h("td", null, Array.isArray(item.eventTypes) ? item.eventTypes.join(", ") : "message"),
              h("td", null, item.targetUrl || "--"),
              h("td", null, item.lastDelivery ? `${item.lastDelivery.ok ? "OK" : "FAIL"} ${fmtDate(item.lastDelivery.at)}` : "--"),
              h("td", null, h("button", { type: "button", className: "ghost-btn", onClick: () => deleteSubscription(item.id) }, "删除")),
            ))),
          )),
        h("div", { className: "panel-actions inline-actions" }, h(RawButton, { title: "ClaudeQQ Subscriptions", data: state.subscriptions, onOpen: onRaw, testId: "raw-claudeqq-subscriptions" })),
      ),
      h(Panel, { title: "最近 QQ 事件", eyebrow: state.refreshedAt ? `Updated ${fmtClock(state.refreshedAt)}` : "Event Stream", loading: state.loading },
        events.length === 0 ? h(EmptyState, { title: "暂无事件", text: "等待 NapCat WebSocket 上报 QQ 消息事件，或通过订阅 API 消费后续事件" }) :
          h("div", { className: "table-wrap", "data-testid": "claudeqq-event-list" }, h("table", null,
            h("thead", null, h("tr", null, h("th", null, "时间"), h("th", null, "类型"), h("th", null, "会话"), h("th", null, "消息"), h("th", null, "ID"))),
            h("tbody", null, events.map((event: any) => h("tr", { key: event.id },
              h("td", null, fmtDate(event.receivedAt || event.timestamp)),
              h("td", null, h(StatusBadge, { status: event.postType || event.eventType }, event.postType || event.eventType || "--")),
              h("td", null, targetText(event)),
              h("td", null, eventText(event)),
              h("td", null, h("code", null, event.messageId || event.id || "--")),
            ))),
          )),
        h("div", { className: "panel-actions inline-actions" }, h(RawButton, { title: "ClaudeQQ Events", data: state.events, onOpen: onRaw, testId: "raw-claudeqq-events" })),
      ),
      h(Panel, { title: "已发送消息", eyebrow: `${sent.length} Sent`, loading: state.loading },
        sent.length === 0 ? h(EmptyState, { title: "暂无发送记录", text: "发送日志来自 ClaudeQQ bot_workspace/messages/sent_messages.jsonl" }) :
          h("div", { className: "table-wrap" }, h("table", null,
            h("thead", null, h("tr", null, h("th", null, "时间"), h("th", null, "目标"), h("th", null, "消息"), h("th", null, "结果"))),
            h("tbody", null, sent.map((item: any, index: number) => h("tr", { key: item.id || index },
              h("td", null, fmtDate(item.timestamp || item.sentAt || item.createdAt)),
              h("td", null, targetText(item)),
              h("td", null, eventText(item)),
              h("td", null, item.status || item.messageId || item.message_id || "--"),
            ))),
          )),
        h("div", { className: "panel-actions inline-actions" }, h(RawButton, { title: "ClaudeQQ Sent Messages", data: state.sent, onOpen: onRaw, testId: "raw-claudeqq-sent" })),
      ),
    ),
  );
}
