import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { WebviewWindow } from "@tauri-apps/api/webviewWindow";
import { revealItemInDir } from "@tauri-apps/plugin-opener";
import { Button, Divider, InputNumber, Layout, Menu, notification, Space, theme, Tooltip } from "antd";
import {
  countPendingTasks,
  listPendingTasks,
  markTaskDone,
  type Task,
} from "./lib/tasks";
import {
  EVT_RECORDING_FAILED,
  EVT_RECORDING_FINISHED,
  EVT_RECORD_SHORTCUT,
  EVT_SCREENSHOT_FAILED,
  EVT_SCREENSHOT_FINISHED,
  EVT_TASKS_IMPORTED,
  type RecordingFailedPayload,
  type RecordingFinishedPayload,
  type RecordShortcutPayload,
  type RecordState,
  type ScreenshotFailedPayload,
  type ScreenshotFinishedPayload,
  type TaskAssets,
} from "./types/ipc";
import { capturePage } from "./lib/capture";
import {
  cancelRecording,
  getRecordState,
  startRecording,
  stopRecording,
  subscribeRecordState,
} from "./lib/recorder";
import "./App.css";
import {
  BankOutlined,
  CheckCircleOutlined,
  CloseOutlined,
  FileImageOutlined,
  FolderOpenOutlined,
  LinkOutlined,
  LoadingOutlined,
  MinusOutlined,
  OrderedListOutlined,
  PictureOutlined,
  PlayCircleFilled,
  PlusOutlined,
  StopOutlined,
  VideoCameraOutlined,
} from "@ant-design/icons";

const { Header, Content, Sider } = Layout;

/**
 * 与 Rust 端常量保持一致（src-tauri/src/lib.rs）：
 *   LEFT_PANEL_WIDTH = 180
 *   TOOLBAR_HEIGHT   = 48
 *
 * 导出以避免 noUnusedLocals 误报；后续如有组件需要可直接 import。
 */

/** 工具栏右侧的尺寸预设（统一横屏：宽 × 高） */
const SIZE_PRESETS = [
  { label: "1280×720", w: 1280, h: 720 },
  { label: "1920×1080", w: 1920, h: 1080 },
  { label: "1024×768", w: 1024, h: 768 }
];


/** 点条目：把 url 加载到子 webview，并把 task_id 一并下发（用于截图命名 + 自动截图回调） */
async function loadInWebview(taskId: string, url: string) {
  try {
    await invoke("navigate_webview", { taskId, url });
  } catch (e) {
    console.error("webview 加载失败:", e);
  }
}

/** 点条目右侧图标：调系统浏览器打开 */
// async function openInBrowser(url: string) {
//   try {
//     await openUrl(url);
//   } catch (e) {
//     console.error("打开系统浏览器失败:", e);
//   }
// }

