/**
 * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
 * SPDX-License-Identifier: MIT
 */

import { FC, useContext, useEffect, useState } from 'react';

import classnames from 'classnames';
import { useService, I18n } from '@flowgram.ai/free-layout-editor';
import { Button, SideSheet, Switch, Tag } from '@douyinfe/semi-ui';
import { IconClose, IconPlay, IconSpin } from '@douyinfe/semi-icons';

import { TestRunJsonInput } from '../testrun-json-input';
import { TestRunForm } from '../testrun-form';
import { NodeStatusGroup } from '../node-status-bar/group';
// 改为使用后端运行服务
import { CustomService } from '../../../services';
import { SidebarContext } from '../../../context';
import { IconCancel } from '../../../assets/icon-cancel';

import styles from './index.module.less';

interface TestRunSidePanelProps {
  visible: boolean;
  onCancel: () => void;
}

export const TestRunSidePanel: FC<TestRunSidePanelProps> = ({ visible, onCancel }) => {
  const customService = useService(CustomService);
  const { nodeId: sidebarNodeId, setNodeId } = useContext(SidebarContext);

  const [isRunning, setRunning] = useState(false);
  const [values, setValues] = useState<Record<string, unknown>>({});
  const [errors, setErrors] = useState<string[]>();
  const [result, setResult] = useState<
    | {
        ok?: boolean;
        ctx: any;
        logs: string[];
      }
    | undefined
  >();

  // en - Use localStorage to persist the JSON mode state
  const [inputJSONMode, _setInputJSONMode] = useState(() => {
    const savedMode = localStorage.getItem('testrun-input-json-mode');
    return savedMode ? JSON.parse(savedMode) : false;
  });

  const setInputJSONMode = (checked: boolean) => {
    _setInputJSONMode(checked);
    localStorage.setItem('testrun-input-json-mode', JSON.stringify(checked));
  };

  const extractErrorMsg = (logs: string[] | undefined): string | undefined => {
    if (!logs || logs.length === 0) return undefined;
    const patterns = [/failed/i, /error/i, /panic/i];
    for (const line of logs) {
      if (patterns.some((p) => p.test(line))) return line;
    }
    return logs[logs.length - 1];
  };

  const onTestRun = async () => {
    if (isRunning) {
      // 后端运行不可取消，这里直接忽略重复点击
      return;
    }
    setResult(undefined);
    setErrors(undefined);
    setRunning(true);
    try {
      // 运行前保存（静默），确保后端 YAML 与编辑器一致；若保存失败则不继续运行
      const saved = await customService.save({ silent: true });
      if (!saved) {
        setErrors([I18n.t('Save failed, cannot run')]);
        return;
      }
      const runRes = await customService.run(values);
      if (runRes) {
        // 若后端返回 ok=false，则视为失败并展示失败信息与日志
        if ((runRes as any).ok === false) {
          setResult(runRes as any);
          const err = extractErrorMsg((runRes as any).logs) || I18n.t('Run failed');
          setErrors([err]);
        } else {
          setResult(runRes as any);
        }
      } else {
        setErrors([I18n.t('Run failed')]);
      }
    } catch (e: any) {
      setErrors([e?.message || I18n.t('Run failed')]);
    } finally {
      setRunning(false);
    }
  };

  const onClose = async () => {
    setValues({});
    setRunning(false);
    onCancel();
  };

  // 当测试运行面板打开时，自动关闭右侧节点编辑侧栏，避免两个 SideSheet 重叠
  useEffect(() => {
    if (visible) {
      setNodeId(undefined);
    }
  }, [visible]);

  useEffect(() => {
    if (sidebarNodeId) {
      onCancel();
    }
  }, [sidebarNodeId]);

  const renderRunning = (
    <div className={styles['testrun-panel-running']}> 
      <IconSpin spin size="large" />
      <div className={styles.text}>{I18n.t('Running...')}</div>
    </div>
  );

  const renderStatus = (
    <div style={{ marginBottom: 8 }}>
      {result?.ok === true && <Tag color="green">{I18n.t('Success')}</Tag>}
      {(errors?.length || result?.ok === false) && (
        <Tag color="red">{I18n.t('Failed')}</Tag>
      )}
    </div>
  );

  const renderForm = (
    <div className={styles['testrun-panel-form']}>
      <div className={styles['testrun-panel-input']}>
        <div className={styles.title}>{I18n.t('Input Form')}</div>
        <div>{I18n.t('JSON Mode')}</div>
        <Switch
          checked={inputJSONMode}
          onChange={(checked: boolean) => setInputJSONMode(checked)}
          size="small"
        />
      </div>
      {renderStatus}
      {errors?.map((e) => (
        <div className={styles.error} key={e}>
          {e}
        </div>
      ))}
      {inputJSONMode ? (
        <TestRunJsonInput values={values} setValues={setValues} />
      ) : (
        <TestRunForm values={values} setValues={setValues} />
      )}
      {/* 展示后端返回的执行信息 */}
      <NodeStatusGroup title={I18n.t('Context')} data={result?.ctx} optional disableCollapse />
      <NodeStatusGroup title={I18n.t('Logs')} data={result?.logs} optional disableCollapse />
    </div>
  );

  const renderButton = (
    <Button
      onClick={onTestRun}
      icon={isRunning ? <IconCancel /> : <IconPlay size="small" />}
      className={classnames(styles.button, {
        [styles.running]: isRunning,
        [styles.default]: !isRunning,
      })}
    >
      {isRunning ? I18n.t('Running...') : I18n.t('Test Run')}
    </Button>
  );

  return (
    <SideSheet
      title={I18n.t('Test Run')}
      visible={visible}
      mask={false}
      motion={false}
      onCancel={onClose}
      width={500}
      headerStyle={{
        display: 'none',
      }}
      bodyStyle={{
        padding: 0,
      }}
      style={{
        background: 'none',
        boxShadow: 'none',
      }}
    >
      <div className={styles['testrun-panel-container']}>
        <div className={styles['testrun-panel-header']}>
          <div className={styles['testrun-panel-title']}>{I18n.t('Test Run')}</div>
          <Button
            className={styles['testrun-panel-title']}
            type="tertiary"
            icon={<IconClose />}
            size="small"
            theme="borderless"
            onClick={onClose}
          />
        </div>
        <div className={styles['testrun-panel-content']}>
          {isRunning ? renderRunning : renderForm}
        </div>
        <div className={styles['testrun-panel-footer']}>{renderButton}</div>
      </div>
    </SideSheet>
  );
};
