import React, { useEffect, useRef, useState } from 'react';
import * as captchaApi from '../api/captcha.js';

// ── 模块级单例：showCaptcha 挂起请求，由 CaptchaModalHost 消费 ──
let pending = null;   // { action, type, resolve }
let listener = null;

function notifyHost() {
  if (listener) listener();
}

/**
 * 验证码流程入口（迁移自 public/js/captcha.js）：
 *  - null    无需验证 / 用户取消
 *  - object  { type: 'proof' | 'recaptcha' | 'turnstile', value }
 *            proof      → 内置验证码通过，value 为后端签发的 captcha_proof
 *            recaptcha  → reCAPTCHA 验证通过，value 为 siteverify token
 *            turnstile  → Turnstile 验证通过，value 为 siteverify token
 * 调用方提交时按 type 放入 captcha_proof / recaptcha_token / turnstile_token 字段。
 */
export function showCaptcha(action) {
  return new Promise((resolve) => {
    captchaApi.required(action)
      .then((r) => {
        if (!r || !r.required || r.type === 'none') { resolve(null); return; }
        pending = { action, type: r.type || 'builtin', resolve };
        notifyHost();
      })
      .catch(() => resolve(null));
  });
}

// 加载第三方验证码脚本（recaptcha / turnstile）
function ensureThirdPartyScript(type) {
  if (type === 'recaptcha') {
    window.recaptchaCallbacks = window.recaptchaCallbacks || [];
    if (typeof window.grecaptcha === 'undefined' && !document.querySelector('script[src*="recaptcha/api"]')) {
      const s = document.createElement('script');
      s.src = 'https://www.recaptcha.net/recaptcha/api.js?onload=onRecaptchaLoad&render=explicit';
      s.async = true; s.defer = true;
      document.head.appendChild(s);
    }
  } else {
    window.turnstileCallbacks = window.turnstileCallbacks || [];
    if (typeof window.turnstile === 'undefined' && !document.querySelector('script[src*="turnstile"]')) {
      const s = document.createElement('script');
      s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onTurnstileLoad&render=explicit';
      s.async = true; s.defer = true;
      document.head.appendChild(s);
    }
  }
}

// SHA-256（Proof of Work 使用）
async function sha256(str) {
  const buf = new TextEncoder().encode(str);
  const hash = await crypto.subtle.digest('SHA-256', buf);
  return Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, '0')).join('');
}

// 内置 SVG 验证码弹窗
function BuiltinCaptcha({ onFinish }) {
  const [svg, setSvg] = useState('');
  const [error, setError] = useState('');
  const [answer, setAnswer] = useState('');
  const [powDone, setPowDone] = useState(false);
  const [verifying, setVerifying] = useState(false);
  const tokenRef = useRef(null);
  const imgRef = useRef(null);

  const loadImage = async () => {
    setError('');
    setAnswer('');
    const data = await captchaApi.getImage();
    if (data && data.token) {
      tokenRef.current = data.token;
      setSvg(data.svg);
    }
  };

  useEffect(() => {
    loadImage();
    // 智能验证（Proof of Work）后台运行，20s 内找到满足难度的 nonce
    (async () => {
      try {
        const chal = await captchaApi.powChallenge();
        if (!chal || !chal.token) return;
        const target = '0'.repeat(chal.difficulty);
        const start = Date.now();
        let nonce = 0;
        while (Date.now() - start < 20000) {
          const hash = await sha256(chal.prefix + nonce);
          if (hash.startsWith(target)) {
            await captchaApi.powVerify(chal.token, String(nonce));
            setPowDone(true);
            return;
          }
          nonce++;
        }
      } catch { /* 失败不影响主流程 */ }
    })();
  }, []);

  // 让后端返回的 SVG 自适应弹窗宽度（照搬 captcha.js 的样式处理）
  useEffect(() => {
    if (svg && imgRef.current) {
      const s = imgRef.current.querySelector('svg');
      if (s) s.setAttribute('style', 'width:100%;max-width:240px;height:auto;border-radius:8px;display:block');
    }
  }, [svg]);

  const submit = async () => {
    if (!powDone) { setError('智能验证尚未完成，请稍候...'); return; }
    if (!answer.trim() || !tokenRef.current) { setError('请输入验证码'); return; }
    setVerifying(true);
    const v = await captchaApi.verify(tokenRef.current, answer.trim());
    setVerifying(false);
    if (v.success) {
      onFinish({ type: 'proof', value: v.proof || '' });
    } else {
      setError(v.error || '验证码错误');
      tokenRef.current = null;
      setAnswer('');
      loadImage();
    }
  };

  return (
    <div className="dialog" style={{ maxWidth: 380, textAlign: 'center' }}>
      <h3 style={{ marginBottom: 12 }}>验证码</h3>
      <div ref={imgRef} style={{ margin: '0 auto 12px', maxWidth: 280, minHeight: 72 }}>
        {svg
          ? <div dangerouslySetInnerHTML={{ __html: svg }} />
          : <div className="spinner" style={{ width: 24, height: 24, margin: '16px auto' }} />}
      </div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', justifyContent: 'center' }}>
        <input
          type="text"
          value={answer}
          onChange={(e) => setAnswer(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter') submit(); }}
          placeholder="输入验证码"
          maxLength={6}
          autoComplete="off"
          style={{ flex: 1, textAlign: 'center', fontSize: 20, letterSpacing: 6, textTransform: 'uppercase' }}
        />
        <button type="button" className="btn btn-icon" title="刷新" onClick={loadImage} style={{ flexShrink: 0 }}>
          <span className="material-icons">refresh</span>
        </button>
      </div>
      {error && <div style={{ color: 'var(--md-ref-error)', fontSize: 13, marginTop: 8 }}>{error}</div>}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, marginTop: 8, fontSize: 13, color: 'var(--md-ref-on-surface-variant)' }}>
        {powDone ? (
          <>
            <span className="material-icons" style={{ fontSize: 16, color: '#4caf50' }}>check_circle</span>
            <span style={{ color: '#4caf50' }}>智能验证通过</span>
          </>
        ) : (
          <>
            <span className="material-icons" style={{ fontSize: 16 }}>smart_toy</span>
            <span>智能验证中...</span>
          </>
        )}
      </div>
      <div className="actions" style={{ justifyContent: 'center', marginTop: 16 }}>
        <button type="button" className="btn btn-text" onClick={() => onFinish(null)}>取消</button>
        <button type="button" className="btn btn-filled" onClick={submit} disabled={verifying}>确认</button>
      </div>
    </div>
  );
}

