import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useOutletContext } from 'react-router-dom';
import { Button, Space, Badge, Spin, Grid, Result } from 'antd';
import { ReloadOutlined, LinkOutlined, MessageOutlined } from '@ant-design/icons';
import { api } from '@/lib/api';
import type { AppOutletContext } from '@/components/AppLayout';
import type { ServicesConfig } from '@/types/api';
import { buildServiceUrl } from '@/lib/service-url';

interface RCConfig {
  enabled: boolean;
  embedPort: number;
  subdomain: string;
  domain: string;
}

interface RCAuthResponse {
  authToken: string;
  rcUserId: string;
}

export default function RocketChatPage() {
  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;

  const [online, setOnline] = useState<boolean | null>(null);
  const [config, setConfig] = useState<ServicesConfig | null>(null);
  const [rcConfig, setRcConfig] = useState<RCConfig | null>(null);
  const [authToken, setAuthToken] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [authError, setAuthError] = useState<string | null>(null);
  const iframeRef = useRef<HTMLIFrameElement>(null);

  const fetchStatus = useCallback(async () => {
    setLoading(true);
    setAuthError(null);
    try {
      const [statusRes, configRes, rcConfigRes] = await Promise.all([
        api.get<{ online: boolean; enabled: boolean }>('/rocketchat/status'),
        api.get<ServicesConfig>('/services/config'),
        api.get<RCConfig>('/rocketchat/config'),
      ]);
      setOnline(statusRes.data.online);
      setConfig(configRes.data);
      setRcConfig(rcConfigRes.data);

      // If online, get auth token for SSO
      if (statusRes.data.online && statusRes.data.enabled) {
        try {
          const authRes = await api.post<RCAuthResponse>('/rocketchat/auth');
          setAuthToken(authRes.data.authToken);
        } catch (err) {
          setAuthError('Failed to authenticate with Rocket.Chat');
        }
      }
    } catch {
      setOnline(false);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchStatus();
  }, [fetchStatus]);

  // Inject auth token into iframe via postMessage when iframe loads.
  // RC's iframe integration listener may not be ready immediately after the
  // login page renders, so we retry a few times with a delay.
  const retryTimers = useRef<ReturnType<typeof setTimeout>[]>([]);

  const handleIframeLoad = useCallback(() => {
    // Clear any pending retries from a previous load
    retryTimers.current.forEach(clearTimeout);
    retryTimers.current = [];

    if (!authToken || !iframeRef.current?.contentWindow) return;

    const sendToken = () => {
      if (!iframeRef.current?.contentWindow || !serviceUrl) return;
      const targetOrigin = new URL(serviceUrl).origin;
      iframeRef.current.contentWindow.postMessage(
        { event: 'login-with-token', loginToken: authToken },
        targetOrigin,
      );
    };

    // Send immediately, then retry after short delays in case the
    // RC login page hasn't registered its listener yet
    sendToken();
    retryTimers.current.push(setTimeout(sendToken, 1000));
    retryTimers.current.push(setTimeout(sendToken, 3000));
  }, [authToken]);

  // Cleanup timers on unmount
  useEffect(() => {
    return () => retryTimers.current.forEach(clearTimeout);
  }, []);

  const serviceUrl = useMemo(() => {
    if (!config || !rcConfig) return null;
    return buildServiceUrl(rcConfig.subdomain, rcConfig.domain, rcConfig.embedPort);
  }, [config, rcConfig]);

  const headerActions = useMemo(() => (
    <Space>
      <Badge
        status={online === null ? 'processing' : online ? 'success' : 'error'}
        text={online === null ? 'Checking...' : online ? 'Online' : 'Offline'}
      />
      <Button icon={<ReloadOutlined />} onClick={fetchStatus} size="small">
        Refresh
      </Button>
      {serviceUrl && (
        <Button icon={<LinkOutlined />} href={serviceUrl} target="_blank" size="small">
          Open in New Tab
        </Button>
      )}
    </Space>
  ), [online, fetchStatus, serviceUrl]);

  useEffect(() => {
    setPageHeader({
      title: 'Team Chat',
      actions: headerActions,
      fullBleed: true,
    });
    return () => setPageHeader(null);
  }, [setPageHeader, headerActions]);

  if (isMobile) {
    return (
      <Result
        status="info"
        title="Desktop Required"
        subTitle="Rocket.Chat requires a desktop browser for the best experience."
        icon={<MessageOutlined style={{ fontSize: 48 }} />}
      />
    );
  }

  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: 80 }}>
        <Spin size="large" />
      </div>
    );
  }

  if (!rcConfig?.enabled) {
    return (
      <Result
        status="info"
        title="Chat Not Enabled"
        subTitle="Team chat is not enabled. Enable it in Settings → Feature Toggles."
      />
    );
  }

  if (!online || !serviceUrl) {
    return (
      <Result
        status="error"
        title="Rocket.Chat Unavailable"
        subTitle="Rocket.Chat is not running or could not be reached. Check that the rocketchat and mongodb-rocketchat containers are started."
        extra={
          <Button type="primary" onClick={fetchStatus}>
            Retry
          </Button>
        }
      />
    );
  }

  if (authError) {
    return (
      <Result
        status="warning"
        title="Authentication Failed"
        subTitle={authError}
        extra={
          <Button type="primary" onClick={fetchStatus}>
            Retry
          </Button>
        }
      />
    );
  }

  // Load full RC UI (with sidebar) — layout=embedded hides the channel sidebar
  const iframeSrc = serviceUrl;

  return (
    <iframe
      ref={iframeRef}
      src={iframeSrc}
      onLoad={handleIframeLoad}
      style={{
        width: '100%',
        height: 'calc(100vh - 64px)',
        border: 'none',
        display: 'block',
      }}
      title="Rocket.Chat Team Chat"
      allow="microphone; camera"
    />
  );
}
