import { Button } from '@tarojs/components';
import Taro, { useLoad, useShareAppMessage } from '@tarojs/taro';

import { useCallback, useEffect, useState } from 'react';

import CommonDialog from '@/components/common-dialog';
import PageLoading from '@/components/page-loading';
import SafeBottomPadding from '@/components/safe-bottom-padding';
import { EventName, OpenSource, PageUrl } from '@/constants/app';
import { CollectEventName } from '@/constants/event';
import { MaterialViewSource } from '@/constants/material';
import ProfileViewFragment from '@/fragments/profile/view';
import { RESPONSE_ERROR_CODE } from '@/http/constant';
import { HttpError } from '@/http/error';
import { JobManageInfo } from '@/types/job';
import { MaterialProfile } from '@/types/material';
import { IJobMessage } from '@/types/message';
import { copy } from '@/utils/common';
import { collectEvent } from '@/utils/event';
import { requestHasPublishedJob, requestJobDetail } from '@/utils/job';
import { getMaterialShareMessage, requestReadProfile, requestShareProfile } from '@/utils/material';
import { isChatWithSelf, postCreateChat } from '@/utils/message';
import { getPageQuery, navigateBack, navigateTo, redirectTo } from '@/utils/route';
import Toast from '@/utils/toast';

import './index.less';

const PREFIX = 'page-material-view';

interface IViewContext {
  resumeId: string;
  source: MaterialViewSource.AnchorList | MaterialViewSource.Chat;
  jobId?: string;
}

interface IShareContext {
  resumeId: string;
  source: MaterialViewSource.Share;
  shareCode: string;
}

const isShareContext = (context: IViewContext | IShareContext): context is IShareContext => {
  return !!(context as IShareContext).shareCode;
};

const requestProfile = async (context: IViewContext | IShareContext) => {
  if (!context.resumeId) {
    throw new Error('参数错误');
  }
  if (isShareContext(context)) {
    const { resumeId, shareCode } = context;
    const profileDetail = await requestShareProfile({ resumeId, shareCode });
    return profileDetail;
  } else {
    const { resumeId, jobId } = context;
    const profileDetail = await requestReadProfile({ resumeId, jobId });
    return profileDetail;
  }
};

