import * as React from 'react';
import { useEffect, useState, useMemo, useRef } from 'react';
import { Skeleton } from 'antd';
import { DeployInfo, GAInfo, PageStep, stageMapping } from '../common';
import { DeployingCard } from './deployingCard';
import { DeployInfoCard } from './deployInfoCard';
import { InfoStepActions } from './infoStepActions';
import { EmptyCard } from './emptyCard';
import { UnsupportCard } from './unsupportCard';
import ReactGA from 'react-ga';

interface InfoProps {
    rpc: any;
    language: string;
    languageMap: { [key: string]: string };
    platform: string;
    initRegion: string;
    initStage: string;
    isSupport: boolean;
    tencentOnly: boolean;
    deployInfo?: DeployInfo;
    setStep: (value: PageStep) => void;
    setInfo: (value: DeployInfo) => void;
    logout: () => void;
    updateConfig: (data: any) => void;
}

export const InfoStep = (props: InfoProps) => {
    const { rpc, languageMap, platform, isSupport, deployInfo, setInfo, updateConfig } = props;
    const [deploying, setDeploying] = useState<boolean>(false);
    const [percentage, setPercentage] = useState<number>(0);
    const [processId, setProcessId] = useState<number>();
    const [projectName, setProjectName] = useState<string>('');
    const [displayPercentage, setDisplayPercentage] = useState<number>(0);
    const [perInterval, setPerInterval] = useState<NodeJS.Timeout>();
    const [loading, setLoading] = useState<boolean>(true);
    const actionsRef = useRef<any>();

    const getDeployInfo = async () => {
        const deployInfo = await rpc.invoke('getDeployInfo', [platform]);
        setInfo(deployInfo);
        setLoading(false);
    };

    const deployingHandler = (pid: number, name: string) => {
        setDeploying(true);
        setProcessId(pid);
        setProjectName(name);
    };
    rpc.registerMethod({ func: deployingHandler, name: 'deploying' });
    rpc.registerMethod({ func: getDeployInfo, name: 'reloadDeployInfo' });
    rpc.registerMethod({
        func: (data: DeployInfo) => {
            if (data) {
                setInfo({ ...data, projectName });
            }
            setDeploying(false);
            setPercentage(0);
        },
        name: 'deployFinished',
    });
    rpc.registerMethod({ func: (value: number) => setPercentage(value), name: 'percentage' });
    rpc.registerMethod({
        func: (data: GAInfo) => {
            const typeMapping = { success: '部署成功', failed: '部署失败', cancelled: '取消部署' };
            ReactGA.event({
                category: 'DeployKit',
                action: `${typeMapping[data.type]}`,
                label: `部署平台：${platform}  ${data.msg ? `失败原因：${data.msg}` : ''}`,
            });
        },
        name: 'reportGA',
    });

    const reload = async (data: { region?: string; stage?: string }) => {
        setLoading(true);
        await rpc.invoke('setConfig', [data, platform]);
        updateConfig(data);
        await getDeployInfo();
    };

    const deploy = () => {
        ReactGA.event({
            category: 'DeployKit',
            action: '点击部署',
            label: `部署平台：${platform}`,
        });

        setPercentage(0);
        setDeploying(true);
        rpc.invoke('deploy', [platform]);
        const intv = setInterval(() => {
            setDisplayPercentage(v => {
                if (v < 10) {
                    return v + 1;
                }
                return v;
            });
        }, 300);
        setPerInterval(intv);
    };

    const triggerDeploy = () => {
        if (isSupport) {
            deploy();
        }
    };

    const openLink = () => {
        if (deployInfo?.link) {
            rpc.invoke('openWebLink', [deployInfo.link]);
        } else {
            rpc.invoke('errAlert', [languageMap['message.info.open.error']]);
        }
    };

    const renderInfo = () => {
        if (deployInfo?.projectName) {
            return (
                <>
                    <DeployInfoCard info={deployInfo} isSupport={isSupport} redeploy={triggerDeploy} open={openLink} />
                    {!isSupport && <UnsupportCard rpc={rpc} />}
                </>
            );
        } else {
            return (
                <EmptyCard
                    rpc={rpc}
                    isSupport={isSupport}
                    stage={stageMapping[actionsRef.current.getStage()]}
                    triggerDeploy={triggerDeploy}
                />
            );
        }
    };

    const limitationMapping: { [key: number]: number } = { 5: 10, 10: 50, 50: 90, 90: 99 };
    useMemo(() => {
        if (perInterval) {
            clearInterval(perInterval);
        }
        if (!percentage) {
            setDisplayPercentage(0);
        } else {
            setDisplayPercentage(percentage);
            const maxPercentage = limitationMapping[percentage];
            const intv = setInterval(() => {
                setDisplayPercentage(v => {
                    return v < maxPercentage ? v + 1 : v;
                });
            }, 200);
            setPerInterval(intv);
        }
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [percentage]);

    useEffect(() => {
        getDeployInfo();
        return () => {
            if (perInterval) {
                clearInterval(perInterval);
            }
        };
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <>
            <div className='info-header'>
                <div className='info-platform'>{languageMap[`home.platform.${platform}`]}</div>
                <InfoStepActions cRef={actionsRef} {...props} reload={reload} />
            </div>

            {loading ? (
                <Skeleton active />
            ) : (
                <div style={{ marginTop: 12 }}>
                    {deploying ? (
                        <DeployingCard
                            stage={actionsRef.current.getStage()}
                            projectName={projectName}
                            percentage={displayPercentage}
                            close={() => rpc.invoke('cancelDeploy', [processId])}
                        />
                    ) : (
                        renderInfo()
                    )}
                </div>
            )}
        </>
    );
};
