import { Injectable, OnModuleInit } from '@nestjs/common';
import { open, Reader, CityResponse } from 'maxmind';
import fs from 'fs';
import { Logger } from 'pino-nestjs';

export type GeoLookupResult = {
  country: string | null;
  countryCode: string | null;
  city: string | null;
  latitude: number | null;
  longitude: number | null;
};

@Injectable()
export class GeoService implements OnModuleInit {
  private reader: Reader<CityResponse> | null = null;

  constructor(private readonly logger: Logger) {}

  async onModuleInit(): Promise<void> {
    const dbPath = process.env.MAXMIND_DB_PATH;
    if (!dbPath) {
      this.logger.warn('GeoService.init: MAXMIND_DB_PATH not set; IP geolocation disabled');
      return;
    }
    if (!fs.existsSync(dbPath)) {
      this.logger.warn(`GeoService.init: MaxMind DB file not found at ${dbPath}; IP geolocation disabled`);
      return;
    }

    try {
      this.reader = await open<CityResponse>(dbPath);
      this.logger.log(`GeoService.init: MaxMind DB loaded from ${dbPath}`);
    } catch (error) {
      this.logger.error('GeoService.init: Failed to load MaxMind DB; IP geolocation disabled', error);
      this.reader = null;
    }
  }

  lookup(ip: string): GeoLookupResult | null {
    if (!this.reader || !ip) return null;

    try {
      const record = this.reader.get(ip);
      if (!record) return null;

      const country = record.country?.names?.en ?? null;
      const countryCode = record.country?.iso_code ?? null;
      const city = record.city?.names?.en ?? null;
      const latitude = record.location?.latitude ?? null;
      const longitude = record.location?.longitude ?? null;

      if (!country && !city && latitude == null) return null;

      return { country, countryCode, city, latitude, longitude };
    } catch (error) {
      this.logger.warn('GeoService.lookup: GeoIP lookup failed', { ip, error });
      return null;
    }
  }
}
