import {
  ShortenerService,
  ShortifyOptions,
  ShortifyResult,
} from "./services/shortener.service";
import {
  IDatabaseAdapter,
  IUrl,
  DatabaseConfig,
} from "./interfaces/database.interface";
import { DatabaseFactory } from "./factories/database.factory";

// Main class that bundles all functionality
export class Shortify {
  private shortenerService: ShortenerService;
  private dbAdapter: IDatabaseAdapter;
  private isConnected: boolean = false;

  /**
   * Create a new Shortify instance
   * @param baseUrl - Base URL for shortened links
   * @param dbConfig - Database configuration
   */
  constructor(baseUrl: string, dbConfig: DatabaseConfig) {
    this.dbAdapter = DatabaseFactory.createAdapter(dbConfig);
    this.shortenerService = new ShortenerService(baseUrl, this.dbAdapter);

    // Handle DB connection events
    this.dbAdapter.on("connected", () => {
      this.isConnected = true;
    });

    this.dbAdapter.on("disconnected", () => {
      this.isConnected = false;
    });

    this.dbAdapter.on("error", (err: Error) => {
      console.error("Shortify DB error:", err);
    });
  }

  /**
   * Create a new Shortify instance with MongoDB (backward compatibility)
   * @param baseUrl - Base URL for shortened links
   * @param mongoUri - MongoDB connection URI
   * @param options - Additional options for MongoDB connection
   */
  static createWithMongo(
    baseUrl: string,
    mongoUri: string,
    options: {
      maxRetries?: number;
      retryDelay?: number;
      collectionName?: string;
    } = {}
  ): Shortify {
    return new Shortify(baseUrl, {
      type: "mongodb",
      connectionString: mongoUri,
      maxRetries: options.maxRetries,
      retryDelay: options.retryDelay,
      collectionName: options.collectionName,
    });
  }

  /**
   * Connect to database
   */
  async connect(): Promise<boolean> {
    return this.dbAdapter.connect();
  }

  /**
   * Disconnect from database
   */
  async disconnect(): Promise<void> {
    return this.dbAdapter.disconnect();
  }

  /**
   * Check connection status
   */
  isReady(): boolean {
    return this.isConnected;
  }

  /**
   * Shorten a URL
   */
  async shorten(
    url: string,
    options: Partial<ShortifyOptions> = {}
  ): Promise<ShortifyResult> {
    if (!this.isConnected) {
      throw new Error("Database connection not established");
    }
    return this.shortenerService.shorten(url, options);
  }

  /**
   * Resolve a short URL ID to its original URL
   */
  async resolve(urlId: string): Promise<string | null> {
    if (!this.isConnected) {
      throw new Error("Database connection not established");
    }
    return this.shortenerService.resolve(urlId);
  }

  /**
   * Get statistics for a shortened URL
   */
  async getStats(urlId: string): Promise<Partial<IUrl> | null> {
    if (!this.isConnected) {
      throw new Error("Database connection not established");
    }
    return this.shortenerService.getUrlStats(urlId);
  }

  /**
   * Delete a shortened URL
   */
  async delete(urlId: string): Promise<boolean> {
    if (!this.isConnected) {
      throw new Error("Database connection not established");
    }
    return this.shortenerService.deleteUrl(urlId);
  }
}

// Export all types and classes
export { ShortifyOptions, ShortifyResult, IUrl };
export {
  DatabaseConfig,
  IDatabaseAdapter,
} from "./interfaces/database.interface";
export { DatabaseFactory } from "./factories/database.factory";
export default Shortify;