// 第三方验证码（reCAPTCHA / Turnstile），验证通过后把 siteverify token 传回调用方
function ThirdPartyCaptcha({ type, onFinish }) {
  const siteKey = type === 'recaptcha'
    ? (window._recaptchaSiteKey || '')
    : (window._turnstileSiteKey || '');
  const [status, setStatus] = useState('正在加载...');
  const widgetRef = useRef(null);
  const doneRef = useRef(false);

  useEffect(() => {
    if (!siteKey) { onFinish(null); return; }
    const container = widgetRef.current;
    const render = () => {
      try {
        if (type === 'recaptcha') {
          const wid = window.grecaptcha.render(container, {
            sitekey: siteKey,
            callback: () => {
              setStatus('验证通过');
              let token = '';
              try { token = window.grecaptcha.getResponse(wid); } catch { /* 忽略 */ }
              setTimeout(() => onFinish({ type: 'recaptcha', value: token || '' }), 300);
            },
            'expired-callback': () => setStatus('验证已过期'),
          });
        } else {
          const wid = window.turnstile.render(container, {
            sitekey: siteKey,
            callback: () => {
              setStatus('验证通过');
              let token = '';
              try { token = window.turnstile.getResponse(wid); } catch { /* 忽略 */ }
              setTimeout(() => onFinish({ type: 'turnstile', value: token || '' }), 300);
            },
            'expired-callback': () => setStatus('验证已过期'),
          });
        }
        setStatus('请完成验证');
      } catch {
        setStatus('加载失败');
        setTimeout(() => onFinish(null), 2000);
      }
    };
    if (type === 'recaptcha') {
      if (typeof window.grecaptcha !== 'undefined') render();
      else {
        window.recaptchaCallbacks = window.recaptchaCallbacks || [];
        window.recaptchaCallbacks.push(render);
        ensureThirdPartyScript(type);
      }
    } else {
      if (typeof window.turnstile !== 'undefined') render();
      else {
        window.turnstileCallbacks = window.turnstileCallbacks || [];
        window.turnstileCallbacks.push(render);
        ensureThirdPartyScript(type);
      }
    }
    // 卸载时不触发重复回调
    return () => { doneRef.current = true; };
  }, []);

  return (
    <div className="dialog" style={{ maxWidth: 400, textAlign: 'center' }}>
      <h3 style={{ marginBottom: 16 }}>{type === 'recaptcha' ? 'Google reCAPTCHA' : 'Cloudflare Turnstile'}</h3>
      <div ref={widgetRef} style={{ display: 'flex', justifyContent: 'center', margin: '16px 0' }} />
      <p className="text-muted" style={{ fontSize: 13 }}>{status}</p>
      <div className="actions" style={{ justifyContent: 'center' }}>
        <button type="button" className="btn btn-text" onClick={() => onFinish(null)}>取消</button>
      </div>
    </div>
  );
}

/**
 * 全局挂载的验证码弹窗宿主：放入 Layout 内，配合 showCaptcha(action) 使用。
 */
export default function CaptchaModalHost() {
  const [request, setRequest] = useState(null);

  useEffect(() => {
    listener = () => setRequest(pending);
    return () => { listener = null; };
  }, []);

  const finish = (proof) => {
    if (request) {
      const resolve = request.resolve;
      pending = null;
      setRequest(null);
      resolve(proof);
    }
  };

  if (!request) return null;

  return (
    <div
      className="dialog-overlay active"
      style={{ display: 'flex', zIndex: 9999 }}
      onMouseDown={(e) => { if (e.target === e.currentTarget) finish(null); }}
    >
      {request.type === 'recaptcha' ? (
        <ThirdPartyCaptcha type="recaptcha" onFinish={finish} />
      ) : request.type === 'turnstile' ? (
        <ThirdPartyCaptcha type="turnstile" onFinish={finish} />
      ) : (
        <BuiltinCaptcha onFinish={finish} />
      )}
    </div>
  );
}