function App() {
  // 当前激活的任务 id（仅用于左栏视觉高亮）
  const [activeId, setActiveId] = useState<string | null>(null);

  // 待处理任务（status=0）的真实列表，来自 sqlite
  const [tasks, setTasks] = useState<Task[]>([]);

  const [contentSize, setContentSize] = useState<{ w: number; h: number }>({ w: 1280, h: 720 });
  const contentSizeRef = useRef(contentSize);
  const [customMode, setCustomMode] = useState(false);
  const isCustomSize = useCallback(() => {
    return !SIZE_PRESETS.find(({ w, h }) => w == contentSize.w && h == contentSize.h);
  }, [contentSize])
  // 录制状态机（由 lib/recorder.ts 内部单例维护，这里订阅以驱动按钮）
  const [recordState, setRecordState] = useState<RecordState>(getRecordState());

  // 当前任务的产物文件信息（截图 / 录制 mp4 是否存在 + 路径），驱动右侧三个按钮的 disabled
  const [assets, setAssets] = useState<TaskAssets | null>(null);

  // activeId 的最新值快照，供 listen 闭包中读取（避免在每个 effect 上加 activeId 依赖
  // 导致 listen 频繁重订）
  const activeIdRef = useRef<string | null>(activeId);
  useEffect(() => {
    activeIdRef.current = activeId;
  }, [activeId]);

  // antd 6 notification 必须用 hook + contextHolder 才能正确取到主题
  const [notifyApi, notifyContext] = notification.useNotification();

  /**
   * 重新拉取 sqlite 中 status=0 的任务列表。
   * 调用场景：
   *   - 首次挂载
   *   - 监听到 EVT_TASKS_IMPORTED（导入窗口写入完）
   *   - "完成" 按钮把当前任务标记为已完成后
   */
  const reloadTasks = useCallback(async (): Promise<Task[]> => {
    try {
      const list = await listPendingTasks();
      setTasks(list);
      return list;
    } catch (e) {
      console.error("加载任务列表失败:", e);
      notifyApi.error({
        message: "加载任务失败",
        description: String(e),
        duration: 6,
      });
      return [];
    }
  }, [notifyApi]);

  /** 启动「批量导入 URL」窗口（独立 WebviewWindow，label = "import"） */
  const openImportWindow = useCallback(async () => {
    try {
      // 若已存在直接 setFocus，避免重复创建
      const existing = await WebviewWindow.getByLabel("import");
      if (existing) {
        await existing.setFocus();
        return;
      }
      const w = new WebviewWindow("import", {
        url: "import.html",
        title: "导入 URL",
        width: 560,
        height: 480,
        resizable: true,
        // 主窗口是 decorations: false，这里给原生标题栏方便用户拖动/关闭
        decorations: true,
      });
      w.once("tauri://error", (e) => {
        console.error("导入窗口创建失败:", e);
      });
    } catch (e) {
      console.error("openImportWindow 失败:", e);
      notifyApi.error({
        message: "无法打开导入窗口",
        description: String(e),
        duration: 6,
      });
    }
  }, [notifyApi]);

  function handleSelectTask({ key }: { key: string }) {
    const t = tasks.find((v) => v.id == key);
    if (!t) {
      return;
    }
    setActiveId(t.id);
    void loadInWebview(t.id, t.url);
  }

  /** 重新查询指定任务的产物文件信息（截图 + mp4） */
  const refreshAssets = useCallback(async (taskId: string | null) => {
    if (!taskId) {
      setAssets(null);
      return;
    }
    try {
      const a = await invoke<TaskAssets>("query_task_assets", { taskId });
      setAssets(a);
    } catch (e) {
      console.error("query_task_assets 失败:", e);
      setAssets(null);
    }
  }, []);

  // activeId 变化时刷新 assets（切换任务后右侧按钮要按新任务的文件存在性变 enabled/disabled）
  useEffect(() => {
    void refreshAssets(activeId);
  }, [activeId, refreshAssets]);

  // 首次挂载：从 sqlite 加载待处理任务；若为空则拉起「批量导入 URL」窗口。
  // 依赖项故意只放 reloadTasks / openImportWindow（都用 useCallback 稳定引用），
  // 避免 tasks 变化导致再次拉起导入窗口。
  useEffect(() => {
    (async () => {
      const pending = await countPendingTasks().catch(() => 0);
      const list = await reloadTasks();
      if (pending === 0 && list.length === 0) {
        setTimeout(() =>
          openImportWindow(), 500);
      }
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // 监听导入窗口发出的 tasks-imported 事件，刷新主列表
  useEffect(() => {
    let unlisten: UnlistenFn | null = null;
    let disposed = false;
    (async () => {
      const u = await listen<{ count: number }>(EVT_TASKS_IMPORTED, (e) => {
        notifyApi.success({
          message: "导入完成",
          description: `已写入 ${e.payload.count} 条任务`,
          duration: 3,
        });
        void reloadTasks();
      });
      if (disposed) u();
      else unlisten = u;
    })();
    return () => {
      disposed = true;
      unlisten?.();
    };
  }, [notifyApi, reloadTasks]);

  /** 工具栏 "完成" 按钮：把当前激活任务标记为已完成（status=1）→ 刷新 → 清空选中 */
  const handleCompleteTask = useCallback(async () => {
    if (!activeId) return;
    try {
      await markTaskDone(activeId);
      notifyApi.success({
        message: "任务已完成",
        description: `任务 ${activeId} 已从列表移除`,
        duration: 3,
      });
      setActiveId(null);
      const list = await reloadTasks();
      // 若已无任务，自动再拉起一次导入窗口（用户可继续粘贴）
      if (list.length === 0) {
        await openImportWindow();
      }
    } catch (e) {
      notifyApi.error({
        message: "标记完成失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [activeId, reloadTasks, openImportWindow, notifyApi]);

  /** 手动截图：交给 Rust 命令，结果通过事件回推（统一与自动截图的提示路径） */
  const handleManualCapture = useCallback(async () => {
    if (!activeId) return;
    try {
      await capturePage(activeId);
    } catch (e) {
      // Rust 侧失败时已经 emit 过 screenshot-failed，这里仅打日志兜底
      console.error("手动截图失败:", e);
    }
  }, [activeId]);

  // 订阅 Rust 端的截图事件，统一用 notification 提示
  useEffect(() => {
    let unlistenFinished: UnlistenFn | null = null;
    let unlistenFailed: UnlistenFn | null = null;
    let disposed = false;

    (async () => {
      const u1 = await listen<ScreenshotFinishedPayload>(EVT_SCREENSHOT_FINISHED, (e) => {
        const { taskId, path, auto } = e.payload;
        notifyApi.success({
          message: auto ? "自动截图完成" : "截图完成",
          description: `任务 ${taskId} → ${path}`,
          duration: 4,
        });
        // 当前选中即此任务时刷新 assets，让预览图按钮立即变可点
        if (activeIdRef.current === taskId) {
          void refreshAssets(taskId);
        }
      });
      const u2 = await listen<ScreenshotFailedPayload>(EVT_SCREENSHOT_FAILED, (e) => {
        const { taskId, auto, error } = e.payload;
        notifyApi.error({
          message: auto ? "自动截图失败" : "截图失败",
          description: `任务 ${taskId}：${error}`,
          duration: 6,
        });
      });

      if (disposed) {
        u1();
        u2();
      } else {
        unlistenFinished = u1;
        unlistenFailed = u2;
      }
    })();

    return () => {
      disposed = true;
      unlistenFinished?.();
      unlistenFailed?.();
    };
  }, [notifyApi, refreshAssets]);

  // 订阅录制状态机变化，驱动按钮 UI 切换
  useEffect(() => {
    return subscribeRecordState(setRecordState);
  }, []);

  // 订阅 Rust 端的录制事件（finalize 转码完成 / 失败），统一 notification 提示。
  // 与截图事件订阅采用同一套 disposed 模式，避免 StrictMode 双调用的清理竞态。
  useEffect(() => {
    let unlistenFinished: UnlistenFn | null = null;
    let unlistenFailed: UnlistenFn | null = null;
    let disposed = false;

    (async () => {
      const u1 = await listen<RecordingFinishedPayload>(EVT_RECORDING_FINISHED, (e) => {
        const { taskId, path } = e.payload;
        notifyApi.success({
          message: "录制完成",
          description: `任务 ${taskId} → ${path}`,
          duration: 5,
        });
        if (activeIdRef.current === taskId) {
          void refreshAssets(taskId);
        }
      });
      const u2 = await listen<RecordingFailedPayload>(EVT_RECORDING_FAILED, (e) => {
        const { taskId, error } = e.payload;
        notifyApi.error({
          message: "录制失败",
          description: `任务 ${taskId}：${error}`,
          duration: 6,
        });
      });

      if (disposed) {
        u1();
        u2();
      } else {
        unlistenFinished = u1;
        unlistenFailed = u2;
      }
    })();

    return () => {
      disposed = true;
      unlistenFinished?.();
      unlistenFailed?.();
    };
  }, [notifyApi, refreshAssets]);

  // 组件卸载兜底：若正在录制 / 暂停 / 转码中，主动取消，避免悬挂 stream
  useEffect(() => {
    return () => {
      void cancelRecording();
    };
  }, []);

  /** 开始按钮：仅在 idle + 已选任务 时可点；Rust 端 spawn ffmpeg 子进程录屏 */
  const handleStartRecord = useCallback(async () => {
    if (recordState !== "idle" || !activeId) return;
    try {
      await startRecording(activeId);
    } catch (e) {
      notifyApi.error({
        message: "开始录制失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [recordState, activeId, notifyApi]);

  /** 停止按钮：触发 ffmpeg 优雅退出 + 落盘 */
  const handleStopRecord = useCallback(async () => {
    if (recordState !== "recording") return;
    try {
      await stopRecording();
      // 成功时由 EVT_RECORDING_FINISHED 事件统一提示；这里不重复弹
    } catch (e) {
      // 本地异常（如内部状态不一致）兜底提示；ffmpeg 失败由 EVT_RECORDING_FAILED 处理
      notifyApi.error({
        message: "停止录制失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [recordState, notifyApi]);

  /** 全局快捷键派发：F9 = 开始，F11 = 停止 */
  const handleShortcut = useCallback(
    async (action: "start" | "stop") => {
      try {
        if (action === "start") {
          if (recordState !== "idle") return;
          if (!activeId) {
            notifyApi.warning({
              message: "无法开始录制",
              description: "请先在左栏选择一个任务",
              duration: 4,
            });
            return;
          }
          await startRecording(activeId);
        } else if (action === "stop") {
          if (recordState === "recording") {
            await stopRecording();
          }
        }
      } catch (e) {
        notifyApi.error({
          message: "快捷键操作失败",
          description: String(e),
          duration: 6,
        });
      }
    },
    [recordState, activeId, notifyApi],
  );

  // 订阅 Rust 端的全局快捷键事件 (F9 / F11)
  useEffect(() => {
    let unlisten: UnlistenFn | null = null;
    let disposed = false;
    (async () => {
      const u = await listen<RecordShortcutPayload>(EVT_RECORD_SHORTCUT, (e) => {
        void handleShortcut(e.payload.action);
      });
      if (disposed) u();
      else unlisten = u;
    })();
    return () => {
      disposed = true;
      unlisten?.();
    };
  }, [handleShortcut]);

  /** 打开当前任务产物所在的文件夹：优先 reveal mp4 → png → 兜底打开 screenshots 目录 */
  const handleOpenFolder = useCallback(async () => {
    if (!assets) return;
    const target = assets.recording_exists
      ? assets.recording_path
      : assets.screenshot_exists
        ? assets.screenshot_path
        : assets.screenshots_dir;
    try {
      await revealItemInDir(target);
    } catch (e) {
      notifyApi.error({
        message: "打开文件夹失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [assets, notifyApi]);

  /** 在新 WebviewWindow 中预览截图 */
  const handlePreviewImage = useCallback(async () => {
    if (!assets?.screenshot_exists) return;
    try {
      await invoke("open_preview_window", {
        path: assets.screenshot_path,
        kind: "image",
      });
    } catch (e) {
      notifyApi.error({
        message: "图片预览失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [assets, notifyApi]);

  /** 在新 WebviewWindow 中预览录制 mp4 */
  const handlePreviewVideo = useCallback(async () => {
    if (!assets?.recording_exists) return;
    try {
      await invoke("open_preview_window", {
        path: assets.recording_path,
        kind: "video",
      });
    } catch (e) {
      notifyApi.error({
        message: "视频预览失败",
        description: String(e),
        duration: 6,
      });
    }
  }, [assets, notifyApi]);

  // 开始按钮的图标 / tooltip
  const startConfig = (() => {
    if (recordState === "stopping") {
      return { icon: <LoadingOutlined />, tip: "正在停止…" };
    }
    if (recordState === "recording") {
      // 视觉上保持 Play 图标，但 disabled
      return { icon: <PlayCircleFilled />, tip: "录制中…（F11 停止）" };
    }
    return {
      icon: <PlayCircleFilled />,
      tip: activeId ? "开始录制（F9）" : "请先选择任务",
    };
  })();

  // 开始按钮仅在 idle 且已选任务时可点；其它状态 disabled
  const startDisabled = recordState !== "idle" || !activeId;
  // 停止按钮仅在 recording 时可点
  const stopDisabled = recordState !== "recording";

  const [collapsed, setCollapsed] = useState(false);

  const applyWorkAreaSize = useCallback(async (w?: number, h?: number) => {
    if (w && h) {
      setContentSize({ w, h });
      contentSizeRef.current = { w, h };
    } else {
      w = contentSize.w;
      h = contentSize.h;
    }
    try {
      // 先调主窗口，避免子 webview 越界
      await invoke("set_window_size", {
        width: w + (collapsed ? 30 : 180) + 4,
        height: h + 48 + 24 + 4,
        contentX: (collapsed ? 30 : 180) + 2,
        contentY: 50,
        contentWidth: w,
        contentHeight: h
      });
    } catch (e) {
      console.error("调整尺寸失败 ", e);
    }
  }, [contentSize, setContentSize]);

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

  // 录制状态机（RecordState 类型已抽到 src/types/ipc.ts），录制功能下一阶段接入
  const handleCollaspsed = useCallback(async (c: boolean) => {
    setCollapsed(c);
    try {
      // 先调主窗口，避免子 webview 越界
      await invoke("set_window_size", {
        width: contentSize.w + (collapsed ? 30 : 180),
        height: contentSize.h + 60,
        contentWidth: contentSize.w,
        contentHeight: contentSize.h
      });
    } catch (e) {
      console.error("调整尺寸失败:", e);
    }
  }, [setCollapsed]);
  const {
    token: { colorBgContainer },
  } = theme.useToken();

  const [statusColor] = useState("#888");
  const [statusText] = useState("请选择任务");

  // 当前窗口句柄，用于自定义标题栏的最小化 / 关闭
  const appWindow = useMemo(() => getCurrentWindow(), []);

  const handleAppClose = useCallback(async () => {
    try {
      await appWindow.close();
    } catch (e) {
      console.error("appWindow.close 失败:", e);
    }
  }, [appWindow]);

  const handleAppMinimize = useCallback(async () => {
    try {
      await appWindow.minimize();
    } catch (e) {
      console.error("appWindow.minimize 失败:", e);
    }
  }, [appWindow]);

  return (
    <Layout className="m-0 p-0 h-full overflow-hidden">
      {/* data-tauri-drag-region：Tauri 2 原生支持，webview 层会自动 hook mousedown
       *   触发系统级拖窗，比手写 startDragging 更稳定（Windows 尤其如此）。 */}
      <Header
        className="app-title h-8 select-none"
        style={{ paddingLeft: 8 }}
        data-tauri-drag-region
      >
        <div className="flex h-full flex-row items-center" data-tauri-drag-region>
          <Space size={4}>
            <Button
              className="app-close"
              icon={<CloseOutlined />}
              size="large"
              type="text"
              data-tauri-drag-region="no-drag"
              onClick={handleAppClose}
            />
            <Button icon={<BankOutlined />} disabled size="large" type="text" />
            <Button
              className="app-minimize"
              icon={<MinusOutlined />}
              size="large"
              type="text"
              data-tauri-drag-region="no-drag"
              onClick={handleAppMinimize}
            />
          </Space>
          <div className="w-32" />
          <Tooltip title={activeId ? "截图整页（覆盖之前的自动截图）" : "请先选择任务"} placement="right">
            <Button

              shape="circle"
              icon={<PictureOutlined />}
              disabled={!activeId}
              onClick={handleManualCapture}
            />
          </Tooltip>
          <Divider orientation="vertical" />
          {/* 开始按钮：仅 idle + 已选任务时可点 */}
          <Tooltip title={startConfig.tip} placement="right">
            <Button

              shape="circle"
              icon={startConfig.icon}
              disabled={startDisabled}
              onClick={() => void handleStartRecord()}
            />
          </Tooltip>
          {/* 停止按钮：仅 recording 时可用 */}
          <Tooltip
            title={
              stopDisabled
                ? "无进行中的录制"
                : "停止录制并落盘 mp4（F11）"
            }
            placement="right"
          >
            <Button

              shape="circle"
              icon={<StopOutlined />}
              disabled={stopDisabled}
              onClick={() => void handleStopRecord()}
            />
          </Tooltip>
          {/* 完成按钮：把当前任务在 sqlite 标记为 status=1，从主列表移除 */}
          <Tooltip
            title={activeId ? "标记当前任务为已完成" : "请先选择任务"}
            placement="right"
          >
            <Button
              shape="circle"
              icon={<CheckCircleOutlined />}
              disabled={!activeId}
              onClick={() => void handleCompleteTask()}
            />
          </Tooltip>
          <Divider orientation="vertical" />
          {/* 打开文件夹：reveal mp4 → png → 兜底 screenshots 目录 */}
          <Tooltip
            title={
              !activeId
                ? "请先选择任务"
                : assets?.recording_exists
                  ? "在文件管理器中显示录制视频"
                  : assets?.screenshot_exists
                    ? "在文件管理器中显示截图"
                    : "打开截图目录"
            }
            placement="right"
          >
            <Button

              shape="circle"
              icon={<FolderOpenOutlined />}
              disabled={!assets}
              onClick={() => void handleOpenFolder()}
            />
          </Tooltip>
          {/* 预览截图：仅当 png 存在 */}
          <Tooltip
            title={
              !assets?.screenshot_exists
                ? "暂无截图可预览"
                : "在新窗口预览截图"
            }
            placement="right"
          >
            <Button

              shape="circle"
              icon={<FileImageOutlined />}
              disabled={!assets?.screenshot_exists}
              onClick={() => void handlePreviewImage()}
            />
          </Tooltip>
          {/* 预览视频：仅当 mp4 存在 */}
          <Tooltip
            title={
              !assets?.recording_exists
                ? "暂无录制视频可预览"
                : "在新窗口预览录制视频"
            }
            placement="right"
          >
            <Button

              shape="circle"
              icon={<VideoCameraOutlined />}
              disabled={!assets?.recording_exists}
              onClick={() => void handlePreviewVideo()}
            />
          </Tooltip>
          <div className="flex-1">

          </div>
          {!customMode ? (
            <>
              {SIZE_PRESETS.map((p) => (
                <Button
                  key={p.label}
                  type={contentSize.w == p.w && contentSize.h == p.h ? "primary" : undefined}

                  onClick={contentSize.w != p.w || contentSize.h != p.h ? () => applyWorkAreaSize(p.w, p.h) as any : undefined}
                >
                  {p.label}
                </Button>
              ))}
              {isCustomSize() ?
                <Button type="primary" onClick={() => setCustomMode(true)}>
                  自定义（{contentSize.w}x{contentSize.h}）
                </Button> : <Button onClick={() => setCustomMode(true)}>
                  自定义
                </Button>}
            </>
          ) : (
            <>
              <InputNumber

                min={200}
                max={3840}
                value={contentSize.w}
                onChange={(v) => setContentSize({ w: v || 0, h: contentSize.h })}
                style={{ width: 80 }}
              />
              <span className="text-gray-7 select-none">×</span>
              <InputNumber

                min={200}
                max={2160}
                value={contentSize.h}
                onChange={(v) => setContentSize({ w: contentSize.w, h: v || 0 })}
                style={{ width: 80 }}
              />
              <Button
                type="primary"
                onClick={() => {
                  setCustomMode(false);
                  applyWorkAreaSize();

                }}
              >
                应用
              </Button>
              <Button onClick={() => {
                setContentSize(contentSizeRef.current)
                setCustomMode(false);
              }}>
                取消
              </Button>
            </>
          )}
        </div>
      </Header>
      <Layout>
        <Sider className="select-none" collapsible collapsed={collapsed} onCollapse={(c) => handleCollaspsed(c)} width={180} style={{ background: colorBgContainer }}>
          <div className="h-full w-full flex-row">
            <div className="flex justify-between items-center text-md pl-1 font-bold text-white"><OrderedListOutlined />{collapsed ? '' : '所有任务'}<Button icon={<PlusOutlined />} onClick={openImportWindow} /> </div>
            <div className="flex-1 overflow-y-auto">
              <Menu
                mode="vertical"
                defaultSelectedKeys={[activeId || '']}
                selectedKeys={[activeId || '']}
                style={{ borderInlineEnd: 0, height: '100%' }}
                onClick={handleSelectTask}

              >
                {tasks.map((t) => <Menu.Item icon={<LinkOutlined />} key={t.id}>
                  {t.id}
                </Menu.Item>
                )}
              </Menu>
            </div>
          </div>
        </Sider>
        <Layout className="flex flex-row">
          <Content className="w-full m-0 p-1 flex-1" />
          <div className="w-full h-6 flex items-center bg-red-400 px-2 text-gray-3">
            <div className="bg-gray-6 rounded-full w-3 h-3 m-2" style={{ backgroundColor: statusColor }} />
            <div className="w-32">{statusText}</div>
            <span className="flex-1">{notifyContext}</span>
          </div>
        </Layout>
      </Layout>
    </Layout >
  );
}




export default App;