import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import axios from 'axios';
import { ChevronLeft, ChevronRight, RefreshCw, Terminal } from 'lucide-react';

import { ProtectedSearchInput } from '../../../components/ProtectedSearchInput';
import { LucentIconButton } from '../../../components/lucent/LucentIconButton';
import { useLucentPrompt } from '../../../components/lucent/LucentPromptProvider';
import { APP_ENDPOINTS } from '../../../config/env';
import { dashboardEn } from '../../../i18n/dashboard.en';
import { dashboardZhCn } from '../../../i18n/dashboard.zh-cn';
import { pickLocale } from '../../../i18n';
import type { BotState } from '../../../types/bot';
import { WorkspaceEntriesList } from '../../dashboard/components/WorkspaceEntriesList';
import { WorkspaceHoverCard } from '../../dashboard/components/WorkspaceHoverCard';
import { WorkspacePreviewModal } from '../../dashboard/components/WorkspacePreviewModal';
import { useDashboardWorkspace } from '../../dashboard/hooks/useDashboardWorkspace';
import { formatBytes, formatWorkspaceTime } from '../../dashboard/utils';
import '../../dashboard/components/BotListPanel.css';
import '../../dashboard/components/RuntimePanel.css';
import '../../dashboard/components/DashboardShared.css';
import '../../dashboard/components/WorkspaceOverlay.css';
import '../../../components/ui/SharedUi.css';

interface PlatformBotRuntimeSectionProps {
  compactSheet?: boolean;
  isZh: boolean;
  pageSize: number;
  selectedBotInfo?: BotState;
  workspaceDownloadExtensions: string[];
}

