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

import { Dialog } from '@taroify/core';
import React, { useCallback, useEffect, useState } from 'react';

import { CertificationStatusIcon } from '@/components/certification-status';
import CommonDialog from '@/components/common-dialog';
import DevDiv from '@/components/dev-div';
import JobRecommendList from '@/components/job-recommend-list';
import { JoinGroupHint } from '@/components/join-group-hint';
import LoginButton from '@/components/login-button';
import PageLoading from '@/components/page-loading';
import { PrejobPopup } from '@/components/prejob-popup';
import ProductJobDialog from '@/components/product-dialog/job';
import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
import { EventName, PageUrl, RoleType } from '@/constants/app';
import { CertificationStatusType } from '@/constants/company';
import { CollectEventName, ReportEventId } from '@/constants/event';
import { EMPLOY_TYPE_TITLE_MAP, GET_CONTACT_TYPE, JobManageStatus } from '@/constants/job';
import { ProductType } from '@/constants/product';
import useInviteCode from '@/hooks/use-invite-code';
import useUserInfo from '@/hooks/use-user-info';
import useRoleType from '@/hooks/user-role-type';
import { RESPONSE_ERROR_CODE } from '@/http/constant';
import { HttpError } from '@/http/error';
import store from '@/store';
import { cacheJobId } from '@/store/actions';
import { JobDetails } from '@/types/job';
import { IMaterialMessage } from '@/types/message';
import { switchRoleType } from '@/utils/app';
import { copy, logWithPrefix } from '@/utils/common';
import { collectEvent, reportEvent } from '@/utils/event';
import { getJobSalary, getJobTitle, postPublishJob, requestJobDetail } from '@/utils/job';
import { calcDistance, isValidLocation } from '@/utils/location';
import { requestProfileDetail } from '@/utils/material';
import { isChatWithSelf, postCreateChat } from '@/utils/message';
import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner';
import { requestProductBalance, requestProductUseRecord } from '@/utils/product';
import { getJumpUrl, getPageQuery, navigateTo } from '@/utils/route';
import { getCommonShareMessage } from '@/utils/share';
import { formatDate } from '@/utils/time';
import Toast from '@/utils/toast';
import { isNeedCreateMaterial } from '@/utils/user';

import './index.less';

const PREFIX = 'job-detail';
const log = logWithPrefix(PREFIX);

const getMapCallout = (data: JobDetails): MapProps.callout | undefined => {
  if (!data.jobLocation?.address) {
    return;
  }
  return {
    display: 'ALWAYS',
    content: data.jobLocation.address,
    color: '#000000',
    bgColor: '#FFFFFF',
    fontSize: 12,
    textAlign: 'center',
    anchorX: 0,
    anchorY: 0,
    borderRadius: 4,
    borderWidth: 0,
    borderColor: '#FFFFFF',
    padding: 4,
  };
};

const AnchorFooter = (props: { data: JobDetails }) => {
  const { data } = props;
  const [errorTips, setErrorTips] = useState<string>('');
  const [dialogVisible, setDialogVisible] = useState(false);
  const [showMaterialGuide, setShowMaterialGuide] = useState(false);

  const handleClickContact = useCallback(async () => {
    log('handleClickContact');
    if (!data) {
      return;
    }
    reportEvent(ReportEventId.CLICK_JOB_CONTACT);
    try {
      const needCreateMaterial = await isNeedCreateMaterial();

      if (data.sourcePlat !== 'bl') {
        if (needCreateMaterial) {
          const result = await requestProductUseRecord(ProductType.VIP, { jobId: data.id });
          if (!result) {
            const [time, isPaidVip] = await requestProductBalance(ProductType.VIP);
            if (time <= 0 || !isPaidVip) {
              setShowMaterialGuide(true);
              return;
            }
          }
        }
      }
      if (data.isAuthed) {
        const toUserId = data.userId;
        if (isChatWithSelf(toUserId)) {
          Toast.error('不能与自己聊天');
          return;
        }
        const chat = await postCreateChat(toUserId);
        let materialMessage: null | IMaterialMessage = null;
        if (!needCreateMaterial) {
          const profile = await requestProfileDetail();
          if (profile) {
            materialMessage = {
              id: profile.id,
              name: profile.name,
              age: profile.age,
              height: profile.height,
              weight: profile.weight,
              shoeSize: profile.shoeSize,
              gender: profile.gender,
              workedSecCategoryStr: profile.workedSecCategoryStr,
            };
          }
        }
        navigateTo(PageUrl.MessageChat, {
          chatId: chat.chatId,
          initText: !materialMessage,
          material: materialMessage,
          jobId: data.id,
        });
      } else {
        setDialogVisible(true);
      }
    } catch (error) {
      const e = error as HttpError;
      const errorCode = e.errorCode;
      if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
        setErrorTips('今日开聊次数已用完，请明日再来');
      } else {
        Toast.error('请求失败请重试');
      }
    }
  }, [data]);

  const handleDialogHidden = useCallback(() => {
    setDialogVisible(false);
  }, []);
  const handleConfirmPrejob = useCallback((type: GET_CONTACT_TYPE) => {
    setShowMaterialGuide(false);
    if (GET_CONTACT_TYPE.VIP === type) {
      setDialogVisible(true);
    }
  }, []);
  return (
    <>
      <div className={`${PREFIX}__footer`}>
        <Button className={`${PREFIX}__share-button`} openType="share">
          分享
        </Button>
        <LoginButton className={`${PREFIX}__contact-publisher`} onClick={handleClickContact}>
          {data.isAuthed ? '在线沟通' : '立即联系'}
        </LoginButton>
      </div>
      <div>
        {dialogVisible && <ProductJobDialog data={data} onClose={handleDialogHidden} />}
        {showMaterialGuide && (
          <PrejobPopup onCancel={() => setShowMaterialGuide(false)} onConfirm={handleConfirmPrejob} />
        )}
        <CommonDialog
          content={errorTips}
          confirm="确定"
          visible={!!errorTips}
          onClose={() => setErrorTips('')}
          onClick={() => setErrorTips('')}
        />
      </div>
    </>
  );
};

