import { onLoad, onUnload } from '@dcloudio/uni-app';
import { ref } from 'vue';
import {
  getAndroidTechs,
  getReadWriteStandard,
  getSakHex,
  getSakType,
  parseAtqaAndroid,
  transformArrayBuffer,
} from './utils';

const NfcAdapter: any = plus.android.importClass('android.nfc.NfcAdapter');
const Context = plus.android.importClass('android.content.Context');
const Tag = plus.android.importClass('android.nfc.Tag');
const Ndef: any = plus.android.importClass('android.nfc.tech.Ndef');
const NfcA: any = plus.android.importClass('android.nfc.tech.NfcA');
const NfcB: any = plus.android.importClass('android.nfc.tech.NfcB');
const NfcF: any = plus.android.importClass('android.nfc.tech.NfcF');
const NfcV: any = plus.android.importClass('android.nfc.tech.NfcV');
const NdefFormat = plus.android.importClass('android.nfc.tech.NdefFormat');
const NdefFormatable: any = plus.android.importClass(
  'android.nfc.tech.NdefFormatable',
);
const MifareClassic: any = plus.android.importClass(
  'android.nfc.tech.MifareClassic',
);
const MifareUltralight: any = plus.android.importClass(
  'android.nfc.tech.MifareUltralight',
);
const IsoDep: any = plus.android.importClass('android.nfc.tech.IsoDep');
const Intent: any = plus.android.importClass('android.content.Intent');
const PendingIntent: any = plus.android.importClass(
  'android.app.PendingIntent',
);
const IntentFilter: any = plus.android.importClass(
  'android.content.IntentFilter',
);
const Settings: any = plus.android.importClass('android.provider.Settings');
const NdefRecord: any = plus.android.importClass('android.nfc.NdefRecord');
const NdefMessage: any = plus.android.importClass('android.nfc.NdefMessage');

const INTENT_FLAGS_SINGLE_TOP = Intent.FLAG_ACTIVITY_SINGLE_TOP;
const PENDING_INTENT_FLAGS = PendingIntent.FLAG_MUTABLE;

const EXTRA_NDEF_MESSAGES = NfcAdapter.EXTRA_NDEF_MESSAGES;
const EXTRA_ID = NfcAdapter.EXTRA_ID;
const EXTRA_TAG = NfcAdapter.EXTRA_TAG;

const TNF_MIME_MEDIA = NdefRecord.TNF_MIME_MEDIA;
const ACTION_NFC_SETTINGS = Settings.ACTION_NFC_SETTINGS;

const NFC_TECH_LISTS = [
  ['android.nfc.tech.Ndef'],
  ['android.nfc.tech.NdefFormatable'],
  ['android.nfc.tech.IsoDep'],
  ['android.nfc.tech.NfcA'],
  ['android.nfc.tech.NfcB'],
  ['android.nfc.tech.NfcF'],
  ['android.nfc.tech.NfcV'],
  ['android.nfc.tech.MifareClassic'],
  ['android.nfc.tech.MifareUltralight'],
];

const NFC_INTENT_FILTERS = [
  NfcAdapter.ACTION_NDEF_DISCOVERED,
  NfcAdapter.ACTION_TECH_DISCOVERED,
  NfcAdapter.ACTION_TAG_DISCOVERED,
];

