import {Alert, Linking, Platform} from 'react-native';
import {
  checkMultiple,
  PERMISSIONS,
  requestMultiple,
  RESULTS,
  type Permission,
  type PermissionStatus,
} from 'react-native-permissions';
import BleManager from 'react-native-ble-manager';
import {isLocationEnabled} from 'react-native-device-info';

type PermissionResult = {
  success: boolean;
  status: PermissionStatus | string;
};

const managePermission = async (
  permission: PermissionResult,
  enableRequestPermission: boolean = false,
  callBack: () => void,
) => {
  if (permission.success && permission.status === RESULTS.GRANTED) {
    if (Platform.OS === 'android') {
      const isLocationEnabledFlag = await isLocationEnabled();
      if (!isLocationEnabledFlag) {
        promptEnableLocation();
        return;
      }
      enableBluetooth().then(() => {
        callBack();
      });
    } else {
      await BleManager.start({showAlert: true}).then(() => {
        callBack();
      });
    }
  } else if (
    enableRequestPermission &&
    !permission.success &&
    permission.status === RESULTS.DENIED
  ) {
    const requestPermission = await requestBluetoothPermission();
    await managePermission(requestPermission, false, callBack);
  } else if (permission.status === RESULTS.BLOCKED) {
    bluetoothPermissionMessageAlert();
  }
};
const enableBluetooth = async () => {
  try {
    const res = await BleManager.enableBluetooth();
    return {
      success: true,
      data: res,
    };
  } catch {
    return {
      success: false,
    };
  }
};

const bluetoothPermissionMessageAlert = () => {
  Alert.alert('Message', 'Please allow Bluetooth permission.', [
    {
      text: 'Open Settings',
      onPress: () => Linking.openSettings(),
    },
    {
      text: 'Cancel',
    },
  ]);
};

const evaluatePermissions = (
  permissionResults: Record<Permission, PermissionStatus>,
  requiredPermissions: Permission[],
): PermissionResult => {
  for (const permission of requiredPermissions) {
    if (permissionResults[permission] !== RESULTS.GRANTED) {
      return {
        success: false,
        status: permissionResults[permission],
      };
    }
  }

  return {
    success: true,
    status: RESULTS.GRANTED,
  };
};

const checkMultiplePermissions = async (
  permissions: Permission[],
): Promise<Record<Permission, PermissionStatus>> => {
  return checkMultiple(permissions);
};

const requestMultiplePermissions = async (
  permissions: Permission[],
): Promise<Record<Permission, PermissionStatus>> => {
  return requestMultiple(permissions);
};

const checkBluetoothPermission = async (): Promise<PermissionResult> => {
  return Platform.OS === 'android'
    ? await checkBluetoothPermissionForAndroid()
    : await checkBluetoothPermissionForIos();
};

const requestBluetoothPermission = async (): Promise<PermissionResult> => {
  return Platform.OS === 'android'
    ? await requestBluetoothPermissionForAndroid()
    : await requestBluetoothPermissionForIos();
};

const checkBluetoothPermissionForIos = async (): Promise<PermissionResult> => {
  const permissions = [PERMISSIONS.IOS.BLUETOOTH];
  return evaluatePermissions(
    await checkMultiplePermissions(permissions),
    permissions,
  );
};

const checkBluetoothPermissionForAndroid =
  async (): Promise<PermissionResult> => {
    const androidVersion = Number(Platform.Version);
    const permissions =
      androidVersion >= 31
        ? [
            PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
            PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
            PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
          ]
        : [
            PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
            PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION,
          ];

    return evaluatePermissions(
      await checkMultiplePermissions(permissions),
      permissions,
    );
  };

const requestBluetoothPermissionForIos =
  async (): Promise<PermissionResult> => {
    const permissions = [PERMISSIONS.IOS.BLUETOOTH];
    return evaluatePermissions(
      await requestMultiplePermissions(permissions),
      permissions,
    );
  };

const requestBluetoothPermissionForAndroid =
  async (): Promise<PermissionResult> => {
    const androidVersion = Number(Platform.Version);
    const permissions =
      androidVersion >= 31
        ? [
            PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
            PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
            PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
          ]
        : [
            PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
            PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION,
          ];

    return evaluatePermissions(
      await requestMultiplePermissions(permissions),
      permissions,
    );
  };

const promptEnableLocation = () => {
  Alert.alert(
    'Location Services Disabled',
    'Please enable location services to continue.',
    [
      {
        text: 'Open Settings',
      },
      {
        text: 'Cancel',
      },
    ],
  );
};

export {
  checkBluetoothPermission,
  requestBluetoothPermission,
  managePermission,
  enableBluetooth,
  promptEnableLocation,
};