const CompanyFooter = (props: { data: JobDetails }) => {
  const { data } = props;
  const [showBuy, setShowBuy] = useState(false);
  const userInfo = useUserInfo();

  const handleClickEdit = useCallback(() => navigateTo(PageUrl.JobPublish, { jobId: data.id }), [data]);

  const handlePublishJob = useCallback(async () => {
    try {
      if (userInfo.bossAuthStatus !== CertificationStatusType.Success) {
        store.dispatch(cacheJobId(data.id));
        navigateTo(PageUrl.CertificationStart);
        return;
      }
      Taro.showLoading();
      await postPublishJob(data.id);
      Taro.eventCenter.trigger(EventName.COMPANY_JOB_PUBLISH_CHANGED);
      setShowBuy(false);
      Toast.success('发布成功');
      Taro.hideLoading();
    } catch (error) {
      Taro.hideLoading();
      const e = error as HttpError;
      const errorCode = e.errorCode;
      const errorMsg = e.info?.() || e.message;
      collectEvent(CollectEventName.PUBLISH_OPEN_JOB_FAILED, { jobId: data.id, error: e.info?.() || e.message });
      if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
        Toast.info('您购买的产品已耗尽使用次数');
        setShowBuy(true);
      } else if (errorCode === RESPONSE_ERROR_CODE.BOSS_VIP_EXPIRED) {
        Toast.info('该通告已到期，请创建新通告', 3000);
      } else {
        Toast.error(errorMsg || '发布失败请重试', 3000);
      }
      console.error(e);
    }
  }, [data]);

  return (
    <>
      <div className={`${PREFIX}__footer`}>
        <Button className={`${PREFIX}__share-button`} onClick={handleClickEdit}>
          编辑
        </Button>
        <Button
          disabled={data.status === JobManageStatus.Open}
          className={`${PREFIX}__contact-publisher`}
          onClick={handlePublishJob}
        >
          发布通告
        </Button>
      </div>
      <Dialog open={showBuy} onClose={() => setShowBuy(false)}>
        <Dialog.Content>
          <CompanyPublishJobBuy onNext={handlePublishJob} />
        </Dialog.Content>
      </Dialog>
    </>
  );
};

