import { fetchMapData } from '@api/regions';
import { SQLiteDatabase } from 'expo-sqlite';
import { isNmDbRefreshing, refreshNmDatabase } from 'src/db';

const NM_TABLES = new Set(['regions']);

export const getData = async (
  db: SQLiteDatabase | null,
  regionId: number,
  name: string,
  callback: (data: any, avatars: string[]) => void
): Promise<void> => {
  const isNmTable = NM_TABLES.has(name);

  if (isNmTable && isNmDbRefreshing()) {
    console.warn(`[getData] nm DB is refreshing, falling back to API for "${name}"`);
    await fallbackToApi(regionId, callback);
    return;
  }

  if (!db) {
    if (isNmTable) {
      console.warn(`[getData] db is null for "${name}", falling back to API`);
      refreshNmDatabase();
      await fallbackToApi(regionId, callback);
      return;
    }
    throw new Error(`[getData] Database is null for table="${name}"`);
  }

  try {
    const regionRows = await db.getAllAsync<any>(`SELECT * FROM ${name} WHERE id = ?;`, [regionId]);

    const regionData = regionRows[0] ?? null;
    if (!regionData && isNmTable) {
      console.warn(
        `[getData] No record found for id=${regionId} in "${name}", falling back to API`
      );
      refreshNmDatabase();
      await fallbackToApi(regionId, callback);
      return;
    }

    const avatarIds: number[] = regionData?.visitors_avatars
      ? JSON.parse(regionData.visitors_avatars)
      : [];

    const avatars: string[] = [];
    for (const avatarId of avatarIds) {
      const avatarRows = await db.getAllAsync<any>(`SELECT * FROM avatars WHERE id = ?;`, [
        avatarId
      ]);
      if (avatarRows.length > 0) {
        avatars.push(avatarRows[0].data);
      }
    }

    setTimeout(() => callback(regionData, avatars), 0);
  } catch (error) {
    console.error('Error in getData:', error);

    if (isNmTable) {
      refreshNmDatabase();
      await fallbackToApi(regionId, callback);
    } else {
      throw error;
    }
  }
};

async function fallbackToApi(
  regionId: number,
  callback: (data: any, avatars: string[]) => void
): Promise<void> {
  try {
    const response = await fetchMapData(regionId);
    const regionData = response?.data ?? null;
    const avatars: string[] =
      regionData?.avatars?.slice(0, 3).map((a: { data: string; id: number }) => a.data) ?? [];

    setTimeout(() => callback(regionData, avatars), 0);
  } catch (apiError) {
    console.error('[getData] API fallback failed:', apiError);
    throw apiError;
  }
}
