import { useCallback, useEffect, useMemo, useState } from 'react';
import type { ComponentType } from 'react';
import { AlertTriangle, ArrowLeft, Film, FolderClock, Loader2, RefreshCcw, Sparkles } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { hostApiFetch } from '@/lib/host-api';

const DEFAULT_NIANXX_PLAY_URL = 'http://127.0.0.1:3000';

type NianxxPlayRoute = '/' | '/projects' | '/planning';
type ServiceState = 'checking' | 'starting' | 'running' | 'error';

type NianxxPlayServiceStatus = {
  success: boolean;
  running: boolean;
  starting: boolean;
  managed: boolean;
  baseUrl: string;
  port: number;
  projectDir?: string;
  pid?: number;
  error?: string;
};

const NIANXX_PLAY_NAV: Array<{
  path: NianxxPlayRoute;
  labelKey: string;
  icon: ComponentType<{ className?: string }>;
}> = [
  { path: '/', labelKey: 'host.nav.create', icon: Film },
  { path: '/projects', labelKey: 'host.nav.projects', icon: FolderClock },
  { path: '/planning', labelKey: 'host.nav.planning', icon: Sparkles },
];

function buildEmbeddedSrc(baseUrl: string, route: NianxxPlayRoute, reloadKey: number) {
  try {
    const url = new URL(route, baseUrl);
    url.searchParams.set('zhinianEmbed', '1');
    url.searchParams.set('zhinianHostReload', String(reloadKey));
    return url.toString();
  } catch {
    const normalizedBase = baseUrl.replace(/\/$/, '');
    return `${normalizedBase}${route}?zhinianEmbed=1&zhinianHostReload=${reloadKey}`;
  }
}

