import * as TaskManager from 'expo-task-manager';
import * as Location from 'expo-location';
import axios from 'axios';
import { checkAndSendSavedMessages, storage, StoreType } from 'src/storage';
import { Platform } from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import { API_URL, APP_VERSION } from 'src/constants';
import { API } from 'src/types';

const LOCATION_TASK_NAME = 'BACKGROUND_LOCATION_TASK';

TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
  if (error) {
    console.error('[BackgroundLocation] Task error:', error);
    return;
  }
  if (data) {
    const { locations } = data as any;
    let lastLocationSentTime =
      (storage.get('last_location_sent_time', StoreType.NUMBER) as number) ?? 0;
    let lastLatitude = storage.get('last_latitude', StoreType.NUMBER) as number | null;
    let lastLongitude = storage.get('last_longitude', StoreType.NUMBER) as number | null;

    if (locations && locations.length > 0) {
      const now = Date.now();
      const { coords } = locations[0];
      const token = storage.get('token', StoreType.STRING);

      if (!token) {
        return;
      }

      const getThreeDigits = (num: number) => Math.floor(num * 1000);

      const latitudeChanged =
        !lastLatitude || getThreeDigits(lastLatitude) !== getThreeDigits(coords.latitude);
      const longitudeChanged =
        !lastLongitude || getThreeDigits(lastLongitude) !== getThreeDigits(coords.longitude);

      if (latitudeChanged || longitudeChanged || now - lastLocationSentTime >= 60 * 1000) {
        storage.set('last_location_sent_time', now);
        storage.set('last_latitude', coords.latitude);
        storage.set('last_longitude', coords.longitude);

        const netInfoState = await NetInfo.fetch();
        if (netInfoState.isConnected) {
          checkAndSendSavedMessages();
        }

        try {
          const response = await axios.postForm(
            API_URL + '/' + API.UPDATE_LOCATION,
            {
              token,
              lat: coords.latitude,
              lng: coords.longitude
            },
            {
              headers: {
                Platform: Platform.OS,
                'App-Version': APP_VERSION
              }
            }
          );
        } catch {}
      }
    }
  }
});

export const startBackgroundLocationUpdates = async () => {
  const hasStarted = await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK_NAME);
  if (hasStarted || Platform.OS === 'android') {
    return;
  }

  await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
    accuracy: Location.Accuracy.High,
    // 30 minutes for Android
    timeInterval: 30 * 60 * 1000,
    showsBackgroundLocationIndicator: false,
    pausesUpdatesAutomatically: false,
    // banner on Android
    foregroundService: {
      notificationTitle: 'NomadMania tracking your location',
      notificationBody: 'Location is used in background every 30 minutes.'
      // notificationColor: '#0F3F4F'
    },
    // iOS only
    activityType: Location.ActivityType.Other,
    // 1 minute for iOS
    deferredUpdatesInterval: 60 * 1000
  });
};

export const stopBackgroundLocationUpdates = async () => {
  const hasStarted = await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK_NAME);
  if (hasStarted) {
    await Location.stopLocationUpdatesAsync(LOCATION_TASK_NAME);
  }
};

export const restartBackgroundLocationUpdates = async () => {
  const lastUpdatedVersion = storage.get('location_update_version', StoreType.STRING) ?? '';

  const hasStarted = await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK_NAME);
  if (hasStarted && lastUpdatedVersion !== APP_VERSION) {
    await Location.stopLocationUpdatesAsync(LOCATION_TASK_NAME);
  }

  await startBackgroundLocationUpdates();

  storage.set('location_update_version', APP_VERSION);
};
