import { useCallback, useMemo, useState } from 'react';
import { Box, TextField, TextFieldProps, Typography } from '@mui/material';
import { parsePhoneNumber } from 'awesome-phonenumber';
import { defaultCountries, CountryIso2, usePhoneInput, parseCountry } from 'react-international-phone';
import CountrySelect, { CountryDisplayOptions } from './country-select';
import { mergeSx } from '../Util/style';

export interface PhoneValue {
  country: CountryIso2;
  phone: string; // 带区号的完整电话号码，如 +86123456789
}

export interface PhoneInputProps extends Omit<TextFieldProps, 'value' | 'onChange'> {
  value?: PhoneValue;
  onChange?: (value: PhoneValue) => void;
  countryDisplayOptions?: CountryDisplayOptions;
  preview?: boolean;
  allowDial?: boolean; // 是否允许拨号, 只在 preview 为 true 时有效
}

export function validatePhoneNumber(phone: string, iso2: CountryIso2, dialCode: string = ''): boolean {
  // 如果没有输入电话号码，返回false
  if (!phone) return false;

  // 如果去除所有格式化字符后，只剩下区号，则认为只有区号
  const cleanedPhone = phone.replace(/[\s\-()]+/g, '');

  const phoneDialCode = dialCode || getDialCodeByCountry(iso2);
  // 这表示电话号码只有区号部分
  if (getDialCodeWithoutPlus(phoneDialCode) === getDialCodeWithoutPlus(cleanedPhone)) {
    return true; // 如果只有区号，则视为有效
  }

  // 否则使用validator进行完整校验
  const pn = parsePhoneNumber(phone, { regionCode: iso2 });
  const cleanedParsedPhone = pn.number?.input.replace(/[\s\-()]+/g, '');
  return (
    pn.valid && (pn.type === 'mobile' || pn.type === 'fixed-line-or-mobile') && cleanedParsedPhone === pn.number?.e164
  );
}

// 从带区号的电话号码中提取纯号码部分
function extractPhoneWithoutCode(phone: string, dialCode: string): string {
  if (!phone) return '';
  // 先去除区号
  const phoneWithoutCode = phone.replace(new RegExp(`^\\+${dialCode}`), '');
  // 去除非数字字符，但保留括号
  return phoneWithoutCode;
}

// 添加区号到纯号码
function addCountryCodeToPhone(phone: string, dialCode: string): string {
  if (!phone) return `+${dialCode}`;
  return phone.startsWith('+') ? phone : `+${dialCode}${phone}`;
}

// 获取不带+号的区号
function getDialCodeWithoutPlus(dialCode: string): string {
  return dialCode.replace(/^\+/, '');
}

// 根据ISO2国家代码获取国家信息
function getCountryInfoByIso2<T extends keyof ReturnType<typeof parseCountry>>(
  iso2: CountryIso2,
  property: T
): ReturnType<typeof parseCountry>[T] | undefined {
  // 查找对应的国家数据
  const countryItem = defaultCountries.find((country) => parseCountry(country).iso2 === iso2);

  if (!countryItem) {
    return undefined;
  }

  // 解析国家信息并返回请求的属性
  return parseCountry(countryItem)[property];
}

// 根据ISO2国家代码获取区号
export function getDialCodeByCountry(iso2: CountryIso2): string {
  return getCountryInfoByIso2(iso2, 'dialCode') || '';
}

// 根据ISO2国家代码获取国家名称
export function getCountryNameByCountry(iso2: CountryIso2): string {
  return getCountryInfoByIso2(iso2, 'name') || '';
}

// 根据手机号识别国家，返回国家的 iso2 码
// 如果手机号带有区号，通过 parsePhoneNumber 识别
// 如果手机号不带区号，通过碰撞识别
export function detectCountryFromPhone(phoneNumber?: string): CountryIso2 | undefined {
  try {
    if (!phoneNumber) return undefined;

    // 如果已经带了+号，尝试从前缀匹配
    if (phoneNumber.startsWith('+')) {
      const parsedPhone = parsePhoneNumber(phoneNumber);
      if (parsedPhone.valid) {
        return parsedPhone.regionCode.toLowerCase() as CountryIso2;
      }
      for (const country of defaultCountries) {
        const parsed = parseCountry(country);
        if (phoneNumber.startsWith(`+${parsed.dialCode}`)) {
          const phoneWithCode = phoneNumber;
          // 验证该号码是否有效
          if (validatePhoneNumber(phoneWithCode, parsed.dialCode, parsed.iso2)) {
            return parsed.iso2;
          }
        }
      }
    } else {
      for (const country of defaultCountries) {
        const parsed = parseCountry(country);
        const phoneWithCode = `+${parsed.dialCode}${phoneNumber}`;
        if (validatePhoneNumber(phoneWithCode, parsed.dialCode, parsed.iso2)) {
          return parsed.iso2;
        }
      }
    }
    return undefined;
  } catch {
    return undefined;
  }
}

