import { Checkbox, Col, Divider, Input, message, Modal, Row, Typography } from 'antd';
import Link from 'antd/lib/typography/Link';
import { isEmpty } from 'lodash';
import type { ReactNode } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { FormattedMessage, useIntl, useRequest } from 'umi';
import AutoEmpty from '../Empty';

type City = {
  cityId: string;
  cityName: string;
};

type CityGroup = {
  name: string;
  child: City[];
};

type CountryData = {
  countryId: string;
  name: string;
  city: CityGroup[];
};

export interface CityModalProps {
  view?: boolean;
  cityIds?: string[];
  defaultShowSelected?: boolean;
  linkText?: ReactNode;
  modalTitle?: ReactNode;
  onFinish?: (data: { cityIds: string[] }) => void;
  /** 返回true则拦截此次选中变更 */
  cancelCityCreator?: (cancelIds: string[], checked: boolean) => Promise<boolean>;
}

const CityModal = (props: CityModalProps) => {
  const {
    view = false,
    cityIds,
    defaultShowSelected = false,
    linkText,
    modalTitle,
    onFinish,
    cancelCityCreator,
  } = props;

  const [open, setOpen] = useState(false);
  const [selectedCityIds, setSelectedCityIds] = useState<string[]>([]);
  const [searchText, setSearchText] = useState('');
  const [activeTab, setActiveTab] = useState<string>();

  const { formatMessage } = useIntl();

  const { data, run: runAll } = useRequest(
    () => ({
      url: '/goapi/config/city/all',
      method: 'POST',
    }),
    { manual: true },
  );

  // 处理城市选择变化
  const handleCityChange = useCallback(
    async (cityId: string, checked: boolean) => {
      const result = await cancelCityCreator?.([cityId], checked);
      if (result) {
        return;
      }
      const newSelected = checked
        ? [...selectedCityIds, cityId]
        : selectedCityIds.filter((id) => id !== cityId);
      setSelectedCityIds(newSelected);
    },
    [cancelCityCreator, selectedCityIds],
  );

  // 处理分组全选
  const handleGroupToggle = useCallback(
    async (group: CityGroup, checked: boolean) => {
      const groupCityIds = group.child.map((city) => city.cityId);
      const result = await cancelCityCreator?.(groupCityIds, checked);
      if (result) {
        return;
      }
      const newSelected = checked
        ? [...new Set([...selectedCityIds, ...groupCityIds])]
        : selectedCityIds.filter((id) => !groupCityIds.includes(id));
      setSelectedCityIds(newSelected);
    },
    [cancelCityCreator, selectedCityIds],
  );

  // 计算国家下已选城市数量
  const getSelectedCount = useCallback(
    (country: CountryData) => {
      return (
        country?.city?.flatMap((group) =>
          group?.child?.filter((city) => selectedCityIds.includes(city.cityId)),
        )?.length || 0
      );
    },
    [selectedCityIds],
  );

  // 处理搜索过滤
  const filteredData = useMemo<CountryData[]>(() => {
    const countrySort = (a: CountryData, b: CountryData) => {
      const aSelectedCount = getSelectedCount(a);
      const bSelectedCount = getSelectedCount(b);
      return bSelectedCount - aSelectedCount;
    };
    const l = Array.isArray(data) ? [...data] : [];
    if (!searchText) return l.sort(countrySort);
    const res = l.filter((country: CountryData) =>
      country?.name.toLowerCase().includes(searchText.toLowerCase()),
    );
    return res.sort(countrySort);
  }, [data, getSelectedCount, searchText]);

  const onOk = useCallback(async () => {
    if (isEmpty(selectedCityIds)) {
      message.error(
        formatMessage({
          id: 'component.ApplyDetail.detail.city.message',
          defaultMessage: 'Please select your city',
        }),
      );
      return;
    }
    onFinish?.({ cityIds: selectedCityIds });
    setOpen(false);
  }, [formatMessage, onFinish, selectedCityIds]);

  const [showSelected, setShowSelected] = useState(view || defaultShowSelected);

  // 渲染城市分组内容
  const renderCityContent = useCallback(
    (country?: CountryData) => {
      const { city: countryCity } = country ?? {};
      return (
        <>
          <Checkbox checked={showSelected} onChange={(e) => setShowSelected(e.target.checked)}>
            {formatMessage({ id: 'component.CityModal.selectedCity.checked.tips' })}
          </Checkbox>
          <Divider />

          <div style={{ padding: '0 16px', overflowY: 'auto', maxHeight: 600 }}>
            <AutoEmpty
              description={formatMessage({
                id: `component.CityModal.${showSelected ? 'noSelectedCity' : 'noCity'}`,
              })}
            >
              {countryCity
                ?.filter((g) => {
                  return showSelected
                    ? g.child.some((city) => selectedCityIds.includes(city.cityId))
                    : true;
                })
                .map((g) => {
                  return {
                    name: g.name,
                    child: g.child.filter((city) => {
                      return showSelected ? selectedCityIds.includes(city.cityId) : true;
                    }),
                  };
                })
                .map((g) => {
                  const { name, child } = g;
                  const everyChecked = child?.every((city) =>
                    selectedCityIds.includes(city.cityId),
                  );
                  // 半选
                  const indeterminate =
                    child?.some((city) => selectedCityIds.includes(city.cityId)) && !everyChecked;
                  return (
                    <div key={name} style={{ marginBottom: 16 }}>
                      <Checkbox
                        disabled={view}
                        indeterminate={indeterminate}
                        checked={everyChecked}
                        onChange={(e) => handleGroupToggle(g, e.target.checked)}
                      >
                        <Typography.Title level={5}>{name}</Typography.Title>
                      </Checkbox>

                      <Row gutter={16}>
                        {child?.map((city) => (
                          <Col span={8} key={city.cityId}>
                            <Checkbox
                              disabled={view}
                              checked={selectedCityIds.includes(city.cityId)}
                              onChange={(e) => handleCityChange(city.cityId, e.target.checked)}
                            >
                              {city.cityName}
                            </Checkbox>
                          </Col>
                        ))}
                      </Row>
                      <Divider />
                    </div>
                  );
                })}
            </AutoEmpty>
          </div>
        </>
      );
    },
    [formatMessage, handleCityChange, handleGroupToggle, selectedCityIds, showSelected, view],
  );

  // 渲染国家
  const renderCountry = useCallback(
    (country: CountryData) => {
      const selectedCount = getSelectedCount(country);
      return (
        <div
          key={country.countryId}
          onClick={() => setActiveTab(country.countryId)}
          style={{
            padding: '12px 16px',
            cursor: 'pointer',
            backgroundColor:
              activeTab === country.countryId ? 'rgba(241, 102, 34, 0.06)' : 'transparent',
            borderRight: activeTab === country.countryId ? '3px solid #F16622' : 'none',
          }}
        >
          <div style={{ fontWeight: 500 }}>{country.name}</div>
          {selectedCount > 0 && (
            <span style={{ color: '#F16622', fontSize: 12 }}>
              {formatMessage({ id: 'base.common.select.count' }, { count: selectedCount })}
            </span>
          )}
        </div>
      );
    },
    [activeTab, formatMessage, getSelectedCount],
  );

  useEffect(() => {
    if (open) {
      runAll();
    }
  }, [open, runAll]);

  const [activeCountry, setActiveCountry] = useState<CountryData>();

  useEffect(() => {
    const find = filteredData.find((country) => country.countryId === activeTab);
    if (find) {
      setActiveCountry(find);
    } else {
      setActiveCountry(filteredData[0]);
      setActiveTab(filteredData[0]?.countryId);
    }
  }, [filteredData, activeTab]);

  useEffect(() => {
    setSelectedCityIds(cityIds || []);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <>
      <Link onClick={() => setOpen(true)}>
        {linkText ?? (
          <FormattedMessage id="component.ApplyDetail.detail.city" defaultMessage="City" />
        )}
      </Link>

      <Modal
        title={
          modalTitle ?? (
            <FormattedMessage
              id="component.ApplyDetail.detail.city.select"
              defaultMessage="Region Selection"
            />
          )
        }
        open={open}
        width={900}
        onCancel={() => setOpen(false)}
        destroyOnClose={true}
        onOk={onOk}
        okButtonProps={view ? { style: { display: 'none' } } : undefined}
      >
        <Row gutter={20}>
          <Col span={6}>
            <Input.Search
              placeholder={formatMessage({
                id: 'component.ApplyDetail.detail.country.search',
                defaultMessage: 'Search Country',
              })}
              allowClear
              onChange={(e) => setSearchText(e.target.value)}
              style={{ marginBottom: 16 }}
            />

            <div style={{ overflowY: 'auto', maxHeight: 550 }}>
              {filteredData.map(renderCountry)}
            </div>
          </Col>

          <Col span={18}>{renderCityContent(activeCountry)}</Col>
        </Row>
      </Modal>
    </>
  );
};

export default CityModal;
