"use client";

import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import clsx from "clsx";

type TelegramGatewayView = {
  enabled: boolean;
  mode: "webhook" | "polling";
  botTokenConfigured: boolean;
  botUsername?: string;
  dmPolicy: "allowlist" | "open" | "disabled";
  allowFrom: string[];
  groupPolicy: "allowlist" | "open" | "disabled";
  groups: string[];
  requireMentionInGroups: boolean;
  defaultProjectId: string;
  groupProjectRoutes: Array<{ chatId: string; threadId?: number; projectId: string; label?: string }>;
  webhookSecretConfigured: boolean;
  webhookUrl?: string;
  lastConfiguredAt?: string;
  lastConfiguredBy?: string;
  lastError?: string;
  processedUpdateCount: number;
};

type Draft = {
  enabled: boolean;
  mode: "webhook" | "polling";
  botToken: string;
  dmPolicy: "allowlist" | "open" | "disabled";
  allowFromText: string;
  groupPolicy: "allowlist" | "open" | "disabled";
  groupsText: string;
  requireMentionInGroups: boolean;
  defaultProjectId: string;
  groupProjectRoutesText: string;
  webhookSecret: string;
  webhookUrl: string;
};

function draftFromView(view: TelegramGatewayView): Draft {
  return {
    enabled: view.enabled,
    mode: view.mode,
    botToken: "",
    dmPolicy: view.dmPolicy,
    allowFromText: view.allowFrom.join("\n"),
    groupPolicy: view.groupPolicy,
    groupsText: view.groups.join("\n"),
    requireMentionInGroups: view.requireMentionInGroups,
    defaultProjectId: view.defaultProjectId,
    groupProjectRoutesText: formatGroupProjectRoutes(view.groupProjectRoutes),
    webhookSecret: "",
    webhookUrl: view.webhookUrl ?? "",
  };
}

function parseLines(value: string) {
  return value
    .split(/\r?\n/)
    .map((item) => item.trim())
    .filter(Boolean);
}

function formatGroupProjectRoutes(routes: TelegramGatewayView["groupProjectRoutes"]) {
  return routes
    .map((route) => {
      const chatPart = route.threadId != null ? `${route.chatId}#${route.threadId}` : route.chatId;
      return [chatPart, route.projectId, route.label].filter(Boolean).join(" ");
    })
    .join("\n");
}

function parseGroupProjectRoutes(value: string) {
  return parseLines(value)
    .map((line) => {
      const [chatAndTopic, projectId, ...labelParts] = line.split(/\s+/);
      if (!chatAndTopic || !projectId) {
        return null;
      }
      const [chatId, threadIdRaw] = chatAndTopic.split("#");
      const threadId = Number(threadIdRaw);
      return {
        chatId,
        ...(threadIdRaw && Number.isFinite(threadId) ? { threadId } : {}),
        projectId,
        ...(labelParts.length > 0 ? { label: labelParts.join(" ") } : {}),
      };
    })
    .filter((route): route is { chatId: string; threadId?: number; projectId: string; label?: string } =>
      Boolean(route?.chatId && route.projectId),
    );
}

function SectionTitle({ title, note }: { title: string; note?: string }) {
  return (
    <div>
      <div className="text-[16px] font-semibold text-[#111111]">{title}</div>
      {note ? <div className="mt-1 text-[12px] leading-5 text-[#8C8C8C]">{note}</div> : null}
    </div>
  );
}

function TextField({
  label,
  value,
  onChange,
  placeholder,
  secret = false,
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  secret?: boolean;
}) {
  return (
    <label className="block space-y-1.5">
      <div className="text-[12px] font-medium text-[#57606A]">{label}</div>
      <input
        type={secret ? "password" : "text"}
        value={value}
        onChange={(event) => onChange(event.target.value)}
        placeholder={placeholder}
        className="w-full rounded-2xl border border-[#E5E5EA] bg-[#F7F8FA] px-4 py-3 text-[14px] text-[#111111] outline-none transition focus:border-[#07C160] focus:bg-white"
      />
    </label>
  );
}

