import 'dart:io';

import 'package:permission_handler/permission_handler.dart';
import 'package:sentinel_shield/core/permissions/permission_activation_state.dart';
import 'package:sentinel_shield/core/permissions/permission_capability.dart';

class PermissionCoordinator {
  const PermissionCoordinator();

  Future<PermissionActivationState> status({
    required bool developerModeEnabled,
  }) async {
    final Map<PermissionCapability, CapabilityPermissionState> states =
        <PermissionCapability, CapabilityPermissionState>{};
    for (final PermissionCapability capability in PermissionCapability.values) {
      states[capability] = await _stateFor(capability);
    }

    return PermissionActivationState(
      states: states,
      developerModeEnabled: developerModeEnabled,
      deviceOwnerRequired: true,
    );
  }

  Future<PermissionActivationState> requestCapability(
    PermissionCapability capability, {
    required bool developerModeEnabled,
    required bool disclosureAccepted,
  }) async {
    if (!disclosureAccepted) {
      throw StateError('The permission disclosure must be accepted first.');
    }

    if (capability == PermissionCapability.backgroundLocation) {
      final PermissionStatus foreground = await Permission.location.status;
      if (!foreground.isGranted) {
        await Permission.location.request();
      }
    }

    final List<Permission> permissions = _permissionsFor(capability);
    if (permissions.isNotEmpty) {
      await permissions.request();
    }
    return status(developerModeEnabled: developerModeEnabled);
  }

  Future<bool> openSystemSettings() => openAppSettings();

  Future<CapabilityPermissionState> _stateFor(
    PermissionCapability capability,
  ) async {
    final List<Permission> permissions = _permissionsFor(capability);
    if (permissions.isEmpty) return CapabilityPermissionState.unsupported;

    final List<PermissionStatus> statuses = <PermissionStatus>[];
    for (final Permission permission in permissions) {
      statuses.add(await permission.status);
    }

    if (statuses.every((PermissionStatus status) => status.isGranted)) {
      return CapabilityPermissionState.granted;
    }
    if (statuses.any((PermissionStatus status) => status.isPermanentlyDenied)) {
      return CapabilityPermissionState.permanentlyDenied;
    }
    if (statuses.any((PermissionStatus status) => status.isRestricted)) {
      return CapabilityPermissionState.restricted;
    }
    return CapabilityPermissionState.denied;
  }

  List<Permission> _permissionsFor(PermissionCapability capability) {
    if (!Platform.isAndroid) return const <Permission>[];

    return switch (capability) {
      PermissionCapability.notifications => <Permission>[
          Permission.notification,
        ],
      PermissionCapability.foregroundLocation => <Permission>[
          Permission.location,
        ],
      PermissionCapability.backgroundLocation => <Permission>[
          Permission.locationAlways,
        ],
      PermissionCapability.camera => <Permission>[Permission.camera],
      PermissionCapability.microphone => <Permission>[Permission.microphone],
      PermissionCapability.phoneState => <Permission>[Permission.phone],
      PermissionCapability.activityRecognition => <Permission>[
          Permission.activityRecognition,
          Permission.sensors,
        ],
      PermissionCapability.bluetooth => <Permission>[
          Permission.bluetoothScan,
          Permission.bluetoothConnect,
        ],
    };
  }
}
