import type { BoundingBox } from '../types/index.js';

/**
 * Utility functions for working with BODS data
 */

/**
 * Create a bounding box from a center point and radius
 * 
 * @param centerLat - Center latitude
 * @param centerLng - Center longitude  
 * @param radiusKm - Radius in kilometers
 * @returns Bounding box coordinates [minLng, minLat, maxLng, maxLat]
 * 
 * @example
 * ```typescript
 * import { createBoundingBox } from 'bods-js/utils';
 * 
 * // Manchester city center, 10km radius
 * const bbox = createBoundingBox(53.4808, -2.2426, 10);
 * const vehicles = await client.avl.getByArea(bbox);
 * ```
 */
export function createBoundingBox(centerLat: number, centerLng: number, radiusKm: number): BoundingBox {
  // Approximate degrees per kilometer
  const latDegPerKm = 1 / 111;
  const lngDegPerKm = 1 / (111 * Math.cos(centerLat * Math.PI / 180));
  
  const latOffset = radiusKm * latDegPerKm;
  const lngOffset = radiusKm * lngDegPerKm;
  
  return [
    centerLng - lngOffset, // minLng
    centerLat - latOffset, // minLat
    centerLng + lngOffset, // maxLng
    centerLat + latOffset  // maxLat
  ];
}

/**
 * Check if a point is within a bounding box
 * 
 * @param lat - Point latitude
 * @param lng - Point longitude
 * @param boundingBox - Bounding box to check against
 * @returns True if point is within the bounding box
 * 
 * @example
 * ```typescript
 * import { isPointInBoundingBox } from 'bods-js/utils';
 * 
 * const manchester = createBoundingBox(53.4808, -2.2426, 10);
 * const isInManchester = isPointInBoundingBox(53.4808, -2.2426, manchester); // true
 * ```
 */
export function isPointInBoundingBox(lat: number, lng: number, boundingBox: BoundingBox): boolean {
  const [minLng, minLat, maxLng, maxLat] = boundingBox;
  return lng >= minLng && lng <= maxLng && lat >= minLat && lat <= maxLat;
}

/**
 * Calculate distance between two points using Haversine formula
 * 
 * @param lat1 - First point latitude
 * @param lng1 - First point longitude
 * @param lat2 - Second point latitude
 * @param lng2 - Second point longitude
 * @returns Distance in kilometers
 * 
 * @example
 * ```typescript
 * import { calculateDistance } from 'bods-js/utils';
 * 
 * const distance = calculateDistance(53.4808, -2.2426, 51.5074, -0.1278); // Manchester to London
 * console.log(`Distance: ${distance.toFixed(2)}km`);
 * ```
 */
export function calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
  const R = 6371; // Earth's radius in kilometers
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLng = (lng2 - lng1) * Math.PI / 180;
  const a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * 
    Math.sin(dLng/2) * Math.sin(dLng/2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  return R * c;
}

/**
 * Format a date for BODS API queries
 * 
 * @param date - Date to format
 * @returns ISO string formatted for BODS API
 * 
 * @example
 * ```typescript
 * import { formatDateForAPI } from 'bods-js/utils';
 * 
 * const formatted = formatDateForAPI(new Date());
 * const timetables = await client.timetables.search({
 *   modifiedDate: formatted
 * });
 * ```
 */
export function formatDateForAPI(date: Date): string {
  return date.toISOString();
}

/**
 * Parse an ISO date string to Date object
 * 
 * @param dateString - ISO date string
 * @returns Date object
 * 
 * @example
 * ```typescript
 * import { parseDateFromAPI } from 'bods-js/utils';
 * 
 * const date = parseDateFromAPI('2023-01-01T12:45:00+00:00');
 * ```
 */
export function parseDateFromAPI(dateString: string): Date {
  return new Date(dateString);
}

/**
 * Validate National Operator Code format
 * 
 * @param noc - National Operator Code to validate
 * @returns True if NOC format appears valid
 * 
 * @example
 * ```typescript
 * import { isValidNOC } from 'bods-js/utils';
 * 
 * console.log(isValidNOC('SCMN')); // true
 * console.log(isValidNOC('invalid')); // false
 * ```
 */
export function isValidNOC(noc: string): boolean {
  // NOCs are typically 4 characters, alphanumeric
  return /^[A-Z0-9]{4}$/.test(noc);
}

/**
 * Validate API key format
 * 
 * @param apiKey - API key to validate
 * @returns True if API key format appears valid
 * 
 * @example
 * ```typescript
 * import { isValidAPIKey } from 'bods-js/utils';
 * 
 * const isValid = isValidAPIKey('your-api-key');
 * ```
 */
export function isValidAPIKey(apiKey: string): boolean {
  // API keys are typically 40 character hex strings
  return /^[a-f0-9]{40}$/.test(apiKey);
}

/**
 * Get common UK city bounding boxes
 */
export const UK_CITIES = {
  LONDON: createBoundingBox(51.5074, -0.1278, 30),
  MANCHESTER: createBoundingBox(53.4808, -2.2426, 15),
  BIRMINGHAM: createBoundingBox(52.4862, -1.8904, 15),
  LEEDS: createBoundingBox(53.8008, -1.5491, 15),
  LIVERPOOL: createBoundingBox(53.4084, -2.9916, 15),
  BRISTOL: createBoundingBox(51.4545, -2.5879, 15),
  SHEFFIELD: createBoundingBox(53.3811, -1.4701, 15),
  LEICESTER: createBoundingBox(52.6369, -1.1398, 10),
  COVENTRY: createBoundingBox(52.4068, -1.5197, 10),
  BRADFORD: createBoundingBox(53.7959, -1.7594, 10)
} as const;
