import { useState, useEffect, useRef, useCallback } from 'react';
import { AlertTriangle, Eye, EyeOff } from 'lucide-react';
import QRCodeLib from 'qrcode';
import { beginDingtalkRegistration, pollDingtalkRegistration, saveDingtalkStreamConfig } from '@/lib/api';
import { assetBasePath } from '@/lib/basePath';
import { useLocale } from '@/lib/i18n';

type BindPhase = 'loading' | 'waiting_scan' | 'confirmed' | 'expired' | 'error' | 'ws_success';

type ReceiveMode = 'qrcode' | 'stream';

const POLL_INTERVAL_MS = 2000;

export default function DingTalkBind({ onBindSuccess }: { onBindSuccess?: () => void }) {
  const { t } = useLocale();
  const [mode, setMode] = useState<ReceiveMode>('qrcode');
  const [phase, setPhase] = useState<BindPhase>('loading');
  const [qrUrl, setQrUrl] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [qrRendered, setQrRendered] = useState(false);

  const [clientId, setClientId] = useState('');
  const [clientSecret, setClientSecret] = useState('');
  const [showSecret, setShowSecret] = useState(false);
  const [submitting, setSubmitting] = useState(false);

  const canvasRef = useRef<HTMLCanvasElement>(null);
  const pollTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const pollingDeviceCodeRef = useRef<string>('');

  const stopPolling = useCallback(() => {
    if (pollTimerRef.current) {
      clearInterval(pollTimerRef.current);
      pollTimerRef.current = null;
    }
    pollingDeviceCodeRef.current = '';
  }, []);

  const renderQrOnCanvas = useCallback(async (url: string) => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    setQrRendered(false);
    try {
      await QRCodeLib.toCanvas(canvas, url, {
        width: 160,
        margin: 2,
        color: { dark: '#000000', light: '#ffffff' },
      });
      setQrRendered(true);
    } catch (err) {
      console.error('Failed to render QR code:', err);
    }
  }, []);

  useEffect(() => {
    if (qrUrl && (phase === 'waiting_scan' || phase === 'confirmed')) {
      renderQrOnCanvas(qrUrl);
    }
  }, [qrUrl, phase, renderQrOnCanvas]);

  const startPolling = useCallback((code: string) => {
    stopPolling();
    pollingDeviceCodeRef.current = code;
    pollTimerRef.current = setInterval(async () => {
      if (pollingDeviceCodeRef.current !== code) return;
      try {
        const data = await pollDingtalkRegistration(code);
        if (pollingDeviceCodeRef.current !== code) return;

        if (data.client_id && data.client_secret) {
          stopPolling();
          setPhase('confirmed');
          onBindSuccess?.();
          return;
        }

        switch (data.status) {
          case 'WAITING':
            break;
          case 'FAIL':
            stopPolling();
            setError(data.fail_reason || t('channel.dingtalk.auth_failed'));
            setPhase('error');
            break;
          case 'EXPIRED':
            stopPolling();
            setPhase('expired');
            break;
          default:
            if (data.error) {
              console.warn('DingTalk poll error:', data.error);
            }
        }
      } catch (err) {
        console.warn('DingTalk status poll error:', err);
      }
    }, POLL_INTERVAL_MS);
  }, [stopPolling]);

  const handleFetchQrCode = useCallback(async () => {
    stopPolling();
    setPhase('loading');
    setError(null);
    setQrRendered(false);
    try {
      const data = await beginDingtalkRegistration();
      setQrUrl(data.verification_uri_complete);
      setPhase('waiting_scan');
      startPolling(data.device_code);
    } catch (err) {
      setPhase('error');
      setError(err instanceof Error ? err.message : String(err));
    }
  }, [stopPolling, startPolling]);

  useEffect(() => {
    if (mode === 'qrcode') {
      handleFetchQrCode();
    }
    return () => {
      stopPolling();
    };
  }, [mode]);

  const handleModeChange = (newMode: ReceiveMode) => {
    setMode(newMode);
    if (newMode === 'stream') {
      stopPolling();
      setPhase('loading');
      setError(null);
      setClientId('');
      setClientSecret('');
      setTimeout(() => setPhase('ws_success'), 100);
    } else {
      handleFetchQrCode();
    }
  };

  const handleStreamConnect = async () => {
    if (!clientId.trim() || !clientSecret.trim()) {
      setError(t('channel.dingtalk.fill_required'));
      return;
    }

    setSubmitting(true);
    setError(null);
    try {
      await saveDingtalkStreamConfig(clientId.trim(), clientSecret.trim());
      setPhase('confirmed');
      onBindSuccess?.();
    } catch (err) {
      setPhase('error');
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setSubmitting(false);
    }
  };

  const handleCancel = () => {
    setClientId('');
    setClientSecret('');
    setShowSecret(false);
    setError(null);
  };

  return (
    <div className="flex flex-col items-center" style={{ fontFamily: "'Noto Sans CJK SC', sans-serif", paddingTop: 48 }}>
      <div style={{ marginBottom: 8 }}>
        <img src={`${assetBasePath}/icons/dingtalk.svg`} alt="DingTalk" width="64" height="64" />
      </div>

      <h1 style={{
        fontFamily: "'Noto Sans CJK SC', sans-serif",
        fontSize: 24,
        fontWeight: 500,
        lineHeight: 'normal',
        textAlign: 'center',
        letterSpacing: 0,
        color: '#000000',
        marginBottom: 2,
      }}>{t('channel.dingtalk')}</h1>

      <p style={{
        fontFamily: "'Noto Sans CJK SC', sans-serif",
        fontSize: 14,
        fontWeight: 400,
        lineHeight: 'normal',
        textAlign: 'center',
        letterSpacing: 0,
        color: 'rgba(0, 0, 0, 0.6)',
        marginBottom: 16,
        maxWidth: 400,
      }}>
        {t('channel.dingtalk.desc')}
      </p>

      {(phase !== 'error' || mode === 'stream') && (
        <div className="mb-4 flex items-center gap-6">
          <label className="flex items-center gap-2 cursor-pointer" onClick={() => handleModeChange('qrcode')}>
            <div
              className="flex items-center justify-center"
              style={{
                width: 16,
                height: 16,
                borderRadius: '50%',
                border: mode === 'qrcode' ? '5px solid #3790FA' : '1.5px solid #d0d0d0',
                background: mode === 'qrcode' ? '#fff' : 'transparent',
              }}
            />
            <span style={{ fontSize: 14, fontWeight: 400, color: mode === 'qrcode' ? 'rgba(0,0,0,0.85)' : 'rgba(0,0,0,0.45)' }}>{t('channel.scan_connect')}</span>
          </label>
          <label className="flex items-center gap-2 cursor-pointer" onClick={() => handleModeChange('stream')}>
            <div
              className="flex items-center justify-center"
              style={{
                width: 16,
                height: 16,
                borderRadius: '50%',
                border: mode === 'stream' ? '5px solid #3790FA' : '1.5px solid #d0d0d0',
                background: mode === 'stream' ? '#fff' : 'transparent',
              }}
            />
            <span style={{ fontSize: 14, fontWeight: 400, color: mode === 'stream' ? 'rgba(0,0,0,0.85)' : 'rgba(0,0,0,0.45)' }}>{t('channel.stream_connect')}</span>
          </label>
        </div>
      )}

      {error && (
        <div className="flex items-center gap-2 px-4 py-2 rounded-lg" style={{ background: 'rgba(239,68,68,0.06)', borderRadius: 6, marginBottom: 16 }}>
          <AlertTriangle className="w-4 h-4 flex-shrink-0" style={{ color: '#ef4444' }} />
          <span style={{ fontSize: 14, color: '#ef4444' }}>{error}</span>
        </div>
      )}

      {mode === 'stream' && (
        <>
          {phase === 'confirmed' ? (
            <div className="flex flex-col items-center gap-4 mt-4">
              <svg className="w-12 h-12" viewBox="0 0 24 24" fill="none" stroke="#10b981" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M22 11.08V12a10 10 0 11-5.93-9.14" />
                <polyline points="22 4 12 14.01 9 11.01" />
              </svg>
              <span style={{
                fontFamily: "'Noto Sans CJK SC', sans-serif",
                fontSize: 12,
                fontWeight: 500,
                color: '#10b981',
                textAlign: 'center',
              }}>
                {t('channel.bind_success')}
              </span>
            </div>
          ) : (
            <div className="w-full flex flex-col" style={{ gap: 16 }}>
              <div className="flex flex-col" style={{ height: 61, padding: 0 }}>
                <label style={{
                  fontFamily: "'Noto Sans CJK SC', sans-serif",
                  fontSize: 14,
                  fontWeight: 400,
                  color: 'rgba(0, 0, 0, 0.85)',
                  height: 21,
                  lineHeight: '21px',
                }}>
                  Client ID <span style={{ color: '#F53F3F' }}>*</span>
                </label>
                <input
                  type="text"
                  value={clientId}
                  onChange={(e) => setClientId(e.target.value)}
                  placeholder={t('channel.dingtalk.client_id_placeholder')}
                  className="w-full px-3 outline-none transition-all focus:ring-2 focus:ring-[#3790FA]/30 channel-input"
                  style={{
                    fontFamily: "'Noto Sans CJK SC', sans-serif",
                    fontSize: 14,
                    fontWeight: 400,
                    background: '#E6E6E6',
                    border: 'none',
                    borderRadius: 6,
                    color: '#333',
                    height: 36,
                    marginTop: 4,
                  }}
                />
              </div>

              <div className="flex flex-col" style={{ height: 61, padding: 0 }}>
                <label style={{
                  fontFamily: "'Noto Sans CJK SC', sans-serif",
                  fontSize: 14,
                  fontWeight: 400,
                  color: 'rgba(0, 0, 0, 0.85)',
                  height: 21,
                  lineHeight: '21px',
                }}>
                  Client Secret <span style={{ color: '#F53F3F' }}>*</span>
                </label>
                <div className="relative" style={{ marginTop: 4 }}>
                  <input
                    type={showSecret ? 'text' : 'password'}
                    value={clientSecret}
                    onChange={(e) => setClientSecret(e.target.value)}
                    placeholder={t('channel.dingtalk.client_secret_placeholder')}
                    className="w-full px-3 pr-9 outline-none transition-all focus:ring-2 focus:ring-[#3790FA]/30 channel-input"
                    style={{
                      fontFamily: "'Noto Sans CJK SC', sans-serif",
                      fontSize: 14,
                      fontWeight: 400,
                      background: '#E6E6E6',
                      border: 'none',
                      borderRadius: 6,
                      color: '#333',
                      height: 36,
                    }}
                  />
                  <button
                    type="button"
                    onClick={() => setShowSecret(!showSecret)}
                    className="absolute right-2.5 top-1/2 -translate-y-1/2 p-0.5 rounded hover:bg-gray-100 transition-colors"
                  >
                    {showSecret ? (
                      <EyeOff className="w-4 h-4" style={{ color: '#999' }} />
                    ) : (
                      <Eye className="w-4 h-4" style={{ color: '#999' }} />
                    )}
                  </button>
                </div>
              </div>

              <div className="flex items-end justify-end gap-3" style={{ height: 52, padding: 0 }}>
                <button
                  onClick={handleCancel}
                  disabled={submitting}
                  style={{
                    fontFamily: "'Noto Sans CJK SC', sans-serif",
                    fontSize: 14,
                    fontWeight: 400,
                    padding: '8px 20px',
                    borderRadius: 6,
                    background: 'rgba(0, 0, 0, 0.1)',
                    color: 'rgba(0, 0, 0, 0.85)',
                    border: 'none',
                    cursor: submitting ? 'not-allowed' : 'pointer',
                  }}
                >
                  {t('channel.cancel')}
                </button>
                <button
                  onClick={handleStreamConnect}
                  disabled={submitting || !clientId.trim() || !clientSecret.trim()}
                  className="inline-flex items-center gap-2 transition-all hover:opacity-90 disabled:opacity-50"
                  style={{
                    fontFamily: "'Noto Sans CJK SC', sans-serif",
                    fontSize: 14,
                    fontWeight: 400,
                    padding: '8px 20px',
                    borderRadius: 6,
                    background: '#3790FA',
                    color: '#FFFFFF',
                    border: 'none',
                    cursor: (!submitting && clientId.trim() && clientSecret.trim()) ? 'pointer' : 'not-allowed',
                  }}
                >
                  {submitting && (
                    <svg className="w-4 h-4 animate-spin" viewBox="0 0 50 50" fill="none">
                      <circle cx="25" cy="25" r="20" stroke="#fff" strokeWidth="4" strokeLinecap="round" strokeDasharray="90 200" />
                    </svg>
                  )}
                  {t('channel.connect')}
                </button>
              </div>
            </div>
          )}
        </>
      )}

      {mode === 'qrcode' && (
        <>
          {(phase === 'loading' || phase === 'waiting_scan' || phase === 'expired' || phase === 'confirmed') && (
            <>
              <div
                className={`relative inline-block${(phase === 'loading' || phase === 'expired') ? ' cursor-pointer' : ''}`}
                style={{
                  background: '#fff',
                  border: '1px solid #e5e7eb',
                  borderRadius: 6,
                  width: 176,
                  height: 176,
                }}
                onClick={(phase === 'loading' || phase === 'expired') ? handleFetchQrCode : undefined}
              >
                <canvas ref={canvasRef} width={160} height={160}
                  className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
                  style={{
                    display: 'block',
                    visibility: (qrRendered && phase !== 'loading') ? 'visible' : 'hidden',
                    filter: (phase === 'expired' || phase === 'confirmed') ? 'blur(4px) opacity(0.12)' : 'none',
                  }} />

                {(phase === 'loading' || !qrRendered || phase === 'expired' || phase === 'confirmed') && (
                  <div className="absolute inset-0 flex flex-col items-center justify-center gap-3">
                    {phase === 'confirmed' ? null : phase === 'loading' ? (
                      <svg className="w-8 h-8 animate-spin" viewBox="0 0 50 50" fill="none">
                        <circle cx="25" cy="25" r="20" stroke="#0089FF" strokeWidth="4" strokeLinecap="round" strokeDasharray="90 200" />
                      </svg>
                    ) : (
                      <svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="#333" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                        <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8" />
                        <path d="M21 3v5h-5" />
                      </svg>
                    )}
                    {phase === 'confirmed' ? (
                      <span style={{
                        fontFamily: "'Noto Sans CJK SC', sans-serif",
                        fontSize: 12,
                        fontWeight: 500,
                        color: '#10b981',
                        textAlign: 'center',
                        padding: '0 16px',
                      }}>{t('channel.bind_success')}</span>
                    ) : phase === 'expired' ? (
                      <span style={{ fontSize: 14, color: 'rgba(0,0,0,0.6)', marginTop: -8 }}>{t('channel.refresh_qr')}</span>
                    ) : null}
                  </div>
                )}
              </div>
            </>
          )}

          <div className="mt-2 h-[28px] flex items-center justify-center">
            {phase === 'expired' ? (
              <span style={{ fontSize: 14, color: '#F53F3F', fontWeight: 400 }}>
                {t('channel.qr_expired')}
              </span>
            ) : null}
          </div>
        </>
      )}

      {phase === 'error' && !['waiting_scan', 'confirmed'].includes(phase) && (
        <div className="flex flex-col items-center gap-4">
          <AlertTriangle className="w-12 h-12" style={{ color: '#ef4444' }} />
          <p style={{ fontSize: 14, color: 'rgba(0,0,0,0.85)' }}>{t('channel.bind_error')}</p>
          <button onClick={() => { setError(null); handleFetchQrCode(); }}
            className="inline-flex items-center gap-2 transition-all hover:opacity-90"
            style={{
              fontFamily: "'Noto Sans CJK SC', sans-serif",
              fontSize: 14,
              padding: '10px 24px',
              borderRadius: 6,
              background: '#0089FF',
              color: '#fff',
              border: 'none',
              cursor: 'pointer',
            }}>
            {t('channel.retry')}
          </button>
        </div>
      )}
    </div>
  );
}
