import { fetchUserProjects, saveUserProjects } from "@/lib/client/projects-api";
import { mergeProjectAccounts } from "@/lib/project/defaults";
import { useProjectsStore } from "@/store/projects-store";
let applyingServerData = false;
let syncTimer: ReturnType<typeof setTimeout> | null = null;

function getStoreSnapshot() {
  const { projects, activeProjectId, dataByProjectId } = useProjectsStore.getState();
  return { activeProjectId, projects, dataByProjectId };
}

export function isApplyingServerProjects() {
  return applyingServerData;
}

function normalizeSnapshot(snapshot: {
  activeProjectId: string | null;
  projects: ReturnType<typeof useProjectsStore.getState>["projects"];
  dataByProjectId: ReturnType<typeof useProjectsStore.getState>["dataByProjectId"];
}) {
  const projects = Array.isArray(snapshot.projects) ? snapshot.projects : [];
  const dataByProjectId = { ...snapshot.dataByProjectId };
  for (const project of projects) {
    const data = dataByProjectId[project.id];
    if (!data) continue;
    dataByProjectId[project.id] = {
      ...data,
      accounts: mergeProjectAccounts(data.accounts),
    };
  }
  return { ...snapshot, projects, dataByProjectId };
}

export function applyServerProjects(snapshot: {
  activeProjectId: string | null;
  projects: ReturnType<typeof useProjectsStore.getState>["projects"];
  dataByProjectId: ReturnType<typeof useProjectsStore.getState>["dataByProjectId"];
}) {
  applyingServerData = true;
  const normalized = normalizeSnapshot(snapshot);
  useProjectsStore.setState({
    projects: normalized.projects,
    activeProjectId: normalized.activeProjectId,
    dataByProjectId: normalized.dataByProjectId,
    _hasHydrated: true,
  });
  applyingServerData = false;
}

export async function hydrateProjectsFromServer(): Promise<void> {
  const server = await fetchUserProjects();
  const local = getStoreSnapshot();

  if (server && Array.isArray(server.projects) && server.projects.length > 0) {
    applyServerProjects({
      activeProjectId: server.activeProjectId,
      projects: server.projects,
      dataByProjectId: server.dataByProjectId,
    });
    return;
  }

  if (local.projects.length > 0) {
    await saveUserProjects(local);
  }
}

export function scheduleProjectsSync(delayMs = 800) {
  if (applyingServerData) return;

  if (syncTimer) clearTimeout(syncTimer);
  syncTimer = setTimeout(() => {
    void saveUserProjects(getStoreSnapshot()).catch((err) => {
      console.error("Project sync failed:", err);
    });
  }, delayMs);
}

/** Push project state to server immediately (after Save Schedule / Save Context). */
export async function flushProjectsSync(): Promise<void> {
  if (applyingServerData) return;
  if (syncTimer) clearTimeout(syncTimer);
  syncTimer = null;
  await saveUserProjects(getStoreSnapshot());
}
