import { Image } from '@tarojs/components';
import Taro, { NodesRef, useDidShow, useLoad, useShareAppMessage } from '@tarojs/taro';

import { ArrowUp, ArrowDown } from '@taroify/icons';
import classNames from 'classnames';
import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useState } from 'react';

import AnchorList, { IAnchorListProps } from '@/components/anchor-list';
import AnchorPicker from '@/components/anchor-picker';
import CustomNavigationBar from '@/components/custom-navigation-bar';
import HomePage from '@/components/home-page';
import Overlay from '@/components/overlay';
import PageLoading from '@/components/page-loading';
import PartnerBanner from '@/components/partner-banner';
import SwitchBar from '@/components/switch-bar';
import { APP_TAB_BAR_ID, EventName, OpenSource, PageUrl } from '@/constants/app';
import { EmployType, JobManageStatus } from '@/constants/job';
import { ALL_ANCHOR_SORT_TYPES, ANCHOR_SORT_TYPE_TITLE_MAP, AnchorSortType } from '@/constants/material';
import useInviteCode from '@/hooks/use-invite-code';
import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height';
import useLocation from '@/hooks/use-location';
import { JobManageInfo } from '@/types/job';
import { Coordinate } from '@/types/location';
import { IAnchorFilters } from '@/types/material';
import { logWithPrefix } from '@/utils/common';
import { getLastSelectMyJobId, requestJobManageList, setLastSelectMyJobId } from '@/utils/job';
import { getWxLocation } from '@/utils/location';
import { requestUnreadMessageCount } from '@/utils/message';
import { navigateTo } from '@/utils/route';
import { getCommonShareMessage } from '@/utils/share';
import Toast from '@/utils/toast';
import './index.less';

const PREFIX = 'page-anchor';
const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`;
const CALC_LIST_PROPS: IUseListHeightProps = {
  selectors: [`.${LIST_CONTAINER_CLASS}`, `#${APP_TAB_BAR_ID}`],
  calc: (rects: [NodesRef.BoundingClientRectCallbackResult, NodesRef.BoundingClientRectCallbackResult]) => {
    const [rect, diffRect] = rects;
    return diffRect.top - rect.top;
  },
};
const log = logWithPrefix(PREFIX);

const EmptyTips = (props: { className?: string; height?: number }) => {
  const { className, height } = props;
  return (
    <div className={classNames(`${PREFIX}__tips-container`, className)} style={height ? { height } : undefined}>
      <Image className={`${PREFIX}__empty-box`} src={require('@/statics/svg/empty-box.svg')} mode="aspectFit" />
      <div className={`${PREFIX}__tips-title`}>该条件下还没有主播</div>
    </div>
  );
};

function ListWrapper(props: IAnchorListProps) {
  const { className, jobId, filters, cityCode, sortType, latitude, longitude } = props;
  const listHeight = useListHeight(CALC_LIST_PROPS);
  const [isEmpty, setIsEmpty] = useState(false);

  const handleListEmpty = useCallback(() => {
    setIsEmpty(true);
  }, []);

  useEffect(() => {
    setIsEmpty(false);
  }, [jobId, filters, cityCode, sortType, latitude, longitude]);

  if (isEmpty) {
    return <EmptyTips className={className} height={listHeight} />;
  }

  return <AnchorList listHeight={listHeight} {...props} onListEmpty={handleListEmpty} />;
}

