import * as FileSystem from 'expo-file-system/legacy';
import * as MapLibreRN from '@maplibre/maplibre-react-native';

import { VECTOR_MAP_HOST } from 'src/constants';
import { fetchLastMapTilesUpdate } from '@api/app';
import { storage, StoreType } from 'src/storage';
import { updateMapMetadata } from 'src/screens/OfflineMapsScreen/OfflineMapManager';

const STYLE_URL = `${VECTOR_MAP_HOST}/nomadmania-maps2025.json`;
const PACK_NAME = 'vector-map-pack';

function getPackName(p: any): string | undefined {
  if (p?.name) return p.name;

  const metaStr = p?.pack?.metadata;
  if (!metaStr) return undefined;

  try {
    return JSON.parse(metaStr)?.name;
  } catch {
    return undefined;
  }
}

async function setupOfflineRegion(): Promise<void> {
  try {
    const bounds: [GeoJSON.Position, GeoJSON.Position] = [
      [-180, -85],
      [180, 85]
    ];
    const minZoom = 0;
    const maxZoom = 6;

    const pack = await MapLibreRN.OfflineManager.getPack(PACK_NAME);

    if (pack) {
      try {
        const status = await pack.status();
        if (status.percentage < 100) {
          pack.resume();
        }
      } catch {
        await MapLibreRN.OfflineManager.createPack(
          { name: PACK_NAME, bounds, minZoom, maxZoom, styleURL: STYLE_URL },
          () => {},
          (error) => {
            if (error) console.error('Error creating offline pack:', error);
          }
        );
      }
    } else {
      await MapLibreRN.OfflineManager.createPack(
        {
          name: PACK_NAME,
          bounds,
          minZoom,
          maxZoom,
          styleURL: STYLE_URL
        },
        () => {},
        (error) => {
          if (error) {
            console.error('Error creating offline pack:', error);
          }
        }
      );
    }
  } catch (error) {
    console.error('Error setting up offline pack:', error);
  }
}

export async function initOfflineSetup(): Promise<void> {
  // await updateMapsCache();
  await setupOfflineRegion();
}

export async function updateMapsCache() {
  const localLastDate =
    (storage.get('lastMapTilesUpdate', StoreType.STRING) as string) || '1990-01-01';
  const lastUpdate = await fetchLastMapTilesUpdate();

  if (lastUpdate && lastUpdate.date !== localLastDate) {
    const packs = await MapLibreRN.OfflineManager.getPacks();

    for (const pack of packs) {
      const name = getPackName(pack);
      if (!name) continue;
      try {
        if (name === PACK_NAME) {
          await MapLibreRN.OfflineManager.deletePack(name);
        } else {
          await MapLibreRN.OfflineManager.invalidatePack(name);
          updateMapMetadata(name, { status: 'invalid' });
        }
      } catch {}
    }

    try {
      await MapLibreRN.OfflineManager.clearAmbientCache();
    } catch {}

    storage.set('lastMapTilesUpdate', lastUpdate.date);
  }
}
