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

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

import EmployTypeSelect from '@/components/employ-type-select';
import JobList, { IJobListProps } from '@/components/job-list';
import Overlay from '@/components/overlay';
import PartnerBanner from '@/components/partner-banner';
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 {
  ALL_SORT_TYPES,
  EMPLOY_TYPE_TITLE_MAP,
  EmployType,
  JOB_TABS,
  JobSourceType,
  JobType,
  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 './index.less';

interface IProps {
  cityCode: string;
  sortType: SortType;
  sourceType: JobSourceType;
  employType: EmployType;
  coordinate: Coordinate;
  onClickCity: () => void;
  onClickEmployType: (type: EmployType) => 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 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,
    sourceType,
    sortType = SortType.RECOMMEND,
    coordinate,
    onClickEmployType,
    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 [showEmployTypeSelect, setShowEmployTypeSelect] = useState<boolean>(false);
  const { latitude, longitude } = coordinate;

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

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

  const handleClickEmployTypeSelect = useCallback(() => {
    setShowEmployTypeSelect(s => !s);
  }, []);

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

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

  const handleSelectEmployType = useCallback(
    (value?: EmployType) => {
      setShowEmployTypeSelect(false);
      onClickEmployType(value!);
    },
    [onClickEmployType]
  );

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

  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}__employType-select`)} onClick={handleClickEmployTypeSelect}>
          <div className="title">
            {employType && employType !== EmployType.All ? EMPLOY_TYPE_TITLE_MAP[employType] : '类型'}
          </div>
          {showEmployTypeSelect ? <ArrowUp /> : <ArrowDown />}
        </div>
        <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}>
            <PartnerBanner />
            <ListWrapper
              category={tab.type}
              cityCode={cityCode}
              sortType={sortType}
              latitude={latitude}
              longitude={longitude}
              sourceType={sourceType}
              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>

      <Overlay
        visible={showEmployTypeSelect}
        onClickOuter={handleHideEmployTypeSelect}
        outerClassName={`${PREFIX}__overlay-outer`}
        innerClassName={`${PREFIX}__overlay-inner`}
      >
        <EmployTypeSelect value={employType} onSelect={handleSelectEmployType} />
      </Overlay>
    </div>
  );
}

export default JobFragment;