export default function AnchorPage() {
  const location = useLocation();
  const [loading, setLoading] = useState(true);
  const [selectJob, setSelectJob] = useState<JobManageInfo | undefined>();
  const [filters, setFilters] = useState<IAnchorFilters>({ employType: EmployType.All });
  const [showFilter, setShowFilter] = useState<boolean>(false);
  const [sortType, setSortType] = useState<AnchorSortType>(AnchorSortType.Active);
  const [coordinate, setCoordinate] = useState<Coordinate>({
    latitude: location.latitude,
    longitude: location.longitude,
  });
  const inviteCode = useInviteCode();
  log('jobId', selectJob);

  const handleChangeSelectJob = useCallback((select?: JobManageInfo) => {
    log('select job change', select);
    setSelectJob(select);
    setLastSelectMyJobId(select?.id || '');
  }, []);

  const handleClickSwitch = useCallback(
    () => navigateTo(PageUrl.JobSelectMyPublish, { id: selectJob?.id, source: OpenSource.AnchorPage }),
    [selectJob]
  );

  const handleClickSalarySelect = useCallback(() => {
    setShowFilter(!showFilter);
  }, [showFilter]);

  const handleHideFilter = useCallback(() => setShowFilter(false), []);

  const handleFilterChange = useCallback(
    (newFilters: IAnchorFilters) => {
      !isEqual(newFilters, filters) && setFilters(newFilters);
      setShowFilter(false);
    },
    [filters]
  );

  const handleClickSortType = useCallback(async (type: AnchorSortType) => setSortType(type), []);

  const handleJobChange = useCallback(
    (select: JobManageInfo, source: OpenSource) => {
      log('handleJobChange', select, source);
      source === OpenSource.AnchorPage && handleChangeSelectJob(select);
    },
    [handleChangeSelectJob]
  );

  const handlePublishJobChange = useCallback(async () => {
    const { jobResults = [] } = await requestJobManageList({ status: JobManageStatus.Open });
    if (!selectJob) {
      // 之前没有开发中的通告，自动选中第一个开放中的通告
      handleChangeSelectJob(jobResults[0]);
      return;
    }
    const curJob = jobResults.find(j => j.id === selectJob.id);
    if (!curJob) {
      // 之前选中的通告不再开放了，自动切到第一个开放中的通告
      handleChangeSelectJob(jobResults[0]);
    } else if (!isEqual(curJob, selectJob)) {
      // 之前选中的通告发生了变化，尝试更新
      handleChangeSelectJob(curJob);
    }
  }, [selectJob, handleChangeSelectJob]);

  useEffect(() => {
    Taro.eventCenter.on(EventName.SELECT_MY_PUBLISH_JOB, handleJobChange);
    Taro.eventCenter.on(EventName.COMPANY_JOB_PUBLISH_CHANGED, handlePublishJobChange);
    return () => {
      Taro.eventCenter.off(EventName.SELECT_MY_PUBLISH_JOB, handleJobChange);
      Taro.eventCenter.off(EventName.COMPANY_JOB_PUBLISH_CHANGED, handlePublishJobChange);
    };
  }, [handleJobChange, handlePublishJobChange]);

  useEffect(() => {
    const ensureLocation = async () => {
      if (location.latitude || !location.longitude) {
        const res = await getWxLocation();
        if (!res) {
          Toast.info('获取位置信息失败，请重试');
          return;
        }
        const { latitude, longitude } = res;
        setCoordinate({ latitude, longitude });
      }
    };
    ensureLocation();
  }, [location]);

  useLoad(async () => {
    try {
      const { jobResults = [] } = await requestJobManageList({ status: JobManageStatus.Open });
      if (!jobResults.length) {
        Toast.info('当前是根据定位为您展示主播');
        return;
      }
      const lastSelectJobId = getLastSelectMyJobId();
      const lastJob = jobResults.find(job => job.id === lastSelectJobId) || jobResults[0];
      log('lastJob', lastSelectJobId, lastJob);
      handleChangeSelectJob(lastJob);
    } catch (e) {
      console.error(e);
    } finally {
      setLoading(false);
    }
  });

  useShareAppMessage(() => {
    return getCommonShareMessage(true, inviteCode);
  });

  useDidShow(() => requestUnreadMessageCount());

  return (
    <HomePage>
      {!!loading && <PageLoading className={`${PREFIX}__loading`} />}
      <CustomNavigationBar className={`${PREFIX}__navigation-bar`}>
        {selectJob && <SwitchBar title={selectJob.title.substring(0, 4)} onClick={handleClickSwitch} />}
      </CustomNavigationBar>
      <div className={PREFIX}>
        <div className={`${PREFIX}__top-search-bar`}>
          <div className={classNames(`${PREFIX}__sort-type`)}>
            {ALL_ANCHOR_SORT_TYPES.map(type => (
              <div
                key={type}
                className={classNames(`${PREFIX}__sort-item`, { selected: sortType === type })}
                onClick={() => handleClickSortType(type)}
              >
                {ANCHOR_SORT_TYPE_TITLE_MAP[type]}
              </div>
            ))}
          </div>
          <div className={classNames(`${PREFIX}__filter`)} onClick={handleClickSalarySelect}>
            <div className="title">筛选</div>
            {showFilter ? <ArrowUp /> : <ArrowDown />}
          </div>
        </div>
        <div className={`${PREFIX}__banner`}>
          <PartnerBanner />
        </div>
        <ListWrapper
          filters={filters}
          ready={!loading}
          sortType={sortType}
          jobId={selectJob?.id}
          cityCode={selectJob?.cityCode ?? location.cityCode}
          latitude={coordinate.latitude}
          longitude={coordinate.longitude}
          className={LIST_CONTAINER_CLASS}
        />
        <Overlay
          visible={showFilter}
          onClickOuter={handleHideFilter}
          outerClassName={`${PREFIX}__overlay-outer`}
          innerClassName={`${PREFIX}__overlay-inner`}
        >
          <AnchorPicker value={filters} onConfirm={handleFilterChange} />
        </Overlay>
      </div>
    </HomePage>
  );
}
