import { useState } from 'react';
import { LoadingOutlined, RocketOutlined, SmileOutlined, UploadOutlined } from '@ant-design/icons';
import { Button, Divider, Result, Spin, Upload, message } from 'antd';
import { useTranslation } from 'react-i18next';
import semver from 'semver';

import * as api from '@/api/application.ts';

import { Preview } from './preview.tsx';

type UpdateProps = {
  setIsLocked: (isClosable: boolean) => void;
};

type Status = '' | 'loading' | 'updating' | 'outdated' | 'latest' | 'failed';

export const Update = ({ setIsLocked }: UpdateProps) => {
  const { t } = useTranslation();

  const [status, setStatus] = useState<Status>('');
  const [currentVersion, setCurrentVersion] = useState('');
  const [latestVersion, setLatestVersion] = useState('');
  const [updateUrl, setUpdateUrl] = useState('');
  const [errMsg, setErrMsg] = useState('');

  // Auto-check disabled
  // useEffect(() => {
  //   checkForUpdates();
  // }, []);

  function checkForUpdates() {
    if (status === 'loading') return;
    setStatus('loading');

    api
      .getVersion()
      .then((rsp: any) => {
        if (rsp.code !== 0 || !rsp.data) {
          setStatus('failed');
          setErrMsg(t('settings.update.queryFailed'));
          return;
        }

        setCurrentVersion(rsp.data.current);
        setLatestVersion(rsp.data.latest);
        setUpdateUrl(rsp.data.update_url);

        const isLatest = semver.gte(rsp.data.current, rsp.data.latest);
        setStatus(isLatest ? 'latest' : 'outdated');
      })
      .catch(() => {
        setStatus('failed');
        setErrMsg(t('settings.update.queryFailed'));
      });
  }

  function update() {
    if (status !== 'outdated') return;

    setIsLocked(true);
    setStatus('updating');

    api
      .update()
      .then((rsp: any) => {
        if (rsp.code !== 0) {
          setStatus('failed');
          setErrMsg(t('settings.update.updateFailed'));
        }
      })
      .finally(() => {
        setTimeout(() => {
          setIsLocked(false);
          setErrMsg('');

          window.location.reload();
        }, 12000);
      });
  }

  const handleServerUpload = (file: File) => {
    setIsLocked(true);
    message.loading('Uploading server binary...', 0);
    api.updateServer(file).then((rsp: any) => {
      message.destroy();
      if (rsp.code === 0) {
        message.success('Server updated successfully. Restarting...');
        setTimeout(() => {
          setIsLocked(false);
          window.location.reload();
        }, 5000);
      } else {
        message.error('Server update failed: ' + rsp.msg);
        setIsLocked(false);
      }
    }).catch(() => {
      message.destroy();
      message.error('Server update failed');
      setIsLocked(false);
    });
    return false;
  };

  const handleWebUpload = (file: File) => {
    setIsLocked(true);
    message.loading('Uploading web resources...', 0);
    api.updateWeb(file).then((rsp: any) => {
      message.destroy();
      if (rsp.code === 0) {
        message.success('Web resources updated successfully. Reloading...');
        setTimeout(() => {
          setIsLocked(false);
          window.location.reload();
        }, 2000);
      } else {
        message.error('Web update failed: ' + rsp.msg);
        setIsLocked(false);
      }
    }).catch(() => {
      message.destroy();
      message.error('Web update failed');
      setIsLocked(false);
    });
    return false;
  };

  return (
    <>
      <div className="text-base font-bold">{t('settings.update.title')}</div>
      <Divider />

      <Preview />

      <div className="my-[20px] h-px bg-neutral-500/10" />

      {updateUrl && (
        <div className="mb-4 text-xs text-gray-500">
          Update Server: {updateUrl}
        </div>
      )}

      <div className="flex min-h-[400px] flex-col justify-between">
        {status === '' && (
          <div className="flex justify-center pt-24">
            <Button type="primary" onClick={checkForUpdates}>
              Check for Updates
            </Button>
          </div>
        )}

        {status === 'loading' && (
          <div className="flex justify-center pt-24">
            <Spin indicator={<LoadingOutlined spin />} size="large" />
          </div>
        )}

        {status === 'updating' && (
          <div className="flex flex-col items-center justify-center space-y-10 pb-10 pt-24">
            <Spin size="large" />
            <span className="text-blue-600">{t('settings.update.updating')}</span>
          </div>
        )}

        {status === 'latest' && (
          <Result
            status="success"
            icon={<SmileOutlined />}
            title={currentVersion}
            subTitle={t('settings.update.isLatest')}
            extra={[
              <Button key="confirm" onClick={checkForUpdates}>
                {t('settings.update.title')}
              </Button>
            ]}
          />
        )}

        {status === 'outdated' && (
          <Result
            status="warning"
            icon={<RocketOutlined />}
            title={`${currentVersion} -> ${latestVersion}`}
            subTitle={t('settings.update.available')}
            extra={[
              <Button key="confirm" type="primary" onClick={update}>
                {t('settings.update.confirm')}
              </Button>
            ]}
          />
        )}

        {status === 'failed' && <Result subTitle={errMsg} extra={[<Button onClick={() => setStatus('')}>Retry</Button>]} />}

        <div className="mt-8">
          <Divider orientation="left">Manual Update</Divider>
          <div className="flex space-x-4 justify-center">
            <Upload beforeUpload={handleServerUpload} showUploadList={false}>
              <Button icon={<UploadOutlined />}>Upload Server (Binary)</Button>
            </Upload>
            <Upload beforeUpload={handleWebUpload} showUploadList={false}>
              <Button icon={<UploadOutlined />}>Upload Web (tar.gz)</Button>
            </Upload>
          </div>
        </div>

        <div className="flex justify-center mt-8">
          <Button
            type="link"
            size="small"
            href="https://github.com/sipeed/NanoKVM/blob/main/CHANGELOG.md"
            target="_blank"
          >
            CHANGELOG
          </Button>
        </div>
      </div>
    </>
  );
};
