import { Button } from '@heroui/button';
import type { Selection } from '@react-types/shared';
import { useLocalStorage } from '@uidotdev/usehooks';
import clsx from 'clsx';
import { useEffect, useRef, useState } from 'react';
import toast from 'react-hot-toast';
import { IoDownloadOutline } from 'react-icons/io5';

import key from '@/const/key';
import { colorizeLogLevelWithTag } from '@/utils/terminal';

import WebUIManager, { Log } from '@/controllers/webui_manager';

import type { XTermRef } from '../xterm';
import XTerm from '../xterm';
import LogLevelSelect from './log_level_select';

const RealTimeLogs = () => {
  const Xterm = useRef<XTermRef>(null);
  const [logLevel, setLogLevel] = useState<Selection>(
    new Set(['info', 'warn', 'error'])
  );
  const [dataArr, setDataArr] = useState<Log[]>([]);
  const [backgroundImage] = useLocalStorage<string>(key.backgroundImage, '');
  const hasBackground = !!backgroundImage;

  const onDownloadLog = () => {
    const logContent = dataArr
      .filter((log) => {
        if (logLevel === 'all') {
          return true;
        }
        return logLevel.has(log.level);
      })
      .map((log) => colorizeLogLevelWithTag(log.message, log.level))
      .join('\r\n');
    const blob = new Blob([logContent], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'napcat.log';
    a.click();
    URL.revokeObjectURL(url);
  };

  const writeStream = () => {
    try {
      const _data = dataArr
        .filter((log) => {
          if (logLevel === 'all') {
            return true;
          }
          return logLevel.has(log.level);
        })
        .map((log) => colorizeLogLevelWithTag(log.message, log.level))
        .join('\r\n');
      Xterm.current?.clear();
      Xterm.current?.write(_data);
    } catch (error) {
      console.error(error);
      toast.error('获取实时日志失败');
    }
  };

  useEffect(() => {
    writeStream();
  }, [logLevel, dataArr]);

  useEffect(() => {
    const subscribeLogs = () => {
      try {
        const source = WebUIManager.getRealTimeLogs((data) => {
          setDataArr((prev) => {
            const newData = [...prev, ...data];
            if (newData.length > 1000) {
              newData.splice(0, newData.length - 1000);
            }
            return newData;
          });
        });
        return () => {
          source.close();
        };
      } catch (_error) {
        toast.error('获取实时日志失败');
      }
    };

    const close = subscribeLogs();
    return () => {
      console.log('close');
      close?.();
    };
  }, []);

  return (
    <>
      <title>实时日志 - NapCat WebUI</title>
      <div className={clsx(
        'flex items-center gap-2 p-2 rounded-2xl border backdrop-blur-sm transition-all shadow-sm mb-4',
        hasBackground ? 'bg-white/20 dark:bg-black/10 border-white/40 dark:border-white/10' : 'bg-white/60 dark:bg-black/40 border-white/40 dark:border-white/10'
      )}>
        <LogLevelSelect
          selectedKeys={logLevel}
          onSelectionChange={setLogLevel}
        />
        <Button
          className='flex-shrink-0'
          onPress={onDownloadLog}
          startContent={<IoDownloadOutline className='text-lg' />}
          color='primary'
          variant='flat'
        >
          下载日志
        </Button>
      </div>
      <div className='flex-1 h-full overflow-hidden'>
        <XTerm ref={Xterm} />
      </div>
    </>
  );
};

export default RealTimeLogs;
