/**
 * URL Builder MCP - Core Implementation
 *
 * Constructs URLs following project-specific rules
 */

import { UrlParams, BookingUrlParams, ValidationResult, UrlBuilderConfig, UtmParams, UrlOptions } from './types';

/**
 * Get configuration from environment variables
 */
function getConfig(): UrlBuilderConfig {
  // Use BASE_DOMAIN as the primary configuration
  // Fall back to BOOKING_URL_BASE for backward compatibility
  const baseDomain =
    process.env.BASE_DOMAIN || process.env.MCP_BASE_DOMAIN || process.env.BOOKING_URL_BASE || 'http://localhost:8080';

  return {
    bookingUrlBase: baseDomain,
    defaultCurrency: process.env.DEFAULT_CURRENCY || 'eur',
    baseDomain: baseDomain,
  };
}

/**
 * Generate intelligent UTM parameters for MCP traffic tracking
 *
 * @param customUtm - Custom UTM parameters to override defaults
 * @returns UTM parameters object
 */
function generateUtmParams(customUtm?: Partial<UtmParams>): UtmParams {
  const defaultUtm: UtmParams = {
    utm_source: 'claude-desktop',
    utm_medium: 'ai-assistant',
    utm_campaign: 'url-builder-mcp',
    utm_content: 'mcp-generated-link',
  };

  return { ...defaultUtm, ...customUtm };
}

/**
 * Add UTM parameters to a URLSearchParams object
 *
 * @param searchParams - URLSearchParams to modify
 * @param utmParams - UTM parameters to add
 */
function addUtmToSearchParams(searchParams: URLSearchParams, utmParams: UtmParams): void {
  Object.entries(utmParams).forEach(([key, value]) => {
    if (value) {
      searchParams.append(key, value);
    }
  });
}

/**
 * Validate URL parameters before building URLs
 *
 * @param params - URL parameters to validate
 * @returns ValidationResult with valid flag and error messages
 */
export function validateUrlParams(params: UrlParams): ValidationResult {
  const errors: string[] = [];

  // Validate required fields
  if (!params.checkIn || !params.checkOut) {
    errors.push('checkIn y checkOut son requeridos');
  }

  // Validate date format (YYYY-MM-DD)
  const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
  if (params.checkIn && !dateRegex.test(params.checkIn)) {
    errors.push('Formato de checkIn inválido. Use YYYY-MM-DD');
  }
  if (params.checkOut && !dateRegex.test(params.checkOut)) {
    errors.push('Formato de checkOut inválido. Use YYYY-MM-DD');
  }

  // Validate date range
  if (params.checkIn && params.checkOut) {
    const checkInDate = new Date(params.checkIn + 'T00:00:00.000Z');
    const checkOutDate = new Date(params.checkOut + 'T00:00:00.000Z');
    const today = new Date();
    const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate());

    // Check if check-in date is in the past
    if (checkInDate < todayStart) {
      errors.push('La fecha de entrada no puede ser anterior a hoy');
    }

    // Check if check-out date is in the past
    if (checkOutDate < todayStart) {
      errors.push('La fecha de salida no puede ser anterior a hoy');
    }

    if (checkInDate >= checkOutDate) {
      errors.push('La fecha de salida debe ser posterior a la de entrada');
    }
  }

  // Validate optional ranges
  if (params.adults !== undefined && (params.adults < 1 || params.adults > 20)) {
    errors.push('Número de adultos debe estar entre 1 y 20');
  }

  if (params.children !== undefined && (params.children < 0 || params.children > 10)) {
    errors.push('Número de niños debe estar entre 0 y 10');
  }

  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * Validate booking URL parameters specifically
 *
 * @param params - Booking URL parameters to validate
 * @returns ValidationResult with valid flag and error messages
 */
function validateBookingUrlParams(params: UrlParams): ValidationResult {
  const errors: string[] = [];

  // Validate required fields for booking
  if (!params.checkIn || !params.checkOut) {
    errors.push('checkIn y checkOut son requeridos');
  }

  if (!params.guestName) {
    errors.push('guestName es requerido para URLs de reserva');
  }

  if (!params.guestPhone) {
    errors.push('guestPhone es requerido para URLs de reserva');
  }

  // Use base validation for the rest (including date validation)
  const baseValidation = validateUrlParams(params);
  errors.push(...baseValidation.errors.filter(error => !error.includes('checkIn y checkOut son requeridos')));

  return {
    valid: errors.length === 0,
    errors,
  };
}

/**
 * Build external booking URL with query parameters
 *
 * @param params - URL parameters
 * @returns Formatted booking URL with query parameters
 */
