import { DataSource, Repository } from "typeorm";
import { User } from "../entities/User";
import * as dotenv from "dotenv";

dotenv.config();

export class DatabaseService {
  private static instance: DatabaseService;
  private dataSource: DataSource;
  private userRepository: Repository<User>;

  private constructor() {
    const isMongoDb = process.env.DB_TYPE === "mongodb";

    this.dataSource = new DataSource({
      type: process.env.DB_TYPE as any,
      url: isMongoDb ? process.env.MONGO_URL : process.env.SQL_URL,
      synchronize: false,
      logging: false,
      entities: [User],
      ...(isMongoDb && { useUnifiedTopology: true }),
    });

    this.userRepository = this.dataSource.getRepository(User);
  }

  public static getInstance(): DatabaseService {
    if (!DatabaseService.instance) {
      DatabaseService.instance = new DatabaseService();
    }
    return DatabaseService.instance;
  }

  public async initialize(): Promise<void> {
    await this.dataSource.initialize();
    console.log("Database connection established successfully.");
  }

  public async findUserByEmail(email: string): Promise<User | null> {
    return await this.userRepository.findOne({ where: { email } });
  }

  public async createUser(userData: Partial<User>): Promise<User> {
    const user = this.userRepository.create(userData);
    return await this.userRepository.save(user);
  }

  /**
   * Update a user by id with new user data
   * @param id - User ID (either number or string, depending on DB type)
   * @param userData - The data to update in the user record
   * @returns The updated user, or null if no user was found
   */
  public async updateUser(id: string | number, userData: Partial<User>): Promise<User | null> {
    const user = await this.userRepository.findOne({ where: { id: id as any } });
    if (!user) {
      return null; // User not found
    }

    // Update user fields
    await this.userRepository.update(id, userData);
    return await this.userRepository.findOne({ where: { id: id as any } });
  }
}
