import pLimit from 'p-limit';
import { Q } from '@nozbe/watermelondb';
import { database } from 'src/watermelondb';
import Message from 'src/watermelondb/models/Message';
import Chat from 'src/watermelondb/models/Chat';
import { makeChatKey, upsertChats } from './chat.repo';
import { upsertBlockedUsers } from './blocked.repo';
import { chatApi } from '@api/chat';
import { createLocalBackup } from 'src/watermelondb/backup';
import { normalizeServerMessage } from './message.sync';

const CONCURRENCY = 5;
const BATCH_LIMIT = 500;

export async function importAllMessagesForChat(
  token: string,
  params: { chatUid?: number; groupToken?: string }
) {
  const isGroup = Boolean(params.groupToken);
  const chatKey = makeChatKey({ chatUid: params.chatUid, groupChatToken: params.groupToken });

  const res = isGroup
    ? await chatApi.getGroupChatAll(token, params.groupToken!)
    : await chatApi.getChatWithAll(token, params.chatUid!);

  const col = database.get<Message>('messages');

  await database.write(async () => {
    const batch: any[] = [];
    const existing = await col.query(Q.where('chat_key', chatKey)).fetch();

    for (const m of existing) {
      await m.destroyPermanently();
    }

    for (const s of res?.data?.messages ?? []) {
      const data = normalizeServerMessage(s, chatKey, isGroup);
      batch.push(
        col.prepareCreate((m) => {
          Object.assign(m, data);
          m.dirtyActions = null;
          m.isDirty = false;
        })
      );
    }

    if (batch.length) {
      await database.batch(batch);
    }
  });
}

async function fetchChatsList(token: string, archive: 0 | 1) {
  try {
    const { data } = await chatApi.getChatsList(token, archive);
    return data?.conversations ?? [];
  } catch (e) {
    console.error(`fetchChatsList(${archive}) failed`, e);
    return [];
  }
}

export async function importChatsFromServer(token: string) {
  try {
    const [active, archived] = await Promise.all([
      fetchChatsList(token, 0),
      fetchChatsList(token, 1)
    ]);
    const conversations = [...active, ...archived];

    if (conversations.length > 0) await upsertChats(conversations);

    const { data: blockedData } = await chatApi.getBlocked(token);
    await upsertBlockedUsers(blockedData?.blocked ?? []);

    const limit = pLimit(CONCURRENCY);
    const tasks = conversations.map((chat) =>
      limit(async () => {
        await importAllMessagesForChat(token, {
          chatUid: chat.uid ?? undefined,
          groupToken: chat.group_chat_token ?? undefined
        });
      })
    );

    console.log(`Running ${tasks.length} imports with concurrency=${CONCURRENCY}`);
    await Promise.all(tasks);

    // console.log('💾 Creating local backup...');
    // await createLocalBackup();

    console.log('All chats imported successfully.');
  } catch (err) {
    console.error('importChatsFromServer failed at root level:', err);
  }
}