export default function PhoneInput({
  value = { country: 'us', phone: '' },
  onChange = undefined,
  placeholder = 'Enter phone number',
  countryDisplayOptions = {},
  preview = false,
  allowDial = true,
  ...props
}: PhoneInputProps) {
  // 创建国家代码映射表，避免重复解析
  const countryMap = useMemo(() => {
    const map = new Map<CountryIso2, ReturnType<typeof parseCountry>>();
    defaultCountries.forEach((country) => {
      const parsed = parseCountry(country);
      map.set(parsed.iso2, parsed);
    });
    return map;
  }, []);

  const [previewValue, setPreviewValue] = useState(value);

  const handleValueChange = useCallback(
    (data: PhoneValue) => {
      if (!preview && onChange) {
        const newValue = {
          ...value,
          ...data,
        };
        const countryData = countryMap.get(newValue.country);
        if (countryData) {
          newValue.phone = addCountryCodeToPhone(newValue.phone, getDialCodeWithoutPlus(countryData.dialCode));
        }
        onChange(newValue);
      }
    },
    [onChange, preview, value, countryMap]
  );

  // 获取当前国家的区号（不带+号）
  const currentDialCode = useMemo(() => {
    const countryData = countryMap.get(value.country);
    return countryData ? getDialCodeWithoutPlus(countryData.dialCode) : '';
  }, [value.country, countryMap]);

  // 使用 react-international-phone 的 hook
  const { phone, country, handlePhoneValueChange, setCountry } = usePhoneInput({
    defaultCountry: value.country,
    value: extractPhoneWithoutCode(value.phone, currentDialCode),
    countries: defaultCountries,
    disableDialCodeAndPrefix: true,
    onChange: (data) => {
      const newData = {
        ...data,
        phone:
          previewValue.country !== data.country && !data.phone
            ? extractPhoneWithoutCode(value.phone, currentDialCode)
            : data.phone,
      };
      setPreviewValue(newData);
      handleValueChange(newData);
    },
  });

  // 从完整电话号码中提取不带区号的部分用于显示，并去除格式化字符
  const displayPhone = useMemo(
    () => phone || extractPhoneWithoutCode(value.phone, currentDialCode),
    [phone, value.phone, currentDialCode]
  );

  // 处理国家变更
  const onCountryChange = (newCountry: CountryIso2) => {
    if (preview) return;
    setCountry(newCountry);
  };

  // 预览模式
  if (preview) {
    const phoneWithCode = addCountryCodeToPhone(phone, getDialCodeByCountry(country));
    const isValid = phone && validatePhoneNumber(phoneWithCode, country);
    const canDial = allowDial && isValid;

    return (
      <Box
        component={canDial ? 'a' : 'div'}
        href={canDial ? `tel:${phone}` : undefined}
        {...(canDial
          ? {
              'aria-label': `Call ${phone}`,
              title: `Call ${phone}`,
              rel: 'nofollow',
              itemProp: 'telephone',
            }
          : {})}
        sx={{
          display: 'flex',
          alignItems: 'center',
          textDecoration: 'none',
          color: 'inherit',
          cursor: canDial ? 'pointer' : 'default',

          '&:hover': {
            opacity: canDial ? 0.8 : 1,
          },
        }}>
        <CountrySelect value={country} preview={preview} />
        <Typography sx={{ ml: 0.5 }}>{displayPhone}</Typography>
      </Box>
    );
  }
  // 编辑模式
  return (
    <Box
      sx={{
        display: 'flex',
        alignItems: 'flex-start',
        gap: 0.5,
      }}>
      <CountrySelect
        value={country}
        onChange={onCountryChange}
        preview={false}
        selectCountryProps={countryDisplayOptions}
      />
      <TextField
        {...props}
        value={displayPhone}
        onChange={handlePhoneValueChange}
        placeholder={placeholder}
        className="phone-input"
        sx={mergeSx(
          {
            '& .MuiInputBase-input': {
              padding: 1,
            },
          },
          props.sx as any // 这里传入的可能是一个数组或一个对象
        )}
        slotProps={{
          input: props.InputProps ?? {},
        }}
      />
    </Box>
  );
}