export function NianxxPlay() {
  const { t } = useTranslation('appCenter');
  const navigate = useNavigate();
  const [webviewKey, setWebviewKey] = useState(0);
  const [currentRoute, setCurrentRoute] = useState<NianxxPlayRoute>('/');
  const [loadError, setLoadError] = useState<string | null>(null);
  const configuredAppUrl = useMemo(() => (
    import.meta.env.VITE_NIANXX_PLAY_URL?.trim() || ''
  ), []);
  const [serviceState, setServiceState] = useState<ServiceState>(configuredAppUrl ? 'running' : 'checking');
  const [serviceError, setServiceError] = useState<string | null>(null);
  const [appUrl, setAppUrl] = useState(configuredAppUrl || DEFAULT_NIANXX_PLAY_URL);
  const initialSrc = useMemo(
    () => buildEmbeddedSrc(appUrl, currentRoute, webviewKey),
    [appUrl, currentRoute, webviewKey],
  );

  const ensureService = useCallback(async () => {
    if (configuredAppUrl) {
      setAppUrl(configuredAppUrl);
      setServiceState('running');
      setServiceError(null);
      return true;
    }

    setServiceState('checking');
    setServiceError(null);
    try {
      const status = await hostApiFetch<NianxxPlayServiceStatus>('/api/apps/nianxx-play/status');
      if (status.running) {
        setAppUrl(status.baseUrl);
        setServiceState('running');
        return true;
      }

      setServiceState('starting');
      const started = await hostApiFetch<NianxxPlayServiceStatus>('/api/apps/nianxx-play/start', {
        method: 'POST',
      });
      setAppUrl(started.baseUrl || DEFAULT_NIANXX_PLAY_URL);
      if (started.running) {
        setServiceState('running');
        setServiceError(null);
        return true;
      }
      setServiceState('error');
      setServiceError(started.error || t('host.serviceFailed'));
      return false;
    } catch (error) {
      setServiceState('error');
      setServiceError(error instanceof Error ? error.message : String(error));
      return false;
    }
  }, [configuredAppUrl, t]);

  useEffect(() => {
    let cancelled = false;
    void (async () => {
      const ok = await ensureService();
      if (cancelled || !ok) return;
      setWebviewKey((value) => value + 1);
    })();
    return () => {
      cancelled = true;
    };
  }, [ensureService]);

  const reloadApp = async () => {
    setLoadError(null);
    const ok = await ensureService();
    if (ok) {
      setWebviewKey((value) => value + 1);
    }
  };

  const openRoute = (route: NianxxPlayRoute) => {
    setLoadError(null);
    setCurrentRoute(route);
    setWebviewKey((value) => value + 1);
  };

  return (
    <div data-testid="nianxx-play-page" className="-m-6 flex h-[calc(100vh-2.5rem)] min-h-0 flex-col overflow-hidden bg-white text-slate-950 dark:bg-slate-950 dark:text-slate-50">
      <header className="grid h-14 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-slate-200/80 bg-white/70 px-4 backdrop-blur dark:border-white/10 dark:bg-slate-950/80">
        <div className="flex min-w-0 items-center gap-2">
          <Button
            type="button"
            variant="outline"
            size="sm"
            onClick={() => navigate('/app-center')}
            data-testid="nianxx-play-back"
            className="shrink-0"
          >
            <ArrowLeft className="h-4 w-4" />
            {t('host.back')}
          </Button>
          <Button
            type="button"
            variant="outline"
            size="icon"
            onClick={reloadApp}
            aria-label={t('host.reload')}
            title={t('host.reload')}
            className="h-9 w-9 shrink-0"
          >
            <RefreshCcw className="h-4 w-4" />
          </Button>
          <div className="min-w-0">
            <h1 className="truncate text-base font-semibold tracking-normal">
              {t('host.title')}
            </h1>
          </div>
        </div>
        <nav className="flex shrink-0 items-center gap-1 justify-self-center rounded-lg border border-slate-200/70 bg-white/60 p-1 dark:border-white/10 dark:bg-white/5" aria-label={t('host.nav.label')}>
          {NIANXX_PLAY_NAV.map((item) => {
            const Icon = item.icon;
            const active = currentRoute === item.path;
            return (
              <button
                key={item.path}
                type="button"
                onClick={() => openRoute(item.path)}
                data-testid={`nianxx-play-nav-${item.path === '/' ? 'create' : item.path.slice(1)}`}
                className={cn(
                  'inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs font-medium transition-colors',
                  active
                    ? 'bg-white text-[#075985] shadow-sm dark:bg-slate-950 dark:text-blue-200'
                    : 'text-slate-600 hover:bg-white/70 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white',
                )}
              >
                <Icon className="h-3.5 w-3.5" />
                {t(item.labelKey)}
              </button>
            );
          })}
        </nav>
        <div aria-hidden className="min-w-0" />
      </header>

      <section className="relative min-h-0 flex-1 overflow-hidden bg-white dark:bg-slate-950">
        {serviceState === 'running' && (
          <iframe
            key={webviewKey}
            src={initialSrc}
            title={t('host.title')}
            className="absolute inset-0 h-full w-full border-0 bg-white dark:bg-slate-950"
            onLoad={() => setLoadError(null)}
            onError={() => setLoadError(t('host.loadFailed'))}
          />
        )}
        {serviceState !== 'running' && (
          <div className="absolute inset-0 flex items-center justify-center bg-white/95 p-6 text-center dark:bg-slate-950/95">
            <div className="max-w-md">
              <div className="mx-auto flex h-11 w-11 items-center justify-center rounded-lg bg-[#EAF5FA] text-[#075985] dark:bg-[#1E3A8A]/30 dark:text-blue-100">
                {serviceState === 'error'
                  ? <AlertTriangle className="h-5 w-5" />
                  : <Loader2 className="h-5 w-5 animate-spin" />}
              </div>
              <div className="mt-4 text-base font-semibold text-slate-950 dark:text-slate-50">
                {serviceState === 'error' ? t('host.serviceFailed') : t('host.serviceStarting')}
              </div>
              <p className="mt-2 text-sm leading-6 text-muted-foreground">
                {serviceError || t('host.serviceStartingDesc')}
              </p>
              <div className="mt-4 flex justify-center gap-2">
                <Button type="button" variant="outline" size="sm" onClick={reloadApp}>
                  <RefreshCcw className="h-4 w-4" />
                  {t('host.reload')}
                </Button>
              </div>
            </div>
          </div>
        )}
        {serviceState === 'running' && loadError && (
          <div className="absolute inset-0 flex items-center justify-center bg-white/95 p-6 text-center dark:bg-slate-950/95">
            <div className="max-w-md">
              <div className="text-base font-semibold text-slate-950 dark:text-slate-50">
                {t('host.loadFailed')}
              </div>
              <p className="mt-2 text-sm leading-6 text-muted-foreground">
                {loadError}
              </p>
              <div className="mt-4 flex justify-center gap-2">
                <Button type="button" variant="outline" size="sm" onClick={reloadApp}>
                  <RefreshCcw className="h-4 w-4" />
                  {t('host.reload')}
                </Button>
              </div>
            </div>
          </div>
        )}
      </section>
    </div>
  );
}

export default NianxxPlay;