export default function useNFCAndroid(
  listener: (data: NFC.Result) => void,
  options: {
    timeout?: number;
    /** 检测连接状态 */
    checkConnectedDelay?: number;
  } = {
    timeout: 0,
    checkConnectedDelay: 500,
  },
) {
  /** 是否支持 nfc */
  const isSupportNFC = ref<boolean | undefined>(false);
  /** 是否监听中 */
  const isListening = ref<boolean>(false);
  /** 是否已连接 */
  const isConnected = ref<boolean>(false);
  /** nfc 数据 */
  const data = ref<NFC.Result>({
    id: new ArrayBuffer(0),
    techs: [],
    byteArray: [],
    hexArray: [],
    hexNumberArray: [],
    hexString: '',
  });

  /** ndef 写入方式比较特殊，需要特殊处理 */
  let isNdef = ref(false);

  const mainActivity: any = plus.android.runtimeMainActivity();

  let checkInterval: any = null;

  let nfcAdapter: NFC.Adapter | null = null;
  let nfcPendingIntent: any = null;
  let nfcTag: any = null;
  let nfcInstance: any = null;

  function checkConnected() {
    checkInterval = setInterval(() => {
      if (!nfcAdapter) {
        isConnected.value = false;
        clearInterval(checkInterval);
        return;
      }

      if (!nfcAdapter.isEnabled()) {
        isConnected.value = false;
        clearInterval(checkInterval);
        return;
      }
      if (!nfcInstance) {
        isConnected.value = false;
        clearInterval(checkInterval);
        return;
      }

      if (nfcInstance.isConnected()) {
        isConnected.value = true;
      } else {
        isConnected.value = false;
        clearInterval(checkInterval);
      }
    }, options.checkConnectedDelay ?? 500);
  }

  function innerListener() {
    try {
      const intent = mainActivity.getIntent();
      if (!intent) {
        uni.showToast({ title: 'NFC 数据解析失败', icon: 'none' });
        return;
      }

      // 获取id
      const id = intent.getByteArrayExtra(EXTRA_ID);

      const transform = transformArrayBuffer(id);

      let techs: NFC.NfcType[] = [];
      let maxTransceiveLength = 0;
      let sak = 0;
      let sakHex = '';
      let sakType = undefined;
      let atqaInfo = {
        uidType: 0,
        storageSize: 0,
        manufacturer: 0,
        cardFeatures: 0,
        reserved: 0,
      };
      let readWriteStandard: string[] = [];
      nfcTag = intent.getParcelableExtra(EXTRA_TAG); // 先获取 Tag 实例

      if (nfcTag) {
        // 核心方法：通过 Tag.getTechList() 获取原生技术列表数组
        const nativeTechList = nfcTag.getTechList();
        // 转换为可直接使用的 string 数组（兼容原生返回格式）
        techs = Array.isArray(nativeTechList) ? nativeTechList : [];

        techs = getAndroidTechs(techs);

        isNdef.value = techs.includes('Ndef');

        // 根据技术类型 获取实例
        const type = techs[0];

        switch (type) {
          case 'NFC-A':
            nfcInstance = NfcA.get(nfcTag);
            break;
          case 'NFC-B':
            nfcInstance = NfcB.get(nfcTag);
            break;
          case 'NFC-F':
            nfcInstance = NfcF.get(nfcTag);
            break;
          case 'NFC-V':
            nfcInstance = NfcV.get(nfcTag);
            break;
          case 'MIFARE Classic':
            nfcInstance = MifareClassic.get(nfcTag);
            break;
          case 'MIFARE Ultralight':
            nfcInstance = MifareUltralight.get(nfcTag);
            break;
          case 'Ndef':
            isNdef.value = true;
            nfcInstance = Ndef.get(nfcTag);
            break;
          case 'Ndef Formatable':
            isNdef.value = true;
            nfcInstance = NdefFormatable.get(nfcTag);
            break;
          case 'ISO-DEP':
            nfcInstance = IsoDep.get(nfcTag);
            break;
          default:
            nfcInstance = undefined;
            break;
        }

        if (!nfcInstance) {
          uni.showToast({ title: 'NFC 实例获取失败', icon: 'none' });
          return;
        }

        nfcInstance?.connect();

        maxTransceiveLength = nfcInstance?.getMaxTransceiveLength?.() ?? 0;

        readWriteStandard = getReadWriteStandard(techs);

        if (techs.includes('NFC-A')) {
          // NFC-A 标签的 SAK 信息
          const nfcAInstance = NfcA.get(nfcTag);
          const sakShortObject =
            plus.android.invoke(nfcAInstance, 'getSak') ?? 0;

          const sakStr = plus.android.invoke(sakShortObject, 'toString');

          sak = Number(sakStr) || 0;

          sakType = getSakType(sak);

          sakHex = getSakHex(sak);

          const atqa = plus.android.invoke(nfcAInstance, 'getAtqa');

          atqaInfo = parseAtqaAndroid(atqa);
        }
      }

      // TODO 实际使用中 获取的ndefMessage格式？？？
      // 解析 NDEF 数据
      const ndefMessage = intent.getParcelableArrayExtra(EXTRA_NDEF_MESSAGES);
      let message: any = '';
      if (ndefMessage && ndefMessage.length > 0) {
        const records = ndefMessage[0].getRecords();
        if (records && records.length > 0) {
          const payload = records[0].getPayload();
          message = payload
            ? plus.android.newObject('java.lang.String', payload)
            : '';
          isNdef.value = true;
        }
      }

      //  返回数据
      data.value = {
        ...data.value,
        ...transform,
        ...atqaInfo,
        id,
        sak,
        sakHex,
        sakType,
        techs,
        message,
        maxTransceiveLength,
        readWriteStandard,
      };
      // 回调通知外部
      listener(data.value);
      // 可将改行去除
      uni?.__dev_tool_nfc_collection__?.(data.value);
      uni.showToast({ title: 'NFC 读取成功', icon: 'none' });

      checkConnected();
    } catch (error) {
      uni.showToast({ title: 'NFC 数据解析失败', icon: 'none' });
    }
  }

  function initNfcAdapter() {
    try {
      if (!mainActivity) {
        uni.showToast({ title: '无法获取主 Activity 实例', icon: 'none' });
        return;
      }

      nfcAdapter = NfcAdapter.getDefaultAdapter(mainActivity);

      // 1. 设备不支持 NFC
      if (!nfcAdapter) {
        isSupportNFC.value = false;
        return;
      }

      // 2. NFC 功能未开启
      if (!nfcAdapter.isEnabled()) {
        isSupportNFC.value = false;
        return;
      }

      // 3. 初始化成功，注册监听
      isSupportNFC.value = true;
    } catch (error) {
      isSupportNFC.value = false;
    }
  }

  function startHCE() {
    if (!isSupportNFC.value) {
      uni.showToast({
        title: '设备不支持 NFC',
        icon: 'none',
      });
      return;
    }
    // 前置校验
    if (!nfcAdapter) {
      uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
      return false;
    }
    //
    if (isListening.value) {
      uni.showToast({ title: 'NFC 监听已开启，无需重复操作', icon: 'none' });
      return true;
    }

    try {
      // 1. 注册 newintent 事件监听
      plus.globalEvent.addEventListener('newintent', innerListener);

      // 2. 构建前台调度 PendingIntent（缓存实例，避免重复创建）
      if (!nfcPendingIntent) {
        const intent = new Intent(mainActivity, mainActivity.getClass());
        intent.addFlags(INTENT_FLAGS_SINGLE_TOP);
        nfcPendingIntent = PendingIntent.getActivity(
          mainActivity,
          0,
          intent,
          PENDING_INTENT_FLAGS,
        );
      }

      // 3. 构建 Intent 过滤器
      const filters = NFC_INTENT_FILTERS.map(
        (filter) => new IntentFilter(filter),
      );

      // 4. 启用前台调度（核心：App 前台优先捕获 NFC 事件）
      nfcAdapter?.enableForegroundDispatch(
        mainActivity,
        nfcPendingIntent,
        filters,
        NFC_TECH_LISTS,
      );

      // 5. 更新监听状态
      isListening.value = true;
      uni.showToast({
        title: '开始监听NFC',
        icon: 'none',
      });
      return true;
    } catch (e) {
      uni.showToast({ title: 'NFC 监听开启失败', icon: 'none' });
      isListening.value = false;
      return false;
    }
  }

  function stopHCE() {
    // 前置校验
    if (!isSupportNFC.value) {
      uni.showToast({
        title: '设备不支持 NFC',
        icon: 'none',
      });
      return;
    }
    // 前置校验
    if (!nfcAdapter) {
      uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' });
      return false;
    }
    //
    if (!isListening.value) {
      uni.showToast({ title: 'NFC 监听已关闭，无需重复操作', icon: 'none' });
      return true;
    }

    try {
      // 1. 禁用前台调度
      nfcAdapter.disableForegroundDispatch(mainActivity);
      // 2. 更新监听状态
      isListening.value = false;
      isConnected.value = false;
      uni.showToast({
        title: '停止监听NFC',
        icon: 'none',
      });
      clearInterval(checkInterval);
      return true;
    } catch (e) {
      uni.showToast({ title: 'NFC 监听停止失败', icon: 'error' });
      return false;
    }
  }

  function connect() {
    if (!isSupportNFC.value) {
      uni.showToast({ title: '设备不支持 NFC', icon: 'none' });
      return;
    }

    if (!isListening.value) {
      uni.showToast({ title: '请先开启前台调度监听', icon: 'none' });
      return;
    }

    if (!nfcInstance) {
      uni.showToast({ title: '请先靠近 NFC 标签', icon: 'none' });
      return;
    }

    try {
      if (!nfcInstance.isConnected()) {
        // 补充连接状态判断
        nfcInstance.connect();
        isConnected.value = true;
        uni.showToast({ title: 'NFC 连接成功', icon: 'none' });
      } else {
        isConnected.value = true;
        uni.showToast({ title: 'NFC 已处于连接状态', icon: 'none' });
      }

      checkConnected();
    } catch (error) {
      uni.showToast({ title: 'NFC 连接失败', icon: 'none' });
      isConnected.value = false;
    }
  }

  function close() {
    if (!isSupportNFC.value) {
      uni.showToast({ title: '设备不支持 NFC', icon: 'none' });
      return;
    }

    if (!nfcInstance) {
      uni.showToast({ title: '无连接中的 NFC 标签', icon: 'none' });
      return;
    }

    try {
      if (nfcInstance.isConnected()) {
        nfcInstance.close();
      }
      // 清空缓存，重置状态
      nfcTag = null;
      nfcInstance = null;
      isConnected.value = false;
      isNdef.value = false;
      clearInterval(checkInterval);
      uni.showToast({ title: 'NFC 连接已关闭', icon: 'none' });
    } catch (error) {
      uni.showToast({ title: 'NFC 连接关闭失败', icon: 'none' });
    }
  }

  function offHCEMessage() {
    try {
      if (!isSupportNFC.value) {
        uni.showToast({ title: '设备不支持 NFC，无需移除监听', icon: 'none' });
        return true;
      }

      // 1. 移除 newintent 事件监听
      plus.globalEvent.removeEventListener('newintent', innerListener);

      // 2. 停止前台调度，关闭连接
      if (nfcAdapter && isListening.value) {
        nfcAdapter.disableForegroundDispatch(mainActivity);
      }
      if (nfcInstance && nfcInstance.isConnected()) {
        nfcInstance.close();
      }

      // 3. 清空所有缓存，重置状态
      nfcPendingIntent = null;
      nfcTag = null;
      nfcInstance = null;
      isListening.value = false;
      isConnected.value = false;
      isNdef.value = false;
      clearInterval(checkInterval);
      uni.showToast({ title: 'NFC 监听已移除', icon: 'none' });
      return true;
    } catch (e) {
      uni.showToast({ title: 'NFC 监听移除失败', icon: 'none' });
      return false;
    }
  }

  /**
   * TODO 寻找一张卡来进行测试写入
   *
   * @param {ArrayBuffer} writeData
   * @return {*}
   */
  function write(writeData: ArrayBuffer) {
    if (!nfcTag) {
      uni.showToast({ title: '请先靠近 NFC 标签建立连接', icon: 'none' });
      return;
    }

    try {
      uni.showToast({
        title: '开始写入数据，请勿断开连接',
        icon: 'none',
      });

      // 1. 转换 ArrayBuffer 为 Java 字节数组
      const uint8Array = new Uint8Array(writeData);
      const text = Array.from(uint8Array)
        .map((byte) => String.fromCharCode(byte))
        .join('');
      const textBytes = plus.android.invoke(text, 'getBytes');

      // 2. 构建 NDEF 记录与消息
      const mimeBytes = plus.android.invoke('text/plain', 'getBytes');
      const textRecord = new NdefRecord(
        TNF_MIME_MEDIA,
        mimeBytes,
        plus.android.invoke('', 'getBytes'),
        textBytes,
      );
      const message = new NdefMessage([textRecord]);

      // 3. 写入数据（支持已格式化和未格式化标签）

      nfcInstance.connect();
      if (!nfcInstance.isWritable()) {
        uni.showToast({ title: 'NFC 标签不允许写入', icon: 'none' });
        nfcInstance.close();
        return;
      }
      if (nfcInstance.getMaxTransceiveLength() < message.toByteArray().length) {
        uni.showToast({ title: '写入数据超出标签容量', icon: 'none' });
        nfcInstance.close();
        return;
      }
      nfcInstance.writeNdefMessage(message);
      nfcInstance.close();

      checkConnected();
      uni.showToast({ title: '数据写入成功', icon: 'none' });
    } catch (e) {
      uni.showToast({ title: '数据写入失败', icon: 'none' });
    }
  }

  /**
   * TODO 寻找一张卡来进行测试写入
   *
   * @param {NFC.NdefData} data
   */
  function writeNdf(data: NFC.NdefData) {}

  onLoad(() => {
    initNfcAdapter();
  });

  onUnload(() => {
    stopHCE();
    offHCEMessage();
  });

  return {
    data,
    isNdef,
    isSupportNFC,
    isListening,
    isConnected,
    nfcInstance,
    startHCE,
    stopHCE,
    connect,
    close,
    write,
    writeNdf,
  };
}