const ANSI_ESCAPE_RE = /(?:\u001b\[|\[)[0-9;]{1,12}m/g;
const DOCKER_LOG_TABLE_HEADER_HEIGHT = 40;
const DOCKER_LOG_TABLE_ROW_HEIGHT = 56;
const EMPTY_DOCKER_LOG_ENTRY = {
  key: '',
  index: '',
  level: '',
  text: '',
  tone: 'plain',
} as const;

function stripAnsi(textRaw: string) {
  return String(textRaw || '').replace(ANSI_ESCAPE_RE, '').trim();
}

function parseDockerLogEntry(textRaw: string) {
  const text = stripAnsi(textRaw);
  const levelMatch = text.match(/\b(INFO|ERROR|WARN|WARNING|DEBUG|TRACE|CRITICAL|FATAL)\b/i);
  const levelRaw = String(levelMatch?.[1] || '').toUpperCase();
  const level = levelRaw === 'WARNING' ? 'WARN' : (levelRaw || '-');
  return {
    level,
    text,
    tone:
      level === 'ERROR' || level === 'FATAL' || level === 'CRITICAL'
        ? 'err'
        : level === 'WARN'
          ? 'warn'
          : level === 'INFO'
            ? 'info'
            : level === 'DEBUG' || level === 'TRACE'
              ? 'debug'
              : 'plain',
  } as const;
}

export function PlatformBotRuntimeSection({
  compactSheet = false,
  isZh,
  pageSize,
  selectedBotInfo,
  workspaceDownloadExtensions,
}: PlatformBotRuntimeSectionProps) {
  const { notify } = useLucentPrompt();
  const dashboardT = pickLocale(isZh ? 'zh' : 'en', { 'zh-cn': dashboardZhCn, en: dashboardEn });
  const [dockerLogs, setDockerLogs] = useState<string[]>([]);
  const [dockerLogsLoading, setDockerLogsLoading] = useState(false);
  const [dockerLogsError, setDockerLogsError] = useState('');
  const [dockerLogsPage, setDockerLogsPage] = useState(1);
  const [dockerLogsHasMore, setDockerLogsHasMore] = useState(false);
  const dockerLogsCardRef = useRef<HTMLDivElement | null>(null);
  const [workspaceCardHeightPx, setWorkspaceCardHeightPx] = useState<number | null>(null);
  const workspaceSearchInputName = useMemo(
    () => `platform-workspace-search-${Math.random().toString(36).slice(2, 10)}`,
    [],
  );
  const effectivePageSize = Math.max(1, Math.trunc(pageSize || 10));
  const dockerLogsTableHeightPx = DOCKER_LOG_TABLE_HEADER_HEIGHT + effectivePageSize * DOCKER_LOG_TABLE_ROW_HEIGHT;
  const recentLogEntries = useMemo(() => {
    const logs = (dockerLogs || [])
      .map((line) => String(line || '').trim())
      .filter(Boolean)
      .map((line, index) => ({
        key: `log-${dockerLogsPage}-${index}`,
        index: String((dockerLogsPage - 1) * effectivePageSize + index + 1).padStart(3, '0'),
        ...parseDockerLogEntry(line),
      }));
    if (logs.length > 0) return logs;

    const events = (selectedBotInfo?.events || [])
      .filter((event) => String(event?.text || '').trim().length > 0)
      .slice(0, effectivePageSize)
      .map((event, index) => ({
        key: `event-${event.ts}-${index}`,
        index: String(index + 1).padStart(3, '0'),
        ...parseDockerLogEntry(`[${String(event.state || 'INFO').toUpperCase()}] ${String(event.text || '').trim()}`),
      }));
    return events;
  }, [dockerLogs, dockerLogsPage, effectivePageSize, selectedBotInfo?.events]);
  const dockerLogTableRows = useMemo(
    () => [
      ...recentLogEntries,
      ...Array.from({ length: Math.max(0, effectivePageSize - recentLogEntries.length) }, (_, index) => ({
        ...EMPTY_DOCKER_LOG_ENTRY,
        key: `docker-log-empty-${dockerLogsPage}-${index}`,
      })),
    ],
    [dockerLogsPage, effectivePageSize, recentLogEntries],
  );
  const workspaceCardStyle = useMemo(
    () => (!compactSheet && workspaceCardHeightPx ? { height: workspaceCardHeightPx } : undefined),
    [compactSheet, workspaceCardHeightPx],
  );
  const {
    closeWorkspacePreview,
    copyWorkspacePreviewPath,
    copyWorkspacePreviewUrl,
    filteredWorkspaceEntries,
    getWorkspaceDownloadHref,
    getWorkspaceRawHref,
    hideWorkspaceHoverCard,
    loadWorkspaceTree,
    openWorkspaceFilePreview,
    resetWorkspaceState,
    saveWorkspacePreviewMarkdown,
    setWorkspaceAutoRefresh,
    setWorkspacePreviewDraft,
    setWorkspacePreviewFullscreen,
    setWorkspacePreviewMode,
    setWorkspaceQuery,
    showWorkspaceHoverCard,
    workspaceAutoRefresh,
    workspaceCurrentPath,
    workspaceDownloadExtensionSet,
    workspaceError,
    workspaceFileLoading,
    workspaceFiles,
    workspaceHoverCard,
    workspaceLoading,
    workspaceParentPath,
    workspacePathDisplay,
    workspacePreview,
    workspacePreviewCanEdit,
    workspacePreviewDraft,
    workspacePreviewEditorEnabled,
    workspacePreviewFullscreen,
    workspacePreviewMarkdownComponents,
    workspacePreviewSaving,
    workspaceQuery,
    workspaceSearchLoading,
  } = useDashboardWorkspace({
    selectedBotId: selectedBotInfo?.id || '',
    selectedBotDockerStatus: selectedBotInfo?.docker_status || '',
    workspaceDownloadExtensions,
    refreshAttachmentPolicy: async () => ({
      uploadMaxMb: 0,
      allowedAttachmentExtensions: [],
    }),
    notify,
    t: dashboardT,
    isZh,
    fileNotPreviewableLabel: dashboardT.fileNotPreviewable,
  });

  useEffect(() => {
    if (!selectedBotInfo?.id) {
      resetWorkspaceState();
      return;
    }
    resetWorkspaceState();
    void loadWorkspaceTree(selectedBotInfo.id, '');
  }, [loadWorkspaceTree, resetWorkspaceState, selectedBotInfo?.id]);

  useEffect(() => {
    setDockerLogsPage(1);
  }, [selectedBotInfo?.id, effectivePageSize]);

  const fetchDockerLogsPage = useCallback(async (page: number, silent: boolean = false) => {
    if (!selectedBotInfo?.id) {
      setDockerLogs([]);
      setDockerLogsHasMore(false);
      setDockerLogsError('');
      setDockerLogsLoading(false);
      return;
    }
    const safePage = Math.max(1, page);
    if (!silent) setDockerLogsLoading(true);
    setDockerLogsError('');
    try {
      const res = await axios.get<{
        bot_id: string;
        logs?: string[];
        total?: number | null;
        offset?: number;
        limit?: number;
        has_more?: boolean;
        reverse?: boolean;
      }>(`${APP_ENDPOINTS.apiBase}/bots/${selectedBotInfo.id}/logs`, {
        params: {
          offset: (safePage - 1) * effectivePageSize,
          limit: effectivePageSize,
          reverse: true,
        },
      });
      const lines = Array.isArray(res.data?.logs)
        ? res.data.logs.map((line) => String(line || '').trim()).filter(Boolean)
        : [];
      setDockerLogs(lines);
      setDockerLogsHasMore(Boolean(res.data?.has_more));
      setDockerLogsPage(safePage);
    } catch (error: any) {
      setDockerLogs([]);
      setDockerLogsHasMore(false);
      setDockerLogsError(error?.response?.data?.detail || (isZh ? '读取 Docker 日志失败。' : 'Failed to load Docker logs.'));
    } finally {
      if (!silent) {
        setDockerLogsLoading(false);
      }
    }
  }, [effectivePageSize, isZh, selectedBotInfo?.id]);

  useEffect(() => {
    if (!selectedBotInfo?.id) {
      setDockerLogs([]);
      setDockerLogsHasMore(false);
      setDockerLogsError('');
      setDockerLogsLoading(false);
      return;
    }

    let stopped = false;
    void fetchDockerLogsPage(dockerLogsPage, false);

    if (dockerLogsPage !== 1 || String(selectedBotInfo.docker_status || '').toUpperCase() !== 'RUNNING') {
      return () => {
        stopped = true;
      };
    }

    const timer = window.setInterval(() => {
      if (!stopped) {
        void fetchDockerLogsPage(1, true);
      }
    }, 3000);

    return () => {
      stopped = true;
      window.clearInterval(timer);
    };
  }, [dockerLogsPage, fetchDockerLogsPage, selectedBotInfo?.docker_status, selectedBotInfo?.id]);

  useEffect(() => {
    if (compactSheet) {
      setWorkspaceCardHeightPx(null);
      return;
    }

    const cardEl = dockerLogsCardRef.current;
    if (!cardEl) return;

    const syncHeight = () => {
      const nextHeight = Math.round(cardEl.getBoundingClientRect().height);
      setWorkspaceCardHeightPx((current) => (current === nextHeight ? current : nextHeight));
    };

    syncHeight();

    if (typeof ResizeObserver === 'undefined') {
      window.addEventListener('resize', syncHeight);
      return () => window.removeEventListener('resize', syncHeight);
    }

    const observer = new ResizeObserver(() => {
      syncHeight();
    });
    observer.observe(cardEl);
    window.addEventListener('resize', syncHeight);
    return () => {
      observer.disconnect();
      window.removeEventListener('resize', syncHeight);
    };
  }, [compactSheet, selectedBotInfo?.id]);

  return (
    <>
      <div className={`platform-bot-runtime-stack ${compactSheet ? 'is-compact' : ''}`}>
        <section className={`${compactSheet ? 'platform-compact-overview' : 'panel stack'} platform-bot-runtime-section`}>
          {!compactSheet ? <div className="platform-bot-runtime-title">{isZh ? 'Workspace' : 'Workspace'}</div> : null}

          <div className="card platform-bot-runtime-card platform-workspace-card" style={workspaceCardStyle}>
            <div className="platform-bot-runtime-card-head">
              <div>
                <div className="platform-monitor-meta">{dashboardT.workspaceHint}</div>
              </div>
            </div>

            {workspaceError ? <div className="ops-empty-inline">{workspaceError}</div> : null}

            <div className="workspace-toolbar">
              <div className="workspace-path-wrap">
                <div className="workspace-path mono" title={workspacePathDisplay}>
                  {workspacePathDisplay}
                </div>
              </div>
              <div className="workspace-toolbar-actions">
                <LucentIconButton
                  className="workspace-refresh-icon-btn"
                  disabled={workspaceLoading || !selectedBotInfo}
                  onClick={() => selectedBotInfo ? void loadWorkspaceTree(selectedBotInfo.id, workspaceCurrentPath) : undefined}
                  tooltip={isZh ? '刷新工作区' : 'Refresh workspace'}
                  aria-label={isZh ? '刷新工作区' : 'Refresh workspace'}
                >
                  <RefreshCw size={14} className={workspaceLoading ? 'animate-spin' : ''} />
                </LucentIconButton>
                <label className="workspace-auto-switch" title={dashboardT.autoRefresh}>
                  <span className="workspace-auto-switch-label">{dashboardT.autoRefresh}</span>
                  <input
                    type="checkbox"
                    checked={workspaceAutoRefresh}
                    onChange={() => setWorkspaceAutoRefresh((value) => !value)}
                    aria-label={dashboardT.autoRefresh}
                    disabled={!selectedBotInfo}
                  />
                  <span className="workspace-auto-switch-track" />
                </label>
              </div>
            </div>

            <div className="workspace-search-toolbar">
              <ProtectedSearchInput
                value={workspaceQuery}
                onChange={setWorkspaceQuery}
                onClear={() => setWorkspaceQuery('')}
                onSearchAction={() => setWorkspaceQuery(workspaceQuery.trim())}
                debounceMs={200}
                placeholder={dashboardT.workspaceSearchPlaceholder}
                ariaLabel={dashboardT.workspaceSearchPlaceholder}
                clearTitle={dashboardT.clearSearch}
                searchTitle={dashboardT.searchAction}
                name={workspaceSearchInputName}
                id={workspaceSearchInputName}
                disabled={!selectedBotInfo}
              />
            </div>

            <div className="workspace-panel">
              <div className="workspace-list">
                {!selectedBotInfo ? (
                  <div className="ops-empty-inline">{isZh ? '从左侧选择一个 Bot 查看工作区。' : 'Select a bot from the list to view its workspace.'}</div>
                ) : workspaceLoading || workspaceSearchLoading ? (
                  <div className="ops-empty-inline">{dashboardT.loadingDir}</div>
                ) : filteredWorkspaceEntries.length === 0 && workspaceParentPath === null ? (
                  <div className="ops-empty-inline">
                    {workspaceQuery.trim() ? dashboardT.workspaceSearchNoResult : dashboardT.emptyDir}
                  </div>
                ) : (
                  <WorkspaceEntriesList
                    nodes={filteredWorkspaceEntries}
                    workspaceParentPath={workspaceParentPath}
                    selectedBotId={selectedBotInfo.id}
                    workspaceFileLoading={workspaceFileLoading}
                    workspaceDownloadExtensionSet={workspaceDownloadExtensionSet}
                    labels={{
                      download: dashboardT.download,
                      fileNotPreviewable: dashboardT.fileNotPreviewable,
                      folder: dashboardT.folder,
                      goUp: dashboardT.goUp,
                      goUpTitle: dashboardT.goUpTitle,
                      openFolderTitle: dashboardT.openFolderTitle,
                      previewTitle: dashboardT.previewTitle,
                    }}
                    onLoadWorkspaceTree={loadWorkspaceTree}
                    onOpenWorkspaceFilePreview={openWorkspaceFilePreview}
                    onShowWorkspaceHoverCard={showWorkspaceHoverCard}
                    onHideWorkspaceHoverCard={hideWorkspaceHoverCard}
                  />
                )}
              </div>
              <div className="workspace-hint">
                {workspaceFileLoading ? dashboardT.openingPreview : dashboardT.workspaceHint}
              </div>
            </div>

            {selectedBotInfo && !workspaceFiles.length ? (
              <div className="ops-empty-inline">{dashboardT.noPreviewFile}</div>
            ) : null}
          </div>
        </section>

        <section className={`${compactSheet ? 'platform-compact-overview' : 'panel stack'} platform-bot-runtime-section`}>
          {!compactSheet ? <div className="platform-bot-runtime-title">{isZh ? 'Docker Logs' : 'Docker Logs'}</div> : null}

          <div ref={dockerLogsCardRef} className="card platform-bot-runtime-card platform-docker-logs-card">
            <div className="platform-bot-runtime-card-head">
              <div>
                <div className="platform-monitor-meta">
                  {isZh ? '直接按页读取容器日志，按时间倒序展示；无日志时回退到最近运行事件' : 'Reading container logs page by page in reverse chronological order; falls back to runtime events if logs are unavailable'}
                </div>
              </div>
              <div className="platform-bot-runtime-card-actions">
                <LucentIconButton
                  className="workspace-refresh-icon-btn"
                  disabled={dockerLogsLoading || !selectedBotInfo}
                  onClick={() => void fetchDockerLogsPage(dockerLogsPage, false)}
                  tooltip={isZh ? '刷新 Docker Logs' : 'Refresh Docker Logs'}
                  aria-label={isZh ? '刷新 Docker Logs' : 'Refresh Docker Logs'}
                >
                  <RefreshCw size={14} className={dockerLogsLoading ? 'animate-spin' : ''} />
                </LucentIconButton>
                <Terminal size={16} />
              </div>
            </div>

            {selectedBotInfo ? (
              <div className="platform-docker-logs-table-shell">
                {dockerLogsError ? <div className="ops-empty-inline">{dockerLogsError}</div> : null}
                <div className="platform-docker-logs-table-wrap" style={{ height: dockerLogsTableHeightPx }}>
                  <table className="table platform-docker-logs-table">
                    <thead>
                      <tr>
                        <th>{isZh ? '序号' : 'No.'}</th>
                        <th>{isZh ? '类型' : 'Level'}</th>
                        <th>{isZh ? '内容' : 'Message'}</th>
                      </tr>
                    </thead>
                    <tbody>
                      {dockerLogTableRows.map((entry) => {
                        const isPlaceholder = !entry.text;
                        return (
                          <tr
                            key={entry.key}
                            className={isPlaceholder ? 'platform-docker-log-row is-placeholder' : 'platform-docker-log-row'}
                            aria-hidden={isPlaceholder ? 'true' : undefined}
                          >
                            <td className="mono platform-docker-log-index">{entry.index || '\u00A0'}</td>
                            <td>
                              {entry.level ? (
                                <span className={`platform-docker-log-level tone-${entry.tone}`}>{entry.level}</span>
                              ) : (
                                <span className="platform-docker-log-placeholder">&nbsp;</span>
                              )}
                            </td>
                            <td className={`platform-docker-log-text tone-${entry.tone}`}>{entry.text || '\u00A0'}</td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                  {recentLogEntries.length === 0 ? (
                    <div className="ops-empty-inline platform-docker-logs-empty">
                      {dockerLogsLoading
                        ? (isZh ? '读取 Docker 日志中...' : 'Loading Docker logs...')
                        : (isZh ? '暂无 Docker 日志或运行事件。' : 'No Docker logs or runtime events yet.')}
                    </div>
                  ) : null}
                </div>
              </div>
            ) : (
              <div className="ops-empty-inline">{isZh ? '从左侧选择一个 Bot 查看日志。' : 'Select a bot from the list to view logs.'}</div>
            )}

            {selectedBotInfo ? (
              <div className="platform-usage-pager platform-docker-logs-pager">
                <span className="pager-status">
                  {isZh
                    ? `第 ${dockerLogsPage} 页${dockerLogsHasMore ? ' · 可继续加载更早日志' : ''}`
                    : `Page ${dockerLogsPage}${dockerLogsHasMore ? ' · more older logs available' : ''}`}
                </span>
                <div className="platform-usage-pager-actions">
                  <LucentIconButton
                    className="btn btn-secondary btn-sm icon-btn pager-icon-btn"
                    type="button"
                    disabled={dockerLogsPage <= 1 || dockerLogsLoading}
                    onClick={() => void fetchDockerLogsPage(dockerLogsPage - 1, false)}
                    tooltip={isZh ? '更新日志' : 'Newer logs'}
                    aria-label={isZh ? '更新日志' : 'Newer logs'}
                  >
                    <ChevronLeft size={16} />
                  </LucentIconButton>
                  <LucentIconButton
                    className="btn btn-secondary btn-sm icon-btn pager-icon-btn"
                    type="button"
                    disabled={!dockerLogsHasMore || dockerLogsLoading}
                    onClick={() => void fetchDockerLogsPage(dockerLogsPage + 1, false)}
                    tooltip={isZh ? '更早日志' : 'Older logs'}
                    aria-label={isZh ? '更早日志' : 'Older logs'}
                  >
                    <ChevronRight size={16} />
                  </LucentIconButton>
                </div>
              </div>
            ) : null}
          </div>
        </section>
      </div>

      <WorkspacePreviewModal
        isZh={isZh}
        labels={{
          cancel: dashboardT.cancel,
          close: dashboardT.close,
          copyAddress: dashboardT.copyAddress,
          download: dashboardT.download,
          editFile: dashboardT.editFile,
          filePreview: dashboardT.filePreview,
          fileTruncated: dashboardT.fileTruncated,
          save: dashboardT.save,
        }}
        preview={workspacePreview}
        previewFullscreen={workspacePreviewFullscreen}
        previewEditorEnabled={workspacePreviewEditorEnabled}
        previewCanEdit={workspacePreviewCanEdit}
        previewDraft={workspacePreviewDraft}
        previewSaving={workspacePreviewSaving}
        markdownComponents={workspacePreviewMarkdownComponents}
        onClose={closeWorkspacePreview}
        onToggleFullscreen={() => setWorkspacePreviewFullscreen((value) => !value)}
        onCopyPreviewPath={copyWorkspacePreviewPath}
        onCopyPreviewUrl={copyWorkspacePreviewUrl}
        onPreviewDraftChange={setWorkspacePreviewDraft}
        onSavePreviewMarkdown={saveWorkspacePreviewMarkdown}
        onEnterEditMode={() => setWorkspacePreviewMode('edit')}
        onExitEditMode={() => {
          setWorkspacePreviewMode('preview');
          setWorkspacePreviewDraft(workspacePreview?.content || '');
        }}
        getWorkspaceDownloadHref={getWorkspaceDownloadHref}
        getWorkspaceRawHref={getWorkspaceRawHref}
      />

      <WorkspaceHoverCard
        state={workspaceHoverCard}
        isZh={isZh}
        formatWorkspaceTime={formatWorkspaceTime}
        formatBytes={formatBytes}
      />
    </>
  );
}
