import { useCallback, useEffect, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import {
  getWechatCursorExecutorConfig,
  getWechatCursorExecutorRuntime,
  listAdminUsers,
  patchWechatCursorExecutorConfig,
} from '../../api/client';
import type {
  AdminUserRow,
  WechatCursorExecutorAdminConfig,
  WechatCursorExecutorRuntimeState,
} from '../../types';
import { formatTime } from '../utils/format';

type CursorChannelForm = {
  enabled: boolean;
  h5Enabled: boolean;
  wechatEnabled: boolean;
  selectedUserIds: string[];
  manualAllowlistEntries: string[];
  intentAllowlist: string;
  fallbackToDeepseek: boolean;
};

const USER_ID_PATTERN =
  /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

function userMatchesAllowlistToken(user: AdminUserRow, token: string) {
  const normalized = token.trim().toLowerCase();
  if (!normalized) return false;
  const identities = [user.id, user.username, user.slug, user.publishSlug, user.displayName]
    .map((value) => String(value ?? '').trim().toLowerCase())
    .filter(Boolean);
  return identities.includes(normalized);
}

function resolveAllowlistTokens(tokens: string[], users: AdminUserRow[]) {
  const selectedUserIds: string[] = [];
  const manualAllowlistEntries: string[] = [];
  const seenIds = new Set<string>();

  for (const rawToken of tokens) {
    const token = String(rawToken ?? '').trim();
    if (!token) continue;
    const matchedUser = users.find((user) => userMatchesAllowlistToken(user, token));
    if (matchedUser) {
      if (!seenIds.has(matchedUser.id)) {
        seenIds.add(matchedUser.id);
        selectedUserIds.push(matchedUser.id);
      }
      continue;
    }
    if (USER_ID_PATTERN.test(token)) {
      if (!seenIds.has(token)) {
        seenIds.add(token);
        selectedUserIds.push(token);
      }
      continue;
    }
    manualAllowlistEntries.push(token);
  }

  return { selectedUserIds, manualAllowlistEntries };
}

function configToForm(
  config: WechatCursorExecutorAdminConfig | undefined,
  users: AdminUserRow[] = [],
): CursorChannelForm {
  const tokens = Array.isArray(config?.userAllowlist) ? config.userAllowlist : [];
  const channels = Array.isArray(config?.channelAllowlist) ? config.channelAllowlist : ['h5', 'wechat_mp'];
  const { selectedUserIds, manualAllowlistEntries } = resolveAllowlistTokens(tokens, users);
  return {
    enabled: Boolean(config?.enabled),
    h5Enabled: channels.includes('h5'),
    wechatEnabled: channels.includes('wechat_mp'),
    selectedUserIds,
    manualAllowlistEntries,
    intentAllowlist: Array.isArray(config?.intentAllowlist)
      ? config.intentAllowlist.join('\n')
      : 'page.generate',
    fallbackToDeepseek: config?.fallbackToDeepseek !== false,
  };
}

function formToAllowlist(form: CursorChannelForm) {
  const manual = form.manualAllowlistEntries.map((item) => item.trim()).filter(Boolean);
  return [...new Set([...form.selectedUserIds, ...manual])];
}

function formToChannelAllowlist(form: CursorChannelForm) {
  const channels: string[] = [];
  if (form.h5Enabled) channels.push('h5');
  if (form.wechatEnabled) channels.push('wechat_mp');
  return channels;
}

function CursorAllowlistPickerModal({
  open,
  users,
  selectedUserIds,
  busy,
  onClose,
  onConfirm,
}: {
  open: boolean;
  users: AdminUserRow[];
  selectedUserIds: string[];
  busy?: boolean;
  onClose: () => void;
  onConfirm: (nextIds: string[]) => void;
}) {
  const [search, setSearch] = useState('');
  const [draftIds, setDraftIds] = useState<string[]>(selectedUserIds);
  const [pickerUsers, setPickerUsers] = useState<AdminUserRow[]>(users);
  const [loadingUsers, setLoadingUsers] = useState(false);

  useEffect(() => {
    if (!open) return;
    setDraftIds(selectedUserIds);
    setSearch('');
    setPickerUsers(users);
  }, [open, selectedUserIds, users]);

  useEffect(() => {
    if (!open) return;
    const timer = window.setTimeout(() => {
      void (async () => {
        setLoadingUsers(true);
        try {
          const result = await listAdminUsers({
            page: 1,
            pageSize: 500,
            status: 'active',
            search: search.trim() || undefined,
          });
          setPickerUsers(result.items);
        } catch {
          setPickerUsers(users);
        } finally {
          setLoadingUsers(false);
        }
      })();
    }, search.trim() ? 250 : 0);
    return () => window.clearTimeout(timer);
  }, [open, search, users]);

  if (!open) return null;

  const visibleIds = pickerUsers.map((user) => user.id);
  const allVisibleSelected =
    visibleIds.length > 0 && visibleIds.every((id) => draftIds.includes(id));

  return (
    <div
      className="modal-backdrop"
      role="presentation"
      onMouseDown={(event) => {
        if (event.target === event.currentTarget) onClose();
      }}
    >
      <div
        className="modal-box"
        role="dialog"
        aria-modal="true"
        aria-labelledby="cursor-allowlist-picker-title"
        style={{ maxWidth: 720, width: 'min(720px, calc(100vw - 32px))' }}
        onMouseDown={(event) => event.stopPropagation()}
      >
        <div className="modal-head">
          <div>
            <h3 id="cursor-allowlist-picker-title">选择体验通道用户</h3>
            <p className="muted" style={{ margin: '6px 0 0', fontSize: 13 }}>
              仅勾选用户会进入 TKMind 智趣独立通道；其余用户完全不受影响，仍走原有 DeepSeek/Goose 链路。
            </p>
          </div>
          <button type="button" className="modal-close" onClick={onClose} aria-label="关闭">
            ×
          </button>
        </div>

        <div className="wechat-toolbar" style={{ marginBottom: 12 }}>
          <input
            value={search}
            onChange={(event) => setSearch(event.target.value)}
            placeholder="搜索用户名、昵称或 userId"
            style={{ flex: 1, minWidth: 220 }}
            autoFocus
          />
          <button
            type="button"
            className="ghost-btn"
            disabled={loadingUsers || pickerUsers.length === 0}
            onClick={() => {
              setDraftIds((current) => {
                if (allVisibleSelected) {
                  return current.filter((id) => !visibleIds.includes(id));
                }
                return [...new Set([...current, ...visibleIds])];
              });
            }}
          >
            {allVisibleSelected ? '取消全选当前列表' : '全选当前列表'}
          </button>
        </div>

        <div className="cursor-allowlist-picker-list">
          {loadingUsers ? <p className="muted">加载用户…</p> : null}
          {!loadingUsers && pickerUsers.length === 0 ? (
            <p className="muted">没有匹配的用户</p>
          ) : null}
          {pickerUsers.map((user) => (
            <label key={user.id} className="cursor-allowlist-picker-row">
              <input
                type="checkbox"
                checked={draftIds.includes(user.id)}
                onChange={() => {
                  setDraftIds((current) =>
                    current.includes(user.id)
                      ? current.filter((id) => id !== user.id)
                      : [...current, user.id],
                  );
                }}
              />
              <span>
                {user.displayName || user.username}
                <span className="muted"> @{user.username}</span>
              </span>
            </label>
          ))}
        </div>

        <div className="modal-actions">
          <button type="button" className="ghost-btn" onClick={onClose} disabled={busy}>
            取消
          </button>
          <button
            type="button"
            className="primary-btn"
            disabled={busy}
            onClick={() => onConfirm(draftIds)}
          >
            确认选择 ({draftIds.length})
          </button>
        </div>
      </div>
    </div>
  );
}

export function CursorChannelPage() {
  const [users, setUsers] = useState<AdminUserRow[]>([]);
  const [form, setForm] = useState<CursorChannelForm | null>(null);
  const [savedForm, setSavedForm] = useState<CursorChannelForm | null>(null);
  const [runtime, setRuntime] = useState<WechatCursorExecutorRuntimeState | null>(null);
  const [pickerOpen, setPickerOpen] = useState(false);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [notice, setNotice] = useState<string | null>(null);

  const dirty = useMemo(() => {
    if (!form || !savedForm) return false;
    return JSON.stringify(form) !== JSON.stringify(savedForm);
  }, [form, savedForm]);

  const selectedUsers = useMemo(() => {
    if (!form) return [];
    const byId = new Map(users.map((user) => [user.id, user]));
    return form.selectedUserIds.map((userId) => ({
      userId,
      user: byId.get(userId) ?? null,
    }));
  }, [form, users]);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const [nextUsers, nextConfig, nextRuntime] = await Promise.all([
        listAdminUsers({ page: 1, pageSize: 200, status: 'active' }),
        getWechatCursorExecutorConfig().catch(() => null),
        getWechatCursorExecutorRuntime().catch(() => null),
      ]);
      setUsers(nextUsers.items);
      const nextForm = configToForm(nextConfig?.config, nextUsers.items);
      setForm(nextForm);
      setSavedForm(nextForm);
      setRuntime(nextRuntime);
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载失败');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void load();
  }, [load]);

  const handleSave = async () => {
    if (!form) return;
    setSaving(true);
    setError(null);
    setNotice(null);
    try {
      const channelAllowlist = formToChannelAllowlist(form);
      if (form.enabled && channelAllowlist.length === 0) {
        throw new Error('启用体验通道时，至少选择一个接入渠道（H5 或服务号）');
      }
      if (form.enabled && formToAllowlist(form).length === 0) {
        throw new Error('启用体验通道时，至少选择一名白名单用户');
      }
      const result = await patchWechatCursorExecutorConfig({
        enabled: form.enabled,
        userAllowlist: formToAllowlist(form),
        channelAllowlist,
        intentAllowlist: form.intentAllowlist
          .split(/[\s,]+/u)
          .map((item) => item.trim())
          .filter(Boolean),
        fallbackToDeepseek: form.fallbackToDeepseek,
      });
      const nextForm = configToForm(result.config, users);
      setForm(nextForm);
      setSavedForm(nextForm);
      setRuntime(await getWechatCursorExecutorRuntime().catch(() => null));
      setNotice('TKMind 智趣体验通道已保存。未在白名单内的用户不受影响。');
    } catch (err) {
      setError(err instanceof Error ? err.message : '保存失败');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="admin-page">
      <div className="admin-page-head">
        <h2>TKMind 智趣体验通道</h2>
        <p className="muted">
          独立于现有 DeepSeek/Goose 链路的 Cursor 执行通道。仅对白名单用户生效，支持 H5 与服务号；其余用户完全不受影响。
        </p>
      </div>

      {error && <p className="banner banner-error">{error}</p>}
      {notice && <p className="banner banner-info">{notice}</p>}

      <section className="admin-card">
        <h3>通道说明</h3>
        <ul className="muted" style={{ margin: '8px 0 0', paddingLeft: 20, lineHeight: 1.7 }}>
          <li>
            <strong>H5</strong>：白名单用户在页面生成、问卷(Page Data)、Excel 分析等任务时，走 Cursor 独立执行。
          </li>
          <li>
            <strong>服务号</strong>：白名单用户在指定意图（默认 page.generate）下走 Cursor；其余意图仍走原有链路。
          </li>
          <li>非白名单用户：H5 与服务号均保持原有 DeepSeek/Goose 行为，不会被 Cursor 路由影响。</li>
        </ul>
        <p className="muted" style={{ marginTop: 12 }}>
          服务端需开启 <code>MEMIND_CURSOR_EXECUTOR_ENABLED=1</code> 与 Tool Gateway；详见 Memind{' '}
          <code>.env.example</code>。
        </p>
      </section>

      {form ? (
        <section className="admin-card">
          <div className="admin-card-head">
            <div>
              <h2>通道配置</h2>
              <p className="muted" style={{ marginTop: 6 }}>
                默认关闭。开启后仅白名单用户进入智趣通道，不影响其他用户。
              </p>
            </div>
            <button
              type="button"
              className="ghost-btn"
              onClick={() => void handleSave()}
              disabled={loading || saving || !dirty}
            >
              {saving ? '保存中…' : dirty ? '保存配置' : '已保存'}
            </button>
          </div>

          <div className="admin-form" style={{ marginTop: 16 }}>
            <label>
              <input
                type="checkbox"
                checked={form.enabled}
                disabled={loading || saving}
                onChange={(event) =>
                  setForm((current) => current && { ...current, enabled: event.target.checked })
                }
              />{' '}
              启用智趣体验通道
            </label>
            <fieldset style={{ border: 'none', padding: 0, margin: '12px 0' }}>
              <legend className="muted" style={{ marginBottom: 8 }}>
                接入渠道
              </legend>
              <label style={{ display: 'block', marginBottom: 8 }}>
                <input
                  type="checkbox"
                  checked={form.h5Enabled}
                  disabled={loading || saving}
                  onChange={(event) =>
                    setForm((current) => current && { ...current, h5Enabled: event.target.checked })
                  }
                />{' '}
                H5 聊天
              </label>
              <label style={{ display: 'block' }}>
                <input
                  type="checkbox"
                  checked={form.wechatEnabled}
                  disabled={loading || saving}
                  onChange={(event) =>
                    setForm((current) => current && { ...current, wechatEnabled: event.target.checked })
                  }
                />{' '}
                微信服务号
              </label>
            </fieldset>
            <label>
              <input
                type="checkbox"
                checked={form.fallbackToDeepseek}
                disabled={loading || saving}
                onChange={(event) =>
                  setForm((current) =>
                    current && { ...current, fallbackToDeepseek: event.target.checked },
                  )
                }
              />{' '}
              Cursor 失败时自动回退 DeepSeek
            </label>
            <label>
              体验用户白名单
              <div className="wechat-toolbar" style={{ marginTop: 8, marginBottom: 8 }}>
                <button
                  type="button"
                  className="ghost-btn"
                  disabled={loading || saving}
                  onClick={() => setPickerOpen(true)}
                >
                  从用户列表选择…
                </button>
                {form.selectedUserIds.length > 0 ? (
                  <button
                    type="button"
                    className="ghost-btn"
                    disabled={loading || saving}
                    onClick={() =>
                      setForm((current) => current && { ...current, selectedUserIds: [] })
                    }
                  >
                    清空已选
                  </button>
                ) : null}
              </div>
              {selectedUsers.length > 0 ? (
                <div className="cursor-allowlist-chips">
                  {selectedUsers.map(({ userId, user }) => (
                    <span key={userId} className="cursor-allowlist-chip">
                      <span>
                        {user ? user.displayName || user.username : userId}
                        {user ? <span className="muted"> @{user.username}</span> : null}
                      </span>
                      <button
                        type="button"
                        className="cursor-allowlist-chip-remove"
                        aria-label="移出白名单"
                        disabled={loading || saving}
                        onClick={() =>
                          setForm((current) =>
                            current
                              ? {
                                  ...current,
                                  selectedUserIds: current.selectedUserIds.filter((id) => id !== userId),
                                }
                              : current,
                          )
                        }
                      >
                        ×
                      </button>
                    </span>
                  ))}
                </div>
              ) : (
                <p className="muted" style={{ margin: 0 }}>
                  尚未选择用户。可在 <Link to="/users">用户管理</Link> 中查找账号后在此勾选。
                </p>
              )}
            </label>
            <label>
              服务号启用意图（H5 不受此限制，默认 page.generate）
              <textarea
                value={form.intentAllowlist}
                disabled={loading || saving}
                rows={2}
                placeholder="page.generate"
                onChange={(event) =>
                  setForm((current) => current && { ...current, intentAllowlist: event.target.value })
                }
              />
            </label>
          </div>

          {runtime ? (
            <p className="muted" style={{ marginTop: 12 }}>
              运行时：{runtime.policy.enabled ? '已开启' : '已关闭'}
              {' · '}
              白名单 {runtime.policy.userAllowlist.length} 人
              {' · '}
              渠道 {(runtime.policy.channelAllowlist ?? []).join('、') || '无'}
              {' · '}
              来源 {runtime.source}
              {runtime.updatedAt ? ` · 更新 ${formatTime(runtime.updatedAt)}` : ''}
            </p>
          ) : null}
        </section>
      ) : null}

      {form ? (
        <CursorAllowlistPickerModal
          open={pickerOpen}
          users={users}
          selectedUserIds={form.selectedUserIds}
          busy={loading || saving}
          onClose={() => setPickerOpen(false)}
          onConfirm={(nextIds) => {
            setForm((current) => current && { ...current, selectedUserIds: nextIds });
            setPickerOpen(false);
          }}
        />
      ) : null}
    </div>
  );
}