export default function MaterialViewPage() {
  const [contactEnable, setContactEnable] = useState(true);
  const [profile, setProfile] = useState<MaterialProfile | null>(null);
  const [jobId, setJobId] = useState<string>();
  const [errorTips, setErrorTips] = useState<string>('');
  const [publishDialogVisible, setPublishDialogVisible] = useState(false);
  const [certificationDialogVisible, setCertificationDialogVisible] = useState(false);
  const [noTimeDialogVisible, setNoTimeDialogVisible] = useState(false);
  const [noVipLimitVisible, setNoVipLimitVisible] = useState(false);
  const [vipExpiredVisible, setVipExpiredVisible] = useState(false);

  const onDev = useCallback(async () => profile && copy(profile.userId), [profile]);

  const handleClickContact = useCallback(async () => {
    if (!profile) {
      return;
    }
    try {
      if (jobId) {
        const toUserId = profile.userId;
        if (isChatWithSelf(toUserId)) {
          Toast.error('不能与自己聊天');
          return;
        }
        const jobDetail = await requestJobDetail(jobId);
        const chat = await postCreateChat(toUserId);
        const jobMessage: IJobMessage = {
          id: jobDetail.id,
          title: jobDetail.title,
          employType: jobDetail.employType,
          salary: jobDetail.salary,
          lowPriceForFullTime: jobDetail.lowPriceForFullTime,
          highPriceForFullTime: jobDetail.highPriceForFullTime,
          lowPriceForPartyTime: jobDetail.lowPriceForPartyTime,
          highPriceForPartyTime: jobDetail.highPriceForPartyTime,
        };
        navigateTo(PageUrl.MessageChat, { chatId: chat.chatId, job: jobMessage, jobId });
        return;
      }
      if (!(await requestHasPublishedJob())) {
        setPublishDialogVisible(true);
        return;
      }
      navigateTo(PageUrl.JobSelectMyPublish, { source: OpenSource.MaterialViewPage });
    } catch (error) {
      const e = error as HttpError;
      const errorCode = e.errorCode;
      if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
        setErrorTips('今日10次开聊次数已用完，请明日再来');
      } else {
        Toast.error('请求失败请重试');
      }
    }
  }, [profile, jobId]);

  const handleClickNoViewTimes = useCallback(() => {
    setNoTimeDialogVisible(false);
    navigateBack();
  }, []);

  const handleClickGoPublish = useCallback(() => {
    setPublishDialogVisible(false);
    redirectTo(PageUrl.CertificationManage);
  }, []);

  const handleClickGoCertification = useCallback(() => {
    setCertificationDialogVisible(false);
    redirectTo(PageUrl.CertificationStart);
  }, []);

  useEffect(() => {
    const callback = (select: JobManageInfo, source: OpenSource) =>
      source === OpenSource.MaterialViewPage && setJobId(select.id);
    Taro.eventCenter.on(EventName.SELECT_MY_PUBLISH_JOB, callback);
    return () => {
      Taro.eventCenter.off(EventName.SELECT_MY_PUBLISH_JOB, callback);
    };
  }, []);

  useLoad(async () => {
    const context = getPageQuery<IViewContext | IShareContext>();
    try {
      const profileDetail = await requestProfile(context);
      setProfile(profileDetail);
      if (!isShareContext(context)) {
        setJobId(context.jobId);
        Taro.eventCenter.trigger(EventName.VIEW_MATERIAL_SUCCESS, profileDetail.id);
      }
      if (context.source === MaterialViewSource.Chat) {
        setContactEnable(false);
      }
      Taro.setNavigationBarTitle({ title: profileDetail.name || '主播模卡' });
    } catch (error) {
      const e = error as HttpError;
      const errorCode = e.errorCode;
      collectEvent(CollectEventName.VIEW_MATERIAL_FAILED, { context, error: e.info?.() || e.message });
      console.error(e);
      if (errorCode === RESPONSE_ERROR_CODE.BOSS_NOT_AUTH) {
        setCertificationDialogVisible(true);
      } else if (errorCode === RESPONSE_ERROR_CODE.NO_PUBLISHED_JOB) {
        setPublishDialogVisible(true);
      } else if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
        setNoTimeDialogVisible(true);
      } else if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_FREE_BALANCE) {
        setNoVipLimitVisible(true);
      } else if (errorCode === RESPONSE_ERROR_CODE.BOSS_VIP_EXPIRED) {
        setVipExpiredVisible(true);
      } else {
        Toast.error(e.message || '加载失败');
      }
    }
  });

  useShareAppMessage(async () => {
    const shareMessage = await getMaterialShareMessage(profile);
    return shareMessage as BL.Anything;
  });

  if (!profile) {
    return (
      <>
        <PageLoading />
        <CommonDialog
          content="要查看主播详情，请先完成实人认证"
          confirm="去认证"
          visible={certificationDialogVisible}
          onClose={() => setCertificationDialogVisible(false)}
          onClick={handleClickGoCertification}
        />
        <CommonDialog
          content="请先发布一个认证通告"
          confirm="去发布"
          visible={publishDialogVisible}
          onClose={() => setPublishDialogVisible(false)}
          onClick={handleClickGoPublish}
        />
        <CommonDialog
          content="请先发布一个认证通告"
          confirm="去发布"
          visible={noVipLimitVisible}
          onClose={() => setNoVipLimitVisible(false)}
          onClick={handleClickGoPublish}
        >
          <div className={`${PREFIX}__no-time-tips`}>免费查看模卡详情次数已用完</div>
        </CommonDialog>
        <CommonDialog
          content="请先发布一个认证通告"
          confirm="去发布"
          visible={vipExpiredVisible}
          onClose={() => setVipExpiredVisible(false)}
          onClick={handleClickGoPublish}
        />
        <CommonDialog
          content="今日查看模卡详情次数已用完"
          confirm="确定"
          visible={noTimeDialogVisible}
          onClick={handleClickNoViewTimes}
        >
          <div className={`${PREFIX}__no-time-tips`}> 当前每个通告单日查看次数为 20 次</div>
        </CommonDialog>
      </>
    );
  }

  return (
    <div className={PREFIX}>
      <ProfileViewFragment profile={profile} editable={false} onDev={onDev} />
      <div className={`${PREFIX}__footer`}>
        <div className={`${PREFIX}__footer__buttons`}>
          <Button className={`${PREFIX}__footer__buttons__share`} openType="share">
            分享
          </Button>
          {contactEnable && (
            <Button className={`${PREFIX}__footer__buttons__contact`} onClick={handleClickContact}>
              立即联系
            </Button>
          )}
        </div>
        <SafeBottomPadding />
      </div>
      <div>
        <CommonDialog
          content="请先发布一个认证通告"
          confirm="去发布"
          visible={publishDialogVisible}
          onClose={() => setPublishDialogVisible(false)}
          onClick={handleClickGoPublish}
        />
        <CommonDialog
          content={errorTips}
          confirm="确定"
          visible={!!errorTips}
          onClose={() => setErrorTips('')}
          onClick={() => setErrorTips('')}
        />
      </div>
    </div>
  );
}
