import { useEffect, useState, type CSSProperties, type ReactNode } from 'react';
import {
  cancelWechatDigest,
  createWechatWebNotification,
  clearWechatRoute,
  fetchAdminUsers,
  fetchWechatBindings,
  fetchWechatDeliveries,
  fetchWechatDigests,
  fetchWechatMessages,
  fetchWechatSummary,
  fetchWechatWebNotifications,
  resumeWechatDigest,
  type AdminUser,
  type WechatAdminSummary,
  type WechatBinding,
  type WechatDeliveryLog,
  type WechatDigestSubscription,
  type WechatMessage,
  type WechatWebNotification,
} from '../../api/admin';

function time(value?: number | null) {
  if (!value) return '—';
  return new Date(value).toLocaleString('zh-CN', { hour12: false });
}

function count(record: Record<string, number>, key: string) {
  return record[key] ?? 0;
}

function badge(status?: string | null) {
  if (!status) return <span style={{ color: '#68716c' }}>—</span>;
  const color =
    status === 'active' || status === 'success' || status === 'done'
      ? '#2f6f57'
      : status === 'failed'
        ? '#b42318'
        : '#68716c';
  return <strong style={{ color, fontSize: 12 }}>{status}</strong>;
}

function userName(row: { displayName?: string | null; username?: string | null }) {
  return row.displayName || row.username || '—';
}

const tableStyle = {
  width: '100%',
  borderCollapse: 'collapse',
  fontSize: 13,
} satisfies CSSProperties;

const thStyle = {
  textAlign: 'left',
  color: '#68716c',
  fontWeight: 600,
  borderBottom: '1px solid #e7dfd1',
  padding: '8px 6px',
  whiteSpace: 'nowrap',
} satisfies CSSProperties;

const tdStyle = {
  borderBottom: '1px solid #eee7da',
  padding: '9px 6px',
  verticalAlign: 'top',
} satisfies CSSProperties;

