import { useState, useEffect, useCallback } from 'react';
import { json, type ActionFunction, type LoaderFunction } from '@remix-run/node';
import { useLoaderData, useSubmit, useNavigation } from '@remix-run/react';
import { spawn, type ChildProcess } from 'child_process';

type SshxStatus = 'running' | 'stopped';

interface LoaderData {
  status: SshxStatus;
  output: string;
  link: string | null;
  shell: string | null;
}

let sshxProcess: ChildProcess | null = null;
let sshxOutput = '';

const extractFromOutput = (output: string, regex: RegExp): string | null => {
  const match = output.match(regex);
  return match ? match[1] : null;
};

const handleProcessOutput = (data: Buffer) => {
  sshxOutput += data.toString();
};

const handleProcessClose = () => {
  sshxProcess = null;
  sshxOutput += '\nSSHX进程已结束。';
};

export const loader: LoaderFunction = async () => {
  const status: SshxStatus = sshxProcess ? 'running' : 'stopped';
  const link = extractFromOutput(sshxOutput, /Link:\s+(https:\/\/sshx\.io\/s\/[^\s]+)/);
  const shell = extractFromOutput(sshxOutput, /Shell:\s+([^\n]+)/);
  return json<LoaderData>({ status, output: sshxOutput, link, shell });
};

export const action: ActionFunction = async ({ request }) => {
  const formData = await request.formData();
  const action = formData.get('action');

  if (action === 'start' && !sshxProcess) {
    sshxProcess = spawn('/home/pn/sshx/sshx', ['-q']);  // 修改这里，添加 '-q' 参数
    sshxProcess.stdout?.on('data', handleProcessOutput);
    sshxProcess.stderr?.on('data', handleProcessOutput);
    sshxProcess.on('close', handleProcessClose);
    return json({ status: 'started' });
  } else if (action === 'stop' && sshxProcess) {
    sshxProcess.kill();
    handleProcessClose();
    return json({ status: 'stopped' });
  }

  return json({ error: '无效操作' }, { status: 400 });
};

export default function Sshx() {
  const { status, output, link, shell } = useLoaderData<LoaderData>();
  const submit = useSubmit();
  const navigation = useNavigation();
  const [localOutput, setLocalOutput] = useState(output);
  const [startTime, setStartTime] = useState<number | null>(null);

  const refreshData = useCallback(() => {
    submit(null, { method: 'get', replace: true });
  }, [submit]);

  const stopSshx = useCallback(() => {
    submit({ action: 'stop' }, { method: 'post' });
    setStartTime(null);
  }, [submit]);

  useEffect(() => {
    let interval: NodeJS.Timeout | null = null;
    let timer: NodeJS.Timeout | null = null;

    if (status === 'running') {
      interval = setInterval(refreshData, 60000); // 每60秒更新一次
      
      if (startTime === null) {
        setStartTime(Date.now());
      } else {
        const elapsedTime = Date.now() - startTime;
        const remainingTime = 600000 - elapsedTime; // 10分钟 = 600000毫秒
        
        if (remainingTime > 0) {
          timer = setTimeout(stopSshx, remainingTime);
        } else {
          stopSshx();
        }
      }
    } else {
      setStartTime(null);
    }

    return () => {
      if (interval) clearInterval(interval);
      if (timer) clearTimeout(timer);
    };
  }, [refreshData, status, startTime, stopSshx]);

  useEffect(() => {
    setLocalOutput(output);
  }, [output]);

  const isLoading = navigation.state === 'submitting' || navigation.state === 'loading';

  const handleAction = (action: 'start' | 'stop') => {
    if (action === 'start') {
      setStartTime(Date.now());
    } else {
      setStartTime(null);
    }
    submit({ action }, { method: 'post' });
    setTimeout(refreshData, 100);
  };

  // 计算剩余时间
  const remainingTime = startTime ? Math.max(0, 600 - Math.floor((Date.now() - startTime) / 1000)) : 0;

  return (
    <div className="container mx-auto px-4 py-8 max-w-3xl">
      <h1 className="text-3xl font-bold text-primary mb-6 pb-2 border-b-2 border-primary">SSHX控制面板</h1>
      <div className="mb-6">
        <p className="text-lg font-semibold">
          状态: <span className={`${status === 'running' ? 'text-green-600' : 'text-red-600'} font-bold`}>
            {status === 'running' ? '运行中' : '已停止'}
          </span>
        </p>
      </div>
      <div className="flex space-x-4 mb-6">
        <button
          onClick={() => handleAction('start')}
          className={`px-4 py-2 rounded-md text-white transition-colors duration-300 ${
            status === 'running' || isLoading
              ? 'bg-gray-400 cursor-not-allowed'
              : 'bg-green-500 hover:bg-green-600'
          }`}
          disabled={status === 'running' || isLoading}
        >
          启动SSHX
        </button>
        <button
          onClick={() => handleAction('stop')}
          className={`px-4 py-2 rounded-md text-white transition-colors duration-300 ${
            status === 'stopped' || isLoading
              ? 'bg-gray-400 cursor-not-allowed'
              : 'bg-red-500 hover:bg-red-600'
          }`}
          disabled={status === 'stopped' || isLoading}
        >
          停止SSHX
        </button>
      </div>
      {status === 'running' && (
        <div className="bg-blue-100 border border-blue-300 rounded-md p-4 mb-6">
          <p className="mb-2 text-blue-800">
            <strong className="font-semibold">链接:</strong>{' '}
            {link ? (
              <a href={link} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline font-medium">
                {link}
              </a>
            ) : (
              <span className="text-gray-600">暂不可用</span>
            )}
          </p>
          <p className="text-blue-800">
            <strong className="font-semibold">Shell:</strong> <span className="font-medium">{shell || '暂不可用'}</span>
          </p>
          <p className="text-blue-800">
            <strong className="font-semibold">剩余时间:</strong> <span className="font-medium">{remainingTime} 秒</span>
          </p>
        </div>
      )}
      <h2 className="text-2xl font-semibold text-secondary mb-4">输出:</h2>
      <pre className="bg-gray-800 text-blue-600 p-4 rounded-md border border-gray-600 font-mono text-sm whitespace-pre-wrap overflow-x-auto max-h-96 overflow-y-auto">
        {localOutput}
      </pre>
    </div>
  );
}