export default function JobDetail() {
  const roleType = useRoleType();
  const userInfo = useUserInfo();
  const [data, setData] = useState<JobDetails | null>(null);
  const isOwner = roleType === RoleType.Company && userInfo.userId === data?.userId;
  const inviteCode = useInviteCode();

  const onDev = useCallback(async () => data && copy(data.id), [data]);

  const handleClickMap = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation();

      if (!data?.jobLocation) {
        return;
      }
      Taro.openLocation({
        longitude: Number(data.jobLocation.longitude),
        latitude: Number(data.jobLocation.latitude),
        address: data.jobLocation.address,
      });
    },
    [data]
  );

  useEffect(() => {
    const callback = async (jobId: string) => {
      try {
        const res = await requestJobDetail(jobId);
        setData(res);
      } catch (e) {
        console.error(e);
      }
    };
    Taro.eventCenter.on(EventName.JOB_UPDATE, callback);
    return () => {
      Taro.eventCenter.off(EventName.JOB_UPDATE, callback);
    };
  }, []);

  useLoad(async () => {
    const query = getPageQuery<Pick<JobDetails, 'id'> & { c: string; share: string }>();

    if (query?.share === 'true') {
      switchRoleType(RoleType.Anchor);
    }
    getInviteCodeFromQueryAndUpdate(query);
    const jobId = query?.id;
    if (!jobId) {
      return;
    }
    Taro.eventCenter.trigger(EventName.VIEW_JOB_SUCCESS, jobId);
    try {
      const res = await requestJobDetail(jobId);
      setData(res);
    } catch (e) {
      console.error(e);
      Toast.error('出错了，请重试');
    }
  });

  useShareAppMessage(() => {
    if (!data) {
      return getCommonShareMessage({ inviteCode });
    }

    return {
      title: getJobTitle(data) || '',
      path: getJumpUrl(PageUrl.JobDetail, { id: data.id, share: true, c: inviteCode }),
    };
  });

  if (!data) {
    return <PageLoading />;
  }

  return (
    <div className={PREFIX}>
      <div className={`${PREFIX}__container`}>
        <div className={`${PREFIX}__header`}>
          <div className={`${PREFIX}__header-info`}>
            <DevDiv className={`${PREFIX}__header-title`} OnDev={onDev}>
              {getJobTitle(data)}
            </DevDiv>
            <div className={`${PREFIX}__employ-type`}>{EMPLOY_TYPE_TITLE_MAP[data.employType]}</div>
          </div>
          <div className={`${PREFIX}__salary`}>{getJobSalary(data)}</div>
          <div className={`${PREFIX}__update-time`}>{`${formatDate(data.updated)}更新`}</div>
          <div className={`${PREFIX}__tips`}>请注意甄别通告真假，谨防上当</div>
          <div className={`${PREFIX}__publisher`}>
            <div className={`${PREFIX}__publisher-name`}>{`发布人：${data.publisher}`}</div>
            {data.isAuthed && (
              <CertificationStatusIcon
                className={`${PREFIX}__certification-type`}
                status={CertificationStatusType.Success}
                small
              />
            )}
            <Image
              mode="aspectFit"
              className={`${PREFIX}__publisher-avatar`}
              src={data.publisherAvatar || require('@/statics/svg/wechat.svg')}
            />
          </div>
          {data.companyName && <div className={`${PREFIX}__company`}>{`公司：${data.companyName}`}</div>}
        </div>

        {!isOwner && <JoinGroupHint />}

        <div className={`${PREFIX}__content`}>
          <div className={`${PREFIX}__content-title`}>职位描述</div>
          <div className={`${PREFIX}__tags`}>
            {(data.tags || []).map((keyword: string, index) => (
              <div className={`${PREFIX}__tag`} key={index}>
                {keyword}
              </div>
            ))}
          </div>
          <Text className={`${PREFIX}__description`}>{data.sourceText}</Text>
          <div className={`${PREFIX}__address-wrapper`}>
            <Image className={`${PREFIX}__distance-icon`} src={require('@/statics/svg/location.svg')} />
            <div className={`${PREFIX}__detailed-address`}>{data.jobLocation?.address}</div>
          </div>
          {data.distance && (
            <div className={`${PREFIX}__distance-wrapper`}>
              <Image className={`${PREFIX}__distance-icon`} src={require('@/statics/svg/location.svg')} />
              <div className={`${PREFIX}__distance`}>{calcDistance(data.distance)}</div>
            </div>
          )}
          {isValidLocation(data.jobLocation) && (
            <div className={`${PREFIX}__map__wrapper`} onClick={handleClickMap}>
              <Map
                enableZoom={false}
                enableScroll={false}
                className={`${PREFIX}__map`}
                latitude={Number(data.jobLocation.latitude)}
                longitude={Number(data.jobLocation.longitude)}
                markers={[
                  {
                    id: 0,
                    latitude: Number(data.jobLocation.latitude),
                    longitude: Number(data.jobLocation.longitude),
                    callout: getMapCallout(data),
                    iconPath: '',
                    width: 20,
                    height: 36,
                  },
                ]}
                onError={() => Toast.error('地图加载错误')}
              />
              <div className={`${PREFIX}__map__mask`} onClick={handleClickMap} />
            </div>
          )}
        </div>
        {!isOwner && <JobRecommendList />}
        <div className={`${PREFIX}__bottom-space`} />
      </div>
      {!isOwner && <AnchorFooter data={data} />}
      {isOwner && <CompanyFooter data={data} />}
    </div>
  );
}