export function buildBookingUrl(params: UrlParams, options?: UrlOptions): string {
  // Validate parameters specifically for booking
  const validation = validateBookingUrlParams(params);
  if (!validation.valid) {
    throw new Error(`Parámetros inválidos: ${validation.errors.join(', ')}`);
  }

  // Type assertion after validation
  const bookingParams = params as BookingUrlParams;

  const config = getConfig();
  const baseUrl = config.bookingUrlBase;

  // Determine if this is a localhost URL or external URL
  const isLocalhost = baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1');
  const isExternal = baseUrl.includes('cloudbeds.com') || (!isLocalhost && baseUrl.startsWith('https://'));

  // Build parameters
  const searchParams = new URLSearchParams();

  if (isExternal) {
    // External URLs (Cloudbeds) use hash fragment format with specific parameter names
    if (bookingParams.roomType) {
      searchParams.append('roomType', bookingParams.roomType);
    }
    searchParams.append('checkin', bookingParams.checkIn); // Note: 'checkin' not 'checkIn'
    searchParams.append('checkout', bookingParams.checkOut); // Note: 'checkout' not 'checkOut'
    searchParams.append('currency', config.defaultCurrency);
    searchParams.append('adults', (bookingParams.adults || 2).toString());

    if (bookingParams.children && bookingParams.children > 0) {
      searchParams.append('children', bookingParams.children.toString());
    }

    searchParams.append('guestName', bookingParams.guestName);
    if (bookingParams.guestEmail) {
      searchParams.append('guestEmail', bookingParams.guestEmail);
    }
    searchParams.append('guestPhone', bookingParams.guestPhone);

    // Add UTM tracking if enabled (default: true for external URLs)
    if (options?.addUtmTracking !== false) {
      const utmParams = generateUtmParams(options?.customUtm);
      addUtmToSearchParams(searchParams, utmParams);
    }

    return `${baseUrl}#${searchParams.toString()}`;
  } else {
    // Localhost URLs use query parameters format with /accommodation/reservations path
    const localhostBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;

    if (bookingParams.roomType) {
      searchParams.append('roomType', bookingParams.roomType);
    }
    searchParams.append('checkIn', bookingParams.checkIn);
    searchParams.append('checkOut', bookingParams.checkOut);
    searchParams.append('adults', (bookingParams.adults || 2).toString());

    if (bookingParams.children && bookingParams.children > 0) {
      searchParams.append('children', bookingParams.children.toString());
    }

    searchParams.append('guestName', bookingParams.guestName);
    if (bookingParams.guestEmail) {
      searchParams.append('guestEmail', bookingParams.guestEmail);
    }
    searchParams.append('guestPhone', bookingParams.guestPhone);

    // Add UTM tracking if enabled (default: true)
    if (options?.addUtmTracking !== false) {
      const utmParams = generateUtmParams(options?.customUtm);
      addUtmToSearchParams(searchParams, utmParams);
    }

    return `${localhostBase}/accommodation/reservations?${searchParams.toString()}`;
  }
}

/**
 * Build internal project URL with query parameters
 *
 * @param params - URL parameters
 * @param options - Options for URL building
 * @returns Formatted internal URL with query parameters
 */
export function buildInternalUrl(params: UrlParams, options?: UrlOptions): string {
  // Validate parameters
  const validation = validateUrlParams(params);
  if (!validation.valid) {
    throw new Error(`Parámetros inválidos: ${validation.errors.join(', ')}`);
  }

  const config = getConfig();
  let baseUrl = '/accommodation/reservations';

  // Use base domain if requested
  if (options?.useBaseDomain) {
    baseUrl = `${config.baseDomain}/accommodation/reservations`;
  }

  // Build search parameters in the specified order
  const searchParams = new URLSearchParams();

  // Add required date parameters
  searchParams.append('checkIn', params.checkIn);
  searchParams.append('checkOut', params.checkOut);

  // Add optional parameters in order
  if (params.roomType) {
    searchParams.append('roomType', params.roomType);
  }

  if (params.adults !== undefined) {
    searchParams.append('adults', params.adults.toString());
  }

  if (params.children !== undefined && params.children > 0) {
    searchParams.append('children', params.children.toString());
  }

  if (params.guestName) {
    searchParams.append('guestName', params.guestName);
  }

  if (params.guestEmail) {
    searchParams.append('guestEmail', params.guestEmail);
  }

  if (params.guestPhone) {
    searchParams.append('guestPhone', params.guestPhone);
  }

  // Add UTM tracking if enabled (default: true)
  if (options?.addUtmTracking !== false) {
    const utmParams = generateUtmParams(options?.customUtm);
    addUtmToSearchParams(searchParams, utmParams);
  }

  return `${baseUrl}?${searchParams.toString()}`;
}

/**
 * Build complete URL using configurable base domain
 *
 * @param relativePath - Relative path to append to base domain
 * @param params - Optional URL parameters
 * @returns Complete URL with base domain and optional parameters
 */
export function buildCompleteUrl(relativePath: string, params?: UrlParams, options?: UrlOptions): string {
  const config = getConfig();

  // Validate parameters if provided
  if (params) {
    const validation = validateUrlParams(params);
    if (!validation.valid) {
      throw new Error(`Parámetros inválidos: ${validation.errors.join(', ')}`);
    }
  }

  // Ensure relativePath starts with / and handle base domain trailing slash
  const path = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;
  const baseDomain = config.baseDomain.endsWith('/') ? config.baseDomain.slice(0, -1) : config.baseDomain;
  let url = `${baseDomain}${path}`;

  // Add parameters if provided
  if (params) {
    const searchParams = new URLSearchParams();

    if (params.checkIn) {
      searchParams.append('checkIn', params.checkIn);
    }

    if (params.checkOut) {
      searchParams.append('checkOut', params.checkOut);
    }

    if (params.adults !== undefined) {
      searchParams.append('adults', params.adults.toString());
    }

    if (params.children !== undefined && params.children > 0) {
      searchParams.append('children', params.children.toString());
    }

    if (params.guestName) {
      searchParams.append('guestName', params.guestName);
    }

    if (params.guestEmail) {
      searchParams.append('guestEmail', params.guestEmail);
    }

    if (params.guestPhone) {
      searchParams.append('guestPhone', params.guestPhone);
    }

    // Add UTM tracking if enabled (default: true)
    if (options?.addUtmTracking !== false) {
      const utmParams = generateUtmParams(options?.customUtm);
      addUtmToSearchParams(searchParams, utmParams);
    }

    if (searchParams.toString()) {
      url += `?${searchParams.toString()}`;
    }
  }

  return url;
}
