import { Image } from '@tarojs/components';
import { NodesRef, useDidHide } from '@tarojs/taro';

import { Tabs } from '@taroify/core';
import { ArrowUp, ArrowDown } from '@taroify/icons';
import classNames from 'classnames';
import { useCallback, useEffect, useState, MouseEvent } from 'react';

import JobList, { IJobListProps } from '@/components/job-list';
import Overlay from '@/components/overlay';
import SalarySelect from '@/components/salary-select';
import SearchInput from '@/components/search';
import { APP_TAB_BAR_ID, PageUrl } from '@/constants/app';
import { CITY_CODE_TO_NAME_MAP } from '@/constants/city';
import { JOB_TABS, JobType, EmployType, ALL_SORT_TYPES, SORT_TYPE_TITLE_MAP, SortType } from '@/constants/job';
import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height';
import { SalaryRange } from '@/types/job';
import { Coordinate } from '@/types/location';
import { logWithPrefix } from '@/utils/common';
import { navigateTo } from '@/utils/route';
import { getPartnerBannerClose, setPartnerBannerClose } from '@/utils/partner';

import './index.less';

interface IProps {
  cityCode: string;
  sortType: SortType;
  employType: EmployType;
  coordinate: Coordinate;
  onClickCity: () => void;
  onClickSort: (type: SortType) => void;
}

const PREFIX = 'all-job-fragment';
const LIST_CONTAINER_CLASS = 'all-job-fragment-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 PartnerBanner = (props: { onClose: (e: MouseEvent) => void }) => {
  const handleClick = useCallback(() => {
    navigateTo(PageUrl.Partner);
  }, []);
  return (
    <div className="partner-banner" onClick={handleClick}>
      <Image className="partner-banner__image" src={require('@/statics/png/partner_banner.png')} mode="aspectFill" />
      <div className="partner-banner__close" onClick={props.onClose} />
    </div>
  );
};

const NoGroupTips = (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: IJobListProps) {
  const { className, listHeight, visible, cityCode, employType, minSalary, maxSalary } = props;
  const [isEmpty, setIsEmpty] = useState(false);

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

  useEffect(() => {
    if (visible) {
      setIsEmpty(false);
    }
  }, [visible, cityCode, employType, minSalary, maxSalary]);

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

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

function JobFragment(props: IProps) {
  const { cityCode, employType, sortType = SortType.RECOMMEND, coordinate, onClickCity, onClickSort } = props;
  const listHeight = useListHeight(CALC_LIST_PROPS);
  const [tabType, setTabType] = useState<JobType>(JobType.All);
  const [salaryRange, setSalaryRange] = useState<SalaryRange | undefined>();
  const [showSalarySelect, setShowSalarySelect] = useState<boolean>(false);
  const { latitude, longitude } = coordinate;
  const [bannerClose, setBannerClose] = useState<boolean>(getPartnerBannerClose());

  const handleClickSearch = useCallback(() => navigateTo(PageUrl.JobSearch, { city: cityCode }), [cityCode]);

  const handleClickSalarySelect = useCallback(() => {
    setShowSalarySelect(!showSalarySelect);
  }, [showSalarySelect]);

  const handleHideSalarySelect = useCallback(() => setShowSalarySelect(false), []);

  const handleSelectSalary = useCallback((value?: SalaryRange) => {
    log('handleSelectSalary', value);
    setSalaryRange(value);
    setShowSalarySelect(false);
  }, []);

  const onTypeChange = useCallback(
    value => {
      log('onTypeChange', value);
      setTabType(value);
    },
    [setTabType]
  );

  const handlePartnerBannerClose = useCallback(e => {
    e.preventDefault();
    e.stopPropagation();
    setBannerClose(true);
    setPartnerBannerClose();
  }, []);

  useDidHide(() => setShowSalarySelect(false));

  return (
    <div className={`${PREFIX}__container`}>
      <div className={`${PREFIX}__top-search-bar`}>
        <SearchInput disabled className={`${PREFIX}__search`} placeholder="试试 女装" onClick={handleClickSearch} />
        <div className={classNames(`${PREFIX}__search-city`)} onClick={onClickCity}>
          <div className="title">{CITY_CODE_TO_NAME_MAP.get(cityCode)}</div>
          <ArrowDown />
        </div>
        <div className={classNames(`${PREFIX}__salary-select`)} onClick={handleClickSalarySelect}>
          <div className="title">薪资</div>
          {showSalarySelect ? <ArrowUp /> : <ArrowDown />}
        </div>
        <div className={classNames(`${PREFIX}__sort-type`)}>
          {ALL_SORT_TYPES.map(type => (
            <div
              key={type}
              className={classNames(`${PREFIX}__sort-item`, { selected: sortType === type })}
              onClick={() => onClickSort(type)}
            >
              {SORT_TYPE_TITLE_MAP[type]}
            </div>
          ))}
        </div>
      </div>
      <Tabs className={`${PREFIX}__type-tabs`} value={tabType} onChange={onTypeChange}>
        {JOB_TABS.map(tab => (
          <Tabs.TabPane title={tab.title} key={tab.type} value={tab.type}>
            {!bannerClose && <PartnerBanner onClose={handlePartnerBannerClose} />}
            <ListWrapper
              category={tab.type}
              cityCode={cityCode}
              sortType={sortType}
              latitude={latitude}
              longitude={longitude}
              employType={employType}
              minSalary={salaryRange?.minSalary}
              maxSalary={salaryRange?.maxSalary}
              listHeight={listHeight}
              className={LIST_CONTAINER_CLASS}
              visible={tabType === tab.type}
            />
          </Tabs.TabPane>
        ))}
      </Tabs>
      <Overlay
        visible={showSalarySelect}
        onClickOuter={handleHideSalarySelect}
        outerClassName={`${PREFIX}__overlay-outer`}
        innerClassName={`${PREFIX}__overlay-inner`}
      >
        <SalarySelect type={employType} value={salaryRange} onSelect={handleSelectSalary} />
      </Overlay>
    </div>
  );
}

export default JobFragment;
