import PocketBase from "pocketbase";
import { createPlayersService } from "./services/players";
import { createTournamentsService } from "./services/tournaments";
import { createTeamsService } from "./services/teams";
import { createMatchesService } from "./services/matches";
import { createReactionsService } from "./services/reactions";
import { createActivitiesService } from "./services/activities";
import { createBadgesService } from "./services/badges";
import { createGroupsService } from "./services/groups";
import { createPredictionsService } from "./services/predictions";
import { createPushService } from "./services/push";

class PocketBaseAdminClient {
  private pb: PocketBase;
  public authPromise: Promise<void>;
  private refreshInterval: NodeJS.Timeout | null = null;

  constructor() {
    this.pb = new PocketBase(process.env.POCKETBASE_URL);

    this.pb.beforeSend = async (url, options) => {
      await this.authPromise;

      if (this.pb.authStore.isValid && this.isTokenExpiringSoon()) {
        try {
          await this.refreshAuth();
        } catch (error) {
          console.error('Failed to refresh admin token, re-authenticating:', error);
          await this.authenticate();
        }
      }

      options.cache = "no-store";
      options.headers = {
        ...options.headers,
        "Cache-Control": "no-cache, no-store, must-revalidate",
        Pragma: "no-cache",
        Expires: "0",
      };

      return { url, options };
    };
    this.pb.autoCancellation(false);

    Object.assign(this, createPlayersService(this.pb));
    Object.assign(this, createTeamsService(this.pb));
    Object.assign(this, createTournamentsService(this.pb));
    Object.assign(this, createMatchesService(this.pb));
    Object.assign(this, createReactionsService(this.pb));
    Object.assign(this, createActivitiesService(this.pb));
    Object.assign(this, createBadgesService(this.pb));
    Object.assign(this, createGroupsService(this.pb));
    Object.assign(this, createPredictionsService(this.pb));
    Object.assign(this, createPushService(this.pb));

    this.authPromise = this.authenticate();
    this.authPromise.then(() => {
      this.startTokenRefresh();
    });
  }

  private async authenticate() {
    try {
      await this.pb
        .collection("_superusers")
        .authWithPassword(
          process.env.POCKETBASE_ADMIN_EMAIL!,
          process.env.POCKETBASE_ADMIN_PASSWORD!
        );
    } catch (error) {
      console.error('Failed to authenticate PocketBase admin:', error);
      throw error;
    }
  }

  private async refreshAuth() {
    try {
      await this.pb.collection("_superusers").authRefresh();
    } catch (error) {
      console.error('Failed to refresh PocketBase admin token:', error);
      throw error;
    }
  }

  private isTokenExpiringSoon(): boolean {
    if (!this.pb.authStore.token) return false;

    try {
      const payload = JSON.parse(atob(this.pb.authStore.token.split('.')[1]));
      const expiresAt = payload.exp * 1000;
      const now = Date.now();
      const fiveMinutes = 5 * 60 * 1000;

      return expiresAt - now < fiveMinutes;
    } catch {
      return false;
    }
  }

  private startTokenRefresh() {
    this.refreshInterval = setInterval(async () => {
      try {
        await this.refreshAuth();
      } catch (error) {
        console.error('Periodic token refresh failed, re-authenticating:', error);
        try {
          await this.authenticate();
        } catch (authError) {
          console.error('Re-authentication failed:', authError);
        }
      }
    }, 10 * 60 * 1000);

    if (typeof process !== 'undefined') {
      process.on('beforeExit', () => {
        if (this.refreshInterval) {
          clearInterval(this.refreshInterval);
        }
      });
    }
  }
}

interface AdminClient
  extends PocketBaseAdminClient,
    ReturnType<typeof createPlayersService>,
    ReturnType<typeof createTeamsService>,
    ReturnType<typeof createTournamentsService>,
    ReturnType<typeof createMatchesService>,
    ReturnType<typeof createReactionsService>,
    ReturnType<typeof createActivitiesService>,
    ReturnType<typeof createBadgesService>,
    ReturnType<typeof createGroupsService>,
    ReturnType<typeof createPredictionsService>,
    ReturnType<typeof createPushService> {
  authPromise: Promise<void>;
}

export const pbAdmin = new PocketBaseAdminClient() as AdminClient;