function TextAreaField({
  label,
  value,
  onChange,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
}) {
  return (
    <label className="block space-y-1.5">
      <div className="text-[12px] font-medium text-[#57606A]">{label}</div>
      <textarea
        value={value}
        onChange={(event) => onChange(event.target.value)}
        placeholder={placeholder}
        rows={4}
        className="w-full rounded-2xl border border-[#E5E5EA] bg-[#F7F8FA] px-4 py-3 text-[14px] leading-6 text-[#111111] outline-none transition focus:border-[#07C160] focus:bg-white"
      />
    </label>
  );
}

function TogglePill({
  active,
  label,
  onClick,
}: {
  active: boolean;
  label: string;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={clsx(
        "rounded-full px-4 py-2 text-[13px] font-semibold transition",
        active ? "bg-[#07C160] text-white" : "bg-[#F5F5F7] text-[#57606A]",
      )}
    >
      {label}
    </button>
  );
}

export function TelegramIntegrationClient({ initialView }: { initialView: TelegramGatewayView }) {
  const router = useRouter();
  const [view, setView] = useState(initialView);
  const [draft, setDraft] = useState(() => draftFromView(initialView));
  const [busy, setBusy] = useState<null | "save" | "test">(null);
  const [message, setMessage] = useState("");

  const webhookPath = useMemo(() => "/api/v1/integrations/telegram/webhook", []);

  async function submit(kind: "save" | "test") {
    setBusy(kind);
    setMessage("");
    try {
      const response = await fetch("/api/v1/integrations/telegram", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          enabled: draft.enabled,
          mode: draft.mode,
          botToken: draft.botToken.trim() || undefined,
          dmPolicy: draft.dmPolicy,
          allowFrom: parseLines(draft.allowFromText),
          groupPolicy: draft.groupPolicy,
          groups: parseLines(draft.groupsText),
          requireMentionInGroups: draft.requireMentionInGroups,
          defaultProjectId: draft.defaultProjectId.trim() || "master-agent",
          groupProjectRoutes: parseGroupProjectRoutes(draft.groupProjectRoutesText),
          webhookSecret: draft.webhookSecret.trim() || undefined,
          webhookUrl: draft.webhookUrl.trim() || undefined,
          testConnection: kind === "test",
        }),
      });
      const result = (await response.json()) as {
        ok: boolean;
        message?: string;
        telegram?: TelegramGatewayView;
        probe?: { ok: boolean; username?: string };
      };
      if (!response.ok || !result.ok || !result.telegram) {
        setMessage(result.message ?? "保存失败。");
        return;
      }
      const nextView = result.telegram;
      setView(nextView);
      setDraft((current) => ({
        ...draftFromView(nextView),
        botToken: "",
        webhookSecret: "",
        webhookUrl: current.webhookUrl,
      }));
      setMessage(
        kind === "test"
          ? `连接测试通过${result.probe?.username ? `，当前 bot：@${result.probe.username}` : ""}。`
          : "Telegram 配置已保存。",
      );
      router.refresh();
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "请求失败。");
    } finally {
      setBusy(null);
    }
  }

  return (
    <div className="space-y-3 px-[18px] pb-6">
      <div className="rounded-2xl border border-[#E5E5EA] bg-white px-4 py-4">
        <SectionTitle title="当前状态" note="当前这里只管理 Boss 作为 Telegram Bot 的接入能力。" />
        <div className="mt-3 space-y-2 text-[13px] leading-6 text-[#57606A]">
          <div>
            开关状态：<span className="font-semibold text-[#111111]">{view.enabled ? "已开启" : "已关闭"}</span>
          </div>
          <div>
            接入模式：<span className="font-semibold text-[#111111]">{view.mode === "webhook" ? "Webhook" : "Polling"}</span>
          </div>
          <div>
            Bot Token：<span className="font-semibold text-[#111111]">{view.botTokenConfigured ? "已配置" : "未配置"}</span>
          </div>
          <div>
            Webhook Secret：
            <span className="font-semibold text-[#111111]">
              {view.webhookSecretConfigured ? " 已配置" : " 未配置"}
            </span>
          </div>
          <div>
            默认项目：<span className="font-semibold text-[#111111]">{view.defaultProjectId}</span>
          </div>
          <div>
            已处理 update：<span className="font-semibold text-[#111111]">{view.processedUpdateCount}</span>
          </div>
          {view.botUsername ? (
            <div>
              当前 bot：<span className="font-semibold text-[#111111]">@{view.botUsername}</span>
            </div>
          ) : null}
        </div>
      </div>

      <div className="rounded-2xl border border-[#E5E5EA] bg-white px-4 py-4">
        <SectionTitle title="接入开关" note="这里控制 Telegram 是否真正接受消息。" />
        <div className="mt-3 flex flex-wrap gap-2">
          <TogglePill
            active={draft.enabled}
            label="开启接入"
            onClick={() => setDraft((current) => ({ ...current, enabled: true }))}
          />
          <TogglePill
            active={!draft.enabled}
            label="关闭接入"
            onClick={() => setDraft((current) => ({ ...current, enabled: false }))}
          />
        </div>
      </div>

      <div className="rounded-2xl border border-[#E5E5EA] bg-white px-4 py-4">
        <SectionTitle title="Bot 配置" note="Token 和 Secret 留空时会沿用已保存值，不会被清掉。" />
        <div className="mt-3 space-y-3">
          <div className="flex flex-wrap gap-2">
            <TogglePill
              active={draft.mode === "webhook"}
              label="Webhook"
              onClick={() => setDraft((current) => ({ ...current, mode: "webhook" }))}
            />
            <TogglePill
              active={draft.mode === "polling"}
              label="Polling"
              onClick={() => setDraft((current) => ({ ...current, mode: "polling" }))}
            />
          </div>
          <TextField
            label="Bot Token"
            value={draft.botToken}
            onChange={(value) => setDraft((current) => ({ ...current, botToken: value }))}
            placeholder={view.botTokenConfigured ? "已配置，留空表示沿用当前 token" : "输入 Telegram Bot Token"}
            secret
          />
          <TextField
            label="Webhook Secret"
            value={draft.webhookSecret}
            onChange={(value) => setDraft((current) => ({ ...current, webhookSecret: value }))}
            placeholder={
              view.webhookSecretConfigured ? "已配置，留空表示沿用当前 secret" : "建议配置一个 webhook secret"
            }
            secret
          />
          <TextField
            label="Webhook URL（可选）"
            value={draft.webhookUrl}
            onChange={(value) => setDraft((current) => ({ ...current, webhookUrl: value }))}
            placeholder="例如 https://boss.hyzq.net/api/v1/integrations/telegram/webhook"
          />
          <TextField
            label="默认路由项目"
            value={draft.defaultProjectId}
            onChange={(value) => setDraft((current) => ({ ...current, defaultProjectId: value }))}
            placeholder="默认 master-agent"
          />
          <div className="rounded-2xl bg-[#F7F8FA] px-4 py-3 text-[12px] leading-6 text-[#57606A]">
            当前 webhook 路径：<span className="font-semibold text-[#111111]">{webhookPath}</span>
            <br />
            建议把公开 URL 配成：`域名 + {webhookPath}`。
          </div>
        </div>
      </div>

      <div className="rounded-2xl border border-[#E5E5EA] bg-white px-4 py-4">
        <SectionTitle title="访问控制" note="支持私聊 allowlist 和群白名单，默认优先安全。" />
        <div className="mt-3 space-y-3">
          <div>
            <div className="mb-2 text-[12px] font-medium text-[#57606A]">私聊策略</div>
            <div className="flex flex-wrap gap-2">
              <TogglePill
                active={draft.dmPolicy === "allowlist"}
                label="Allowlist"
                onClick={() => setDraft((current) => ({ ...current, dmPolicy: "allowlist" }))}
              />
              <TogglePill
                active={draft.dmPolicy === "open"}
                label="开放"
                onClick={() => setDraft((current) => ({ ...current, dmPolicy: "open" }))}
              />
              <TogglePill
                active={draft.dmPolicy === "disabled"}
                label="关闭"
                onClick={() => setDraft((current) => ({ ...current, dmPolicy: "disabled" }))}
              />
            </div>
          </div>

          <TextAreaField
            label="允许私聊的 Telegram 用户 ID（每行一个）"
            value={draft.allowFromText}
            onChange={(value) => setDraft((current) => ({ ...current, allowFromText: value }))}
            placeholder={"123456789\n987654321"}
          />

          <div>
            <div className="mb-2 text-[12px] font-medium text-[#57606A]">群聊策略</div>
            <div className="flex flex-wrap gap-2">
              <TogglePill
                active={draft.groupPolicy === "allowlist"}
                label="白名单"
                onClick={() => setDraft((current) => ({ ...current, groupPolicy: "allowlist" }))}
              />
              <TogglePill
                active={draft.groupPolicy === "open"}
                label="开放"
                onClick={() => setDraft((current) => ({ ...current, groupPolicy: "open" }))}
              />
              <TogglePill
                active={draft.groupPolicy === "disabled"}
                label="关闭"
                onClick={() => setDraft((current) => ({ ...current, groupPolicy: "disabled" }))}
              />
            </div>
          </div>

          <TextAreaField
            label="允许的群 chat ID（每行一个）"
            value={draft.groupsText}
            onChange={(value) => setDraft((current) => ({ ...current, groupsText: value }))}
            placeholder={"-1001234567890\n-1009876543210"}
          />

          <TextAreaField
            label="群 / Topic 路由到 Boss 项目"
            value={draft.groupProjectRoutesText}
            onChange={(value) => setDraft((current) => ({ ...current, groupProjectRoutesText: value }))}
            placeholder={"-1001234567890 audit-collab 审计群\n-1001234567890#12 master-agent 主控 Topic"}
          />
          <div className="rounded-2xl bg-[#F7F8FA] px-4 py-3 text-[12px] leading-6 text-[#57606A]">
            每行格式：<span className="font-semibold text-[#111111]">chatId[#topicId] projectId 可选备注</span>。
            未命中路由时会回到默认项目。
          </div>

          <div className="flex flex-wrap gap-2">
            <TogglePill
              active={draft.requireMentionInGroups}
              label="群聊需 @Bot"
              onClick={() => setDraft((current) => ({ ...current, requireMentionInGroups: true }))}
            />
            <TogglePill
              active={!draft.requireMentionInGroups}
              label="群聊免 @"
              onClick={() => setDraft((current) => ({ ...current, requireMentionInGroups: false }))}
            />
          </div>
          <div className="rounded-2xl bg-[#F7F8FA] px-4 py-3 text-[12px] leading-6 text-[#57606A]">
            开启后，群里只有 <span className="font-semibold text-[#111111]">@Bot</span> 或直接回复 Bot 上一条消息时，才会进入主 Agent。
          </div>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-3">
        <button
          type="button"
          disabled={busy !== null}
          onClick={() => void submit("test")}
          className="rounded-full border border-[#E5E5EA] bg-white px-4 py-3 text-[14px] font-semibold text-[#111111] disabled:opacity-60"
        >
          {busy === "test" ? "测试中" : "测试连接"}
        </button>
        <button
          type="button"
          disabled={busy !== null}
          onClick={() => void submit("save")}
          className="rounded-full bg-[#07C160] px-4 py-3 text-[14px] font-semibold text-white disabled:opacity-60"
        >
          {busy === "save" ? "保存中" : "保存配置"}
        </button>
      </div>

      {message ? (
        <div className="rounded-2xl bg-[#F7F8FA] px-4 py-3 text-[12px] leading-6 text-[#57606A]">
          {message}
        </div>
      ) : null}

      {view.lastError ? (
        <div className="rounded-2xl border border-[#FFD6D6] bg-[#FFF5F5] px-4 py-3 text-[12px] leading-6 text-[#B42318]">
          最近错误：{view.lastError}
        </div>
      ) : null}
    </div>
  );
}
