import { useEffect, useMemo, useState } from "react";
import {
  App as AntApp,
  Button,
  Card,
  Form,
  Input,
  Modal,
  Popconfirm,
  Select,
  Space,
  Table,
  Tag,
  Typography,
} from "antd";
import {
  EditOutlined,
  PlusOutlined,
  ReloadOutlined,
  DeleteOutlined,
  KeyOutlined,
  StopOutlined,
  CheckOutlined,
} from "@ant-design/icons";
import {
  AgentAccount,
  Role,
  Session,
  SyncBinding,
  SyncChannel,
  createAgent,
  deleteAgent,
  listAgents,
  listRoles,
  listSyncBindings,
  listSyncChannels,
  rotateAgentSecret,
  updateAgent,
} from "./api";
import { permLabel } from "./agentPerms";

type FormValues = {
  name: string;
  role_id: number;
  app_slugs: string[];
  channel_id?: string;
  online_db_id?: string;
  database_name?: string;
};

export function AgentUsersPage(props: {
  session: Session;
  busy: boolean;
  setBusy: (v: boolean) => void;
  setError: (v: string) => void;
  setInfo: (v: string) => void;
}) {
  const { session, busy, setBusy, setError, setInfo } = props;
  const { message, modal } = AntApp.useApp();
  const [agents, setAgents] = useState<AgentAccount[]>([]);
  const [roles, setRoles] = useState<Role[]>([]);
  const [channels, setChannels] = useState<SyncChannel[]>([]);
  const [bindings, setBindings] = useState<SyncBinding[]>([]);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [editing, setEditing] = useState<AgentAccount | null>(null);
  const [form] = Form.useForm<FormValues>();
  const roleId = Form.useWatch("role_id", form);

  const selectedRole = useMemo(
    () => roles.find((r) => r.role_id === roleId),
    [roles, roleId]
  );

  async function refresh() {
    setLoading(true);
    try {
      const [a, r, ch, bind] = await Promise.all([
        listAgents(session),
        listRoles(session),
        listSyncChannels(session).catch(() => ({ items: [] as SyncChannel[] })),
        listSyncBindings(session).catch(() => ({ items: [] as SyncBinding[] })),
      ]);
      setAgents(a.items || []);
      setRoles(r.items || []);
      setChannels(ch.items || []);
      setBindings(bind.items || []);
    } catch (e: any) {
      const msg = e.message || String(e);
      setError(msg);
      message.error(msg);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    refresh();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [session.accessToken]);

  function openCreate() {
    setEditing(null);
    const pref =
      roles.find((x) => x.code === "生成发布" || x.code === "publisher") ||
      roles.find((x) => x.code === "运维" || x.code === "operator") ||
      roles[0];
    form.resetFields();
    form.setFieldsValue({
      name: "",
      role_id: pref?.role_id,
      app_slugs: [],
      channel_id: undefined,
      online_db_id: undefined,
      database_name: undefined,
    });
    setOpen(true);
  }

  function openEdit(a: AgentAccount) {
    setEditing(a);
    form.setFieldsValue({
      name: a.name || "",
      role_id: a.role_id || undefined,
      app_slugs: a.app_slugs || [],
      channel_id: a.channel_id || undefined,
      online_db_id: a.online_db_id || undefined,
      database_name: a.database_name || undefined,
    });
    setOpen(true);
  }

  async function onSubmit(activate = false) {
    const values = await form.validateFields();
    setBusy(true);
    try {
      const bindBody = {
        channel_id: values.channel_id || "",
        online_db_id: values.online_db_id || "",
        database_name: (values.database_name || "").trim() || "",
      };
      if (!editing) {
        const res = await createAgent(session, {
          name: values.name.trim(),
          role_id: values.role_id,
          app_slugs: values.app_slugs || [],
          ...bindBody,
        });
        modal.success({
          title: "用户已创建",
          content: (
            <div>
              <p>请立即保存 client_secret（只显示一次）：</p>
              <Typography.Paragraph copyable code>
                {res.client_secret}
              </Typography.Paragraph>
            </div>
          ),
        });
        setInfo(`已创建用户「${values.name.trim()}」`);
      } else {
        await updateAgent(session, editing.agent_id, {
          name: values.name.trim(),
          role_id: values.role_id,
          app_slugs: values.app_slugs || [],
          ...bindBody,
          ...(activate ? { status: "active" } : {}),
        });
        message.success(activate ? "已保存并启用" : "已保存");
        setInfo(activate ? `已保存并启用「${values.name.trim()}」` : `已保存「${values.name.trim()}」`);
      }
      setOpen(false);
      await refresh();
    } catch (e: any) {
      const msg = e.message || String(e);
      setError(msg);
      message.error(msg);
    } finally {
      setBusy(false);
    }
  }

  const statusTag = (s: string, r?: AgentAccount) => {
    if (s === "active") {
      const syncBound = !!(r?.channel_id && r?.online_db_id);
      return (
        <Space size={4}>
          <Tag color="success">active</Tag>
          {syncBound ? <Tag color="blue">同步已绑</Tag> : null}
        </Space>
      );
    }
    if (s === "pending") return <Tag color="warning">pending · 仅登记</Tag>;
    return <Tag>{s}</Tag>;
  };

  return (
    <Card
      title="用户管理"
      extra={
        <Space>
          <Button icon={<ReloadOutlined />} onClick={refresh} loading={loading}>
            刷新
          </Button>
          <Button type="primary" icon={<PlusOutlined />} onClick={openCreate} disabled={!roles.length}>
            新建用户
          </Button>
        </Space>
      }
    >
      <Typography.Paragraph type="secondary" style={{ marginTop: 0 }}>
        当前租户 #{session.tenantId}。用户挂在本租户下；同角色跨公司靠租户隔离，不靠再拆一套角色。
        角色请在「角色管理」中维护。可绑定<strong>同步通道 / 线上库</strong>：该智能体发布的模块与松离线数据进同一目标库（Z8）。
      </Typography.Paragraph>

      <Table
        rowKey="agent_id"
        loading={loading || busy}
        dataSource={agents}
        pagination={{ pageSize: 10 }}
        columns={[
          {
            title: "用户名称",
            dataIndex: "name",
            render: (v, r) => (
              <div>
                <strong>{v || "—"}</strong>
                {r.host_key ? (
                  <div>
                    <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                      host: {r.host_key}
                    </Typography.Text>
                  </div>
                ) : null}
              </div>
            ),
          },
          {
            title: "client_id",
            dataIndex: "client_id",
            render: (v) => <Typography.Text code>{v}</Typography.Text>,
          },
          { title: "状态", dataIndex: "status", width: 160, render: (s: string, r: AgentAccount) => statusTag(s, r) },
          {
            title: "角色",
            render: (_, r) => r.role_name || r.role_code || "—",
          },
          {
            title: "权限",
            dataIndex: "permissions",
            width: 260,
            render: (permissions: string[]) =>
              (permissions || []).length ? (
                <Space size={[4, 4]} wrap>
                  {(permissions || []).map((p) => (
                    <Tag key={p} color={["读取模块", "发布模块", "数据同步"].includes(permLabel(p)) ? "blue" : undefined}>
                      {permLabel(p)}
                    </Tag>
                  ))}
                </Space>
              ) : (
                <Typography.Text type="secondary">未授权</Typography.Text>
              ),
          },
          {
            title: "可访问模块",
            dataIndex: "app_slugs",
            render: (slugs: string[]) =>
              (slugs || []).length ? (
                <Space size={[4, 4]} wrap>
                  {(slugs || []).map((s) => (
                    <Tag key={s}>{s}</Tag>
                  ))}
                </Space>
              ) : (
                "—"
              ),
          },
          {
            title: "同步绑定",
            render: (_: unknown, r: AgentAccount) => {
              if (!r.channel_id && !r.online_db_id && !r.database_name) return "—";
              const ch = channels.find((c) => c.id === r.channel_id);
              return (
                <span style={{ fontSize: 12 }}>
                  {ch?.name || r.channel_id || "无通道"}
                  <br />
                  <Typography.Text type="secondary">
                    {r.online_db_id || "—"}
                    {r.database_name ? ` · ${r.database_name}` : ""}
                  </Typography.Text>
                </span>
              );
            },
          },
          {
            title: "操作",
            width: 320,
            render: (_, a) => (
              <Space wrap>
                <Button size="small" icon={<EditOutlined />} onClick={() => openEdit(a)}>
                  编辑
                </Button>
                <Button
                  size="small"
                  icon={a.status === "active" ? <StopOutlined /> : <CheckOutlined />}
                  onClick={async () => {
                    const next = a.status === "active" ? "disabled" : "active";
                    if (next === "active" && !a.role_id && !(a.permissions || []).length) {
                      message.warning("请先编辑并分配角色后再启用");
                      return;
                    }
                    setBusy(true);
                    try {
                      await updateAgent(session, a.agent_id, { status: next });
                      message.success(`已设为 ${next}`);
                      setInfo(`已将「${a.name}」设为 ${next}`);
                      await refresh();
                    } catch (e: any) {
                      message.error(e.message || String(e));
                      setError(e.message || String(e));
                    } finally {
                      setBusy(false);
                    }
                  }}
                >
                  {a.status === "active" ? "停用" : "启用"}
                </Button>
                <Button
                  size="small"
                  icon={<KeyOutlined />}
                  onClick={async () => {
                    setBusy(true);
                    try {
                      const res = await rotateAgentSecret(session, a.agent_id);
                      modal.success({
                        title: "密钥已轮换",
                        content: (
                          <Typography.Paragraph copyable code>
                            {res.client_secret}
                          </Typography.Paragraph>
                        ),
                      });
                      setInfo(`已轮换「${a.name}」的 secret`);
                    } catch (e: any) {
                      message.error(e.message || String(e));
                      setError(e.message || String(e));
                    } finally {
                      setBusy(false);
                    }
                  }}
                >
                  轮换密钥
                </Button>
                <Popconfirm
                  title={`删除用户「${a.name}」？`}
                  onConfirm={async () => {
                    setBusy(true);
                    try {
                      await deleteAgent(session, a.agent_id);
                      message.success("已删除");
                      setInfo(`已删除「${a.name}」`);
                      await refresh();
                    } catch (e: any) {
                      message.error(e.message || String(e));
                      setError(e.message || String(e));
                    } finally {
                      setBusy(false);
                    }
                  }}
                >
                  <Button size="small" danger icon={<DeleteOutlined />}>
                    删除
                  </Button>
                </Popconfirm>
              </Space>
            ),
          },
        ]}
      />

      <Modal
        title={editing ? `编辑用户 #${editing.agent_id}` : "新建用户"}
        open={open}
        onCancel={() => setOpen(false)}
        confirmLoading={busy}
        width={640}
        destroyOnClose
        footer={[
          <Button key="cancel" onClick={() => setOpen(false)}>
            取消
          </Button>,
          editing ? (
            <Button key="activate" onClick={() => onSubmit(true)} loading={busy}>
              保存并启用
            </Button>
          ) : null,
          <Button key="ok" type="primary" onClick={() => onSubmit(false)} loading={busy}>
            {editing ? "保存修改" : "创建用户"}
          </Button>,
        ]}
      >
        <Form form={form} layout="vertical" style={{ marginTop: 12 }}>
          <Form.Item label="用户名称" name="name" rules={[{ required: true, message: "请填写名称" }]}>
            <Input placeholder="例如：产线宿主 A" />
          </Form.Item>
          <Form.Item label="角色" name="role_id" rules={[{ required: true, message: "请选择角色" }]}>
            <Select
              placeholder="请选择角色"
              options={roles.map((r) => ({
                value: r.role_id,
                label: `${r.name}（${r.code}）`,
              }))}
            />
          </Form.Item>
          {selectedRole && (
            <Card size="small" title="角色权限预览" style={{ marginBottom: 16 }}>
              <Space size={[4, 4]} wrap>
                {(selectedRole.permissions || []).map((p) => (
                  <Tag key={p}>{permLabel(p)}</Tag>
                ))}
              </Space>
            </Card>
          )}
          <Form.Item
            label="可访问模块（可选）"
            name="app_slugs"
            extra="留空=可自由发布任意自建模块，无需再逐个授权。仅当需要限制范围时再填写白名单（或 * 表示全部）。"
          >
            <Select
              mode="tags"
              placeholder="可选限制：输入 slug 后回车；留空表示不限制"
              tokenSeparators={[","]}
              allowClear
            />
          </Form.Item>
          <Typography.Text strong>松离线 / 模块落库（Z8）</Typography.Text>
          <Form.Item
            name="channel_id"
            label="同步通道"
            style={{ marginTop: 8 }}
            extra="该智能体的模块与本机 sync 应对准同一通道线上库"
          >
            <Select
              allowClear
              showSearch
              optionFilterProp="label"
              placeholder="可选"
              options={channels.map((c) => ({
                value: c.id,
                label: `${c.name} (${c.id.slice(0, 8)}…)`,
              }))}
              onChange={(cid?: string) => {
                if (!cid) return;
                const b = bindings.find((x) => x.channel_id === cid);
                if (b) {
                  form.setFieldsValue({
                    online_db_id: b.online_db_id,
                    database_name: b.display_name || b.database_name || form.getFieldValue("database_name"),
                  });
                }
              }}
            />
          </Form.Item>
          <Form.Item
            name="online_db_id"
            label="线上库 ID"
            extra="与 Binding.online_db_id 对齐；宇恒 push 须带此 id。可选从 Binding 带出。"
          >
            <Input placeholder="online_db_id" allowClear list="agent-online-db-options" />
          </Form.Item>
          <datalist id="agent-online-db-options">
            {[...new Set(bindings.map((b) => b.online_db_id).filter(Boolean))].map((id) => (
              <option key={id} value={id} />
            ))}
          </datalist>
          <Form.Item
            name="database_name"
            label="模块落库名"
            extra="智能体新建发布时优先写入此 Postgres 库（database_per_app）；与通道 remote 对齐为佳"
          >
            <Input placeholder="例如 appdb_t1_aisite" allowClear />
          </Form.Item>
        </Form>
      </Modal>
    </Card>
  );
}
