import { ConfigService } from '@nestjs/config';

export const DEFAULT_MONGODB_URI = 'mongodb://127.0.0.1:27017/trip_track';

export const DEFAULT_REDIS_URL = 'redis://127.0.0.1:6379';

export const DEV_JWT_ACCESS_SECRET =
  'development-only-jwt-access-secret-min-32-chars';

export const DEV_JWT_REFRESH_SECRET =
  'development-only-jwt-refresh-secret-min-32-chars';

export function resolveMongoUri(cfg: ConfigService): string {
  const uri = cfg.get<string>('MONGODB_URI') ?? process.env.MONGODB_URI;
  if (uri?.trim()) return uri.trim();
  if (process.env.NODE_ENV === 'production') {
    throw new Error('MONGODB_URI is required in production');
  }
  return DEFAULT_MONGODB_URI;
}

export function resolveRedisUrl(cfg: ConfigService): string {
  const url = cfg.get<string>('REDIS_URL') ?? process.env.REDIS_URL;
  if (url?.trim()) return url.trim();
  if (process.env.NODE_ENV === 'production') {
    throw new Error('REDIS_URL is required in production');
  }
  return DEFAULT_REDIS_URL;
}

export function isRedisEnabled(cfg: ConfigService): boolean {
  const raw = cfg.get<string>('REDIS_ENABLED') ?? process.env.REDIS_ENABLED;
  if (raw === undefined || raw === '') {
    return process.env.NODE_ENV === 'production';
  }
  return raw === '1' || raw.toLowerCase() === 'true';
}

export function resolveJwtAccessSecret(cfg: ConfigService): string {
  const s =
    cfg.get<string>('JWT_ACCESS_SECRET') ?? process.env.JWT_ACCESS_SECRET;
  if (s?.trim()) return s.trim();
  if (process.env.NODE_ENV === 'production') {
    throw new Error('JWT_ACCESS_SECRET is required in production');
  }
  return DEV_JWT_ACCESS_SECRET;
}

export function resolveJwtRefreshSecret(cfg: ConfigService): string {
  const s =
    cfg.get<string>('JWT_REFRESH_SECRET') ?? process.env.JWT_REFRESH_SECRET;
  if (s?.trim()) return s.trim();
  if (process.env.NODE_ENV === 'production') {
    throw new Error('JWT_REFRESH_SECRET is required in production');
  }
  return DEV_JWT_REFRESH_SECRET;
}

export function parseDurationMs(raw: string, fallbackMs: number): number {
  const m = /^(\d+)([dhms])$/.exec(raw.trim());
  if (!m) return fallbackMs;
  const n = parseInt(m[1], 10);
  const u = m[2];
  const mult =
    u === 'd' ? 86400000 : u === 'h' ? 3600000 : u === 'm' ? 60000 : 1000;
  return n * mult;
}

export function geofenceRadiusMeters(cfg: ConfigService): number {
  return Number(cfg.get('GEOFENCE_ARRIVAL_RADIUS_METERS') ?? 500);
}

export function geofenceDepartureRadiusMeters(cfg: ConfigService): number {
  return Number(cfg.get('GEOFENCE_DEPARTURE_RADIUS_METERS') ?? 500);
}

export function gpsTrackingIntervalSeconds(cfg: ConfigService): number {
  return Number(cfg.get('GPS_TRACKING_INTERVAL_SECONDS') ?? 30);
}

export function gpsStopDetectionMinutes(cfg: ConfigService): number {
  return Number(cfg.get('GPS_STOP_DETECTION_MINUTES') ?? 5);
}

export function gpsDuplicateThresholdMeters(cfg: ConfigService): number {
  return Number(cfg.get('GPS_DUPLICATE_THRESHOLD_METERS') ?? 5);
}

export function isLiveTrackingWsEnabled(cfg: ConfigService): boolean {
  const raw =
    cfg.get<string>('LIVE_TRACKING_WS_ENABLED') ??
    process.env.LIVE_TRACKING_WS_ENABLED;
  if (raw === undefined || raw === '') return true;
  return raw === '1' || raw.toLowerCase() === 'true';
}

/** Minimum seconds between accepted live socket points per trip. */
export function gpsLiveMinIntervalMs(cfg: ConfigService): number {
  return Number(cfg.get('GPS_LIVE_MIN_INTERVAL_MS') ?? 2000);
}

/** Ignore socket point if moved less than this since last accepted point. */
export function gpsLiveMinDistanceMeters(cfg: ConfigService): number {
  return Number(cfg.get('GPS_LIVE_MIN_DISTANCE_METERS') ?? 3);
}

/** Gap between route points above this → untracked period (seconds). */
export function trackingCoverageGapThresholdSeconds(cfg: ConfigService): number {
  return Number(cfg.get('TRACKING_COVERAGE_GAP_THRESHOLD_SECONDS') ?? 90);
}