export function WechatPage() {
  const [summary, setSummary] = useState<WechatAdminSummary | null>(null);
  const [bindings, setBindings] = useState<WechatBinding[]>([]);
  const [messages, setMessages] = useState<WechatMessage[]>([]);
  const [digests, setDigests] = useState<WechatDigestSubscription[]>([]);
  const [deliveries, setDeliveries] = useState<WechatDeliveryLog[]>([]);
  const [webNotifications, setWebNotifications] = useState<WechatWebNotification[]>([]);
  const [users, setUsers] = useState<AdminUser[]>([]);
  const [search, setSearch] = useState('');
  const [messageStatus, setMessageStatus] = useState('');
  const [digestStatus, setDigestStatus] = useState('');
  const [deliveryStatus, setDeliveryStatus] = useState('');
  const [notificationStatus, setNotificationStatus] = useState('');
  const [notifyAudience, setNotifyAudience] = useState<'single' | 'multi' | 'all'>('single');
  const [notifyUserId, setNotifyUserId] = useState('');
  const [notifyUserIds, setNotifyUserIds] = useState<string[]>([]);
  const [notifyTitle, setNotifyTitle] = useState('');
  const [notifyBody, setNotifyBody] = useState('');
  const [notifyType, setNotifyType] = useState('manual');
  const [notifyChannels, setNotifyChannels] = useState<Array<'web' | 'wechat'>>(['web']);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [notice, setNotice] = useState<string | null>(null);

  const load = async () => {
    setError(null);
    try {
      const [
        summaryResult,
        bindingResult,
        messageResult,
        digestResult,
        deliveryResult,
        notificationResult,
        userResult,
      ] =
        await Promise.all([
          fetchWechatSummary(),
          fetchWechatBindings({ search, limit: 80 }),
          fetchWechatMessages({ status: messageStatus || undefined, limit: 80 }),
          fetchWechatDigests({ status: digestStatus || undefined, limit: 80 }),
          fetchWechatDeliveries({ status: deliveryStatus || undefined, limit: 80 }),
          fetchWechatWebNotifications({ status: notificationStatus || undefined, limit: 80 }),
          fetchAdminUsers({ page: 1, pageSize: 200, status: 'active' }),
        ]);
      setSummary(summaryResult);
      setBindings(bindingResult.bindings);
      setMessages(messageResult.messages);
      setDigests(digestResult.digests);
      setDeliveries(deliveryResult.deliveries);
      setWebNotifications(notificationResult.notifications);
      setUsers(userResult.users);
      setNotifyUserId((current) =>
        current || userResult.users[0]?.id || '',
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : '加载失败');
    }
  };

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

  const handleClearRoute = async (binding: WechatBinding) => {
    if (!window.confirm(`确认清除「${userName(binding)}」的服务号会话路由？下一次用户发消息会重建路由。`)) return;
    setBusy(true);
    try {
      await clearWechatRoute(binding.userId);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : '清除失败');
    } finally {
      setBusy(false);
    }
  };

  const handleCancelDigest = async (digest: WechatDigestSubscription) => {
    if (!window.confirm(`确认暂停「${userName(digest)}」的每日待办推送？`)) return;
    setBusy(true);
    try {
      await cancelWechatDigest(digest.id);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : '暂停失败');
    } finally {
      setBusy(false);
    }
  };

  const handleResumeDigest = async (digest: WechatDigestSubscription) => {
    setBusy(true);
    try {
      await resumeWechatDigest(digest.id);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : '恢复失败');
    } finally {
      setBusy(false);
    }
  };

  const toggleChannel = (channel: 'web' | 'wechat') => {
    setNotifyChannels((current) => {
      if (current.includes(channel)) {
        if (current.length === 1) return current;
        return current.filter((item) => item !== channel);
      }
      return [...current, channel];
    });
  };

  const handleSubmitNotification = async () => {
    const title = notifyTitle.trim();
    const body = notifyBody.trim();
    if (!title) {
      setError('请填写通知标题');
      return;
    }
    if (!body) {
      setError('请填写通知内容');
      return;
    }
    setBusy(true);
    setError(null);
    setNotice(null);
    try {
      const payload =
        notifyAudience === 'all'
          ? {
              audience: 'all' as const,
              allUsers: true,
              title,
              body,
              notificationType: notifyType.trim() || 'manual',
              channels: notifyChannels,
            }
          : notifyAudience === 'multi'
            ? {
                userIds: notifyUserIds,
                title,
                body,
                notificationType: notifyType.trim() || 'manual',
                channels: notifyChannels,
              }
            : {
                userId: notifyUserId,
                title,
                body,
                notificationType: notifyType.trim() || 'manual',
                channels: notifyChannels,
              };
      const result = await createWechatWebNotification(payload);
      const failureCount = result.wechatFailures?.length ?? 0;
      setNotice(
        `发送完成：目标 ${result.targets} 人，网页通知 ${result.created} 条，公众号成功 ${result.wechatSent} 条${
          failureCount ? `，失败 ${failureCount} 条` : ''
        }。`,
      );
      setNotifyTitle('');
      setNotifyBody('');
      if (notifyAudience === 'multi') setNotifyUserIds([]);
      await load();
    } catch (err) {
      setError(err instanceof Error ? err.message : '发送失败');
    } finally {
      setBusy(false);
    }
  };

  if (!summary && !error) return <p>加载中...</p>;

  return (
    <div className="grid">
      {error ? <p className="alert">{error}</p> : null}
      {notice ? <p className="alert" style={{ background: '#edf7f1', color: '#2f6f57' }}>{notice}</p> : null}

      {summary ? (
        <div
          className="card"
          style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(170px, 1fr))', gap: 12 }}
        >
          <Metric label="服务号" value={summary.config.mpEnabled ? '已启用' : '未启用'} />
          <Metric label="绑定用户" value={summary.counts.boundUsers} />
          <Metric label="活跃路由" value={`${summary.counts.routes.active}/${summary.counts.routes.total}`} />
          <Metric label="每日订阅" value={count(summary.counts.digests, 'active')} />
          <Metric label="24h 消息失败" value={count(summary.counts.recentMessages, 'failed')} danger />
          <Metric label="24h 投递失败" value={count(summary.counts.recentDeliveries, 'failed')} danger />
          <div style={{ gridColumn: '1 / -1', color: '#68716c', fontSize: 12 }}>
            AppID {summary.config.appId ?? '未配置'} · {summary.config.publicBaseUrl ?? '未配置公网地址'}
            {summary.config.bindPath ? ` · 绑定路径 ${summary.config.bindPath}` : ''}
          </div>
        </div>
      ) : null}

      <section className="card grid">
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0 }}>主动通知推送</h3>
          <button type="button" className="btn secondary" onClick={() => void load()} disabled={busy}>
            刷新用户
          </button>
        </div>
        <div
          style={{
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
            gap: 12,
          }}
        >
          <Field label="发送对象">
            <select value={notifyAudience} onChange={(event) => setNotifyAudience(event.target.value as 'single' | 'multi' | 'all')}>
              <option value="single">单个用户</option>
              <option value="multi">多个用户</option>
              <option value="all">全部活跃用户</option>
            </select>
          </Field>
          <Field label="通知类型">
            <input value={notifyType} onChange={(event) => setNotifyType(event.target.value)} placeholder="manual / recharge / balance_low" />
          </Field>
          <Field label="发送渠道">
            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', minHeight: 38, alignItems: 'center' }}>
              <label><input type="checkbox" checked={notifyChannels.includes('web')} onChange={() => toggleChannel('web')} /> 网页端</label>
              <label><input type="checkbox" checked={notifyChannels.includes('wechat')} onChange={() => toggleChannel('wechat')} /> 公众号</label>
            </div>
          </Field>
          {notifyAudience === 'single' ? (
            <Field label="目标用户">
              <select value={notifyUserId} onChange={(event) => setNotifyUserId(event.target.value)}>
                <option value="">请选择用户</option>
                {users.map((user) => (
                  <option key={user.id} value={user.id}>
                    {user.displayName || user.username} ({user.username})
                  </option>
                ))}
              </select>
            </Field>
          ) : null}
          {notifyAudience === 'multi' ? (
            <Field label="目标用户（可多选）">
              <select
                multiple
                value={notifyUserIds}
                onChange={(event) =>
                  setNotifyUserIds(Array.from(event.target.selectedOptions).map((item) => item.value))
                }
                style={{ minHeight: 120 }}
              >
                {users.map((user) => (
                  <option key={user.id} value={user.id}>
                    {user.displayName || user.username} ({user.username})
                  </option>
                ))}
              </select>
            </Field>
          ) : null}
        </div>
        <Field label="标题">
          <input value={notifyTitle} onChange={(event) => setNotifyTitle(event.target.value)} placeholder="例如：系统维护提醒" />
        </Field>
        <Field label="内容">
          <textarea
            value={notifyBody}
            onChange={(event) => setNotifyBody(event.target.value)}
            placeholder="填写要发送给用户的通知内容"
            rows={4}
          />
        </Field>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
          <p style={{ margin: 0, color: '#68716c', fontSize: 12 }}>
            支持单发、批量、多通道；全部用户会发送给所有非 disabled 用户。
          </p>
          <button type="button" className="btn" onClick={() => void handleSubmitNotification()} disabled={busy}>
            {busy ? '发送中…' : '立即发送'}
          </button>
        </div>
      </section>

      <section className="card grid">
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0 }}>绑定与会话路由</h3>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            <input
              value={search}
              onChange={(event) => setSearch(event.target.value)}
              placeholder="搜索用户、昵称、openid"
              style={{ width: 220 }}
            />
            <button type="button" className="btn secondary" onClick={() => void load()} disabled={busy}>
              查询
            </button>
          </div>
        </div>
        <TableShell empty={bindings.length === 0}>
          <table style={tableStyle}>
            <thead>
              <tr>
                <th style={thStyle}>用户</th>
                <th style={thStyle}>微信</th>
                <th style={thStyle}>路由</th>
                <th style={thStyle}>最近绑定登录</th>
                <th style={thStyle}>操作</th>
              </tr>
            </thead>
            <tbody>
              {bindings.map((binding) => (
                <tr key={`${binding.userId}-${binding.openidMasked}`}>
                  <td style={tdStyle}>
                    <strong>{userName(binding)}</strong>
                    <div style={{ color: '#68716c', fontSize: 12 }}>{binding.username}</div>
                  </td>
                  <td style={tdStyle}>
                    <div>{binding.nickname || '—'}</div>
                    <div style={{ color: '#68716c', fontSize: 12 }}>{binding.openidMasked}</div>
                  </td>
                  <td style={tdStyle}>
                    {badge(binding.routeStatus)}
                    <div style={{ color: '#68716c', fontSize: 12 }}>{binding.agentSessionId || '无会话'}</div>
                  </td>
                  <td style={tdStyle}>{time(binding.lastLoginAt)}</td>
                  <td style={tdStyle}>
                    <button
                      type="button"
                      className="btn secondary"
                      style={{ padding: '4px 10px', fontSize: 12 }}
                      onClick={() => void handleClearRoute(binding)}
                      disabled={busy || !binding.routeId}
                    >
                      清除路由
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </TableShell>
      </section>

      <section className="card grid">
        <SectionHead
          title="最近网页通知"
          value={notificationStatus}
          options={['', 'unread', 'read']}
          onChange={setNotificationStatus}
          onRefresh={() => void load()}
          busy={busy}
        />
        <TableShell empty={webNotifications.length === 0}>
          <table style={tableStyle}>
            <thead>
              <tr>
                <th style={thStyle}>用户</th>
                <th style={thStyle}>类型</th>
                <th style={thStyle}>标题</th>
                <th style={thStyle}>状态</th>
                <th style={thStyle}>创建时间</th>
              </tr>
            </thead>
            <tbody>
              {webNotifications.map((notification) => (
                <tr key={notification.id}>
                  <td style={tdStyle}>{userName(notification)}</td>
                  <td style={tdStyle}>{notification.notificationType}</td>
                  <td style={{ ...tdStyle, maxWidth: 420 }}>
                    <strong>{notification.title}</strong>
                    <div style={{ color: '#68716c', fontSize: 12, marginTop: 4 }}>{notification.body}</div>
                  </td>
                  <td style={tdStyle}>{badge(notification.status)}</td>
                  <td style={tdStyle}>{time(notification.createdAt)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </TableShell>
      </section>

      <section className="card grid">
        <SectionHead
          title="每日待办推送"
          value={digestStatus}
          options={['', 'active', 'locked', 'failed', 'cancelled']}
          onChange={setDigestStatus}
          onRefresh={() => void load()}
          busy={busy}
        />
        <TableShell empty={digests.length === 0}>
          <table style={tableStyle}>
            <thead>
              <tr>
                <th style={thStyle}>用户</th>
                <th style={thStyle}>时间</th>
                <th style={thStyle}>状态</th>
                <th style={thStyle}>下次运行</th>
                <th style={thStyle}>错误</th>
                <th style={thStyle}>操作</th>
              </tr>
            </thead>
            <tbody>
              {digests.map((digest) => (
                <tr key={digest.id}>
                  <td style={tdStyle}>
                    <strong>{userName(digest)}</strong>
                    <div style={{ color: '#68716c', fontSize: 12 }}>{digest.username}</div>
                  </td>
                  <td style={tdStyle}>
                    {String(digest.hour).padStart(2, '0')}:{String(digest.minute).padStart(2, '0')}
                    <div style={{ color: '#68716c', fontSize: 12 }}>{digest.timezone}</div>
                  </td>
                  <td style={tdStyle}>{badge(digest.status)}</td>
                  <td style={tdStyle}>{time(digest.nextRunAt)}</td>
                  <td style={{ ...tdStyle, maxWidth: 260 }}>{digest.lastError || '—'}</td>
                  <td style={tdStyle}>
                    {digest.status === 'active' || digest.status === 'locked' ? (
                      <button
                        type="button"
                        className="btn secondary"
                        style={{ padding: '4px 10px', fontSize: 12 }}
                        onClick={() => void handleCancelDigest(digest)}
                        disabled={busy}
                      >
                        暂停
                      </button>
                    ) : (
                      <button
                        type="button"
                        className="btn"
                        style={{ padding: '4px 10px', fontSize: 12 }}
                        onClick={() => void handleResumeDigest(digest)}
                        disabled={busy}
                      >
                        恢复
                      </button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </TableShell>
      </section>

      <section className="card grid">
        <SectionHead
          title="最近服务号消息"
          value={messageStatus}
          options={['', 'processing', 'done', 'failed']}
          onChange={setMessageStatus}
          onRefresh={() => void load()}
          busy={busy}
        />
        <TableShell empty={messages.length === 0}>
          <table style={tableStyle}>
            <thead>
              <tr>
                <th style={thStyle}>用户</th>
                <th style={thStyle}>OpenID</th>
                <th style={thStyle}>状态</th>
                <th style={thStyle}>会话</th>
                <th style={thStyle}>更新时间</th>
              </tr>
            </thead>
            <tbody>
              {messages.map((message) => (
                <tr key={`${message.openidMasked}-${message.msgId}`}>
                  <td style={tdStyle}>{userName(message)}</td>
                  <td style={tdStyle}>{message.openidMasked}</td>
                  <td style={tdStyle}>{badge(message.status)}</td>
                  <td style={tdStyle}>{message.agentSessionId || '—'}</td>
                  <td style={tdStyle}>{time(message.updatedAt)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </TableShell>
      </section>

      <section className="card grid">
        <SectionHead
          title="推送投递日志"
          value={deliveryStatus}
          options={['', 'success', 'failed']}
          onChange={setDeliveryStatus}
          onRefresh={() => void load()}
          busy={busy}
        />
        <TableShell empty={deliveries.length === 0}>
          <table style={tableStyle}>
            <thead>
              <tr>
                <th style={thStyle}>用户</th>
                <th style={thStyle}>类型</th>
                <th style={thStyle}>状态</th>
                <th style={thStyle}>错误</th>
                <th style={thStyle}>时间</th>
              </tr>
            </thead>
            <tbody>
              {deliveries.map((delivery) => (
                <tr key={delivery.id}>
                  <td style={tdStyle}>{userName(delivery)}</td>
                  <td style={tdStyle}>{delivery.digestType ?? (delivery.reminderId ? 'reminder' : '—')}</td>
                  <td style={tdStyle}>{badge(delivery.status)}</td>
                  <td style={{ ...tdStyle, maxWidth: 320 }}>
                    {delivery.errorMessage || delivery.errorCode || delivery.providerMessageId || '—'}
                  </td>
                  <td style={tdStyle}>{time(delivery.createdAt)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </TableShell>
      </section>
    </div>
  );
}

function Metric({ label, value, danger = false }: { label: string; value: string | number; danger?: boolean }) {
  return (
    <div>
      <p style={{ color: '#68716c', marginBottom: 4 }}>{label}</p>
      <strong style={{ fontSize: 26, color: danger && Number(value) > 0 ? '#b42318' : undefined }}>{value}</strong>
    </div>
  );
}

function SectionHead({
  title,
  value,
  options,
  onChange,
  onRefresh,
  busy,
}: {
  title: string;
  value: string;
  options: string[];
  onChange: (value: string) => void;
  onRefresh: () => void;
  busy: boolean;
}) {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
      <h3 style={{ margin: 0 }}>{title}</h3>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
        <select value={value} onChange={(event) => onChange(event.target.value)} style={{ width: 160 }}>
          {options.map((option) => (
            <option key={option || 'all'} value={option}>
              {option || '全部状态'}
            </option>
          ))}
        </select>
        <button type="button" className="btn secondary" onClick={onRefresh} disabled={busy}>
          刷新
        </button>
      </div>
    </div>
  );
}

function TableShell({ empty, children }: { empty: boolean; children: ReactNode }) {
  if (empty) return <p style={{ color: '#68716c', margin: 0 }}>暂无记录</p>;
  return <div style={{ overflowX: 'auto' }}>{children}</div>;
}

function Field({ label, children }: { label: string; children: ReactNode }) {
  return (
    <label style={{ display: 'grid', gap: 6 }}>
      <span style={{ color: '#68716c', fontSize: 12 }}>{label}</span>
      {children}
    </label>
  );
}
