/**
 * Karibeo API Service
 * Integración con la API del sistema de aplicaciones turísticas
 */

const API_BASE_URL = 'https://karibeo.lesoluciones.net:8443/api/v1';

// Tipos de datos principales
export interface User {
  id: string;
  email: string;
  firstName: string;
  lastName: string;
  userType: 'tourist' | 'politur' | 'taxi_driver' | 'guide' | 'admin' | 'business';
  profilePhoto?: string;
  preferredLanguage: string;
  status: 'active' | 'inactive' | 'suspended';
  createdAt: string;
  updatedAt: string;
}

export interface Location {
  id: string;
  name: string;
  address: string;
  coordinates: {
    latitude: number;
    longitude: number;
  };
  city: string;
  country: string;
}

export interface PointOfInterest {
  id: string;
  locationId: string;
  name: string;
  description: string;
  category: string;
  subcategory?: string;
  tags: string[];
  images: string[];
  rating?: number;
  priceRange?: string;
  openingHours?: any;
}

export interface Reservation {
  id: string;
  userId: string;
  type: 'hotel' | 'restaurant' | 'tour';
  status: 'pending' | 'confirmed' | 'completed' | 'cancelled';
  referenceNumber: string;
  startDateTime: string;
  endDateTime?: string;
  numberOfPeople: number;
  totalAmount: number;
  paymentStatus: 'pending' | 'paid' | 'refunded';
}

// Clase principal del servicio API
class KaribeoAPI {
  private baseURL: string;
  private token: string | null = null;

  constructor(baseURL: string = API_BASE_URL) {
    this.baseURL = baseURL;
    this.token = localStorage.getItem('karibeo_token');
  }

  // Configurar token de autenticación
  setToken(token: string) {
    this.token = token;
    localStorage.setItem('karibeo_token', token);
  }

  // Limpiar token
  clearToken() {
    this.token = null;
    localStorage.removeItem('karibeo_token');
  }

  // Método base para realizar peticiones HTTP
  private async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<T> {
    const url = `${this.baseURL}${endpoint}`;
    
    const config: RequestInit = {
      headers: {
        'Content-Type': 'application/json',
        ...(this.token && { Authorization: `Bearer ${this.token}` }),
        ...options.headers,
      },
      ...options,
    };

    try {
      const response = await fetch(url, config);
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      return await response.json();
    } catch (error) {
      console.error('API request error:', error);
      throw error;
    }
  }

  // ============ AUTENTICACIÓN ============
  
  async register(userData: {
    email: string;
    password: string;
    firstName: string;
    lastName: string;
    userType: string;
  }) {
    return this.request<{ user: User; token: string }>('/auth/register', {
      method: 'POST',
      body: JSON.stringify(userData),
    });
  }

  async login(email: string, password: string) {
    return this.request<{ user: User; token: string }>('/auth/login', {
      method: 'POST',
      body: JSON.stringify({ email, password }),
    });
  }

  async getProfile() {
    return this.request<User>('/auth/profile');
  }

  // ============ USUARIOS ============
  
  async getUsers(page = 1, limit = 10) {
    return this.request<{ data: User[]; total: number; page: number; limit: number }>(
      `/users?page=${page}&limit=${limit}`
    );
  }

  async getUserById(id: string) {
    return this.request<User>(`/users/${id}`);
  }

  async updateUserProfile(userData: Partial<User>) {
    return this.request<User>('/users/me', {
      method: 'PATCH',
      body: JSON.stringify(userData),
    });
  }

  async getUserStats() {
    return this.request<any>('/users/stats');
  }

  // ============ UBICACIONES ============
  
  async getLocations(params?: {
    city?: string;
    country?: string;
    search?: string;
    page?: number;
    limit?: number;
  }) {
    const searchParams = new URLSearchParams();
    if (params) {
      Object.entries(params).forEach(([key, value]) => {
        if (value !== undefined) {
          searchParams.append(key, value.toString());
        }
      });
    }
    
    return this.request<{ data: Location[]; total: number }>
      (`/locations?${searchParams.toString()}`);
  }

  async getLocationById(id: string) {
    return this.request<Location>(`/locations/${id}`);
  }

  async createLocation(locationData: Omit<Location, 'id'>) {
    return this.request<Location>('/locations', {
      method: 'POST',
      body: JSON.stringify(locationData),
    });
  }

  // ============ PUNTOS DE INTERÉS ============
  
  async getPOIs(params?: {
    category?: string;
    city?: string;
    search?: string;
    page?: number;
    limit?: number;
  }) {
    const searchParams = new URLSearchParams();
    if (params) {
      Object.entries(params).forEach(([key, value]) => {
        if (value !== undefined) {
          searchParams.append(key, value.toString());
        }
      });
    }
    
    return this.request<{ data: PointOfInterest[]; total: number }>
      (`/points-of-interest?${searchParams.toString()}`);
  }

  async getPOIById(id: string) {
    return this.request<PointOfInterest>(`/points-of-interest/${id}`);
  }

  async createPOI(poiData: Omit<PointOfInterest, 'id'>) {
    return this.request<PointOfInterest>('/points-of-interest', {
      method: 'POST',
      body: JSON.stringify(poiData),
    });
  }

  // ============ RESERVAS ============
  
  async getReservations(params?: {
    userId?: string;
    type?: string;
    status?: string;
    page?: number;
    limit?: number;
  }) {
    const searchParams = new URLSearchParams();
    if (params) {
      Object.entries(params).forEach(([key, value]) => {
        if (value !== undefined) {
          searchParams.append(key, value.toString());
        }
      });
    }
    
    return this.request<{ data: Reservation[]; total: number }>
      (`/reservations?${searchParams.toString()}`);
  }

  async getReservationById(id: string) {
    return this.request<Reservation>(`/reservations/${id}`);
  }

  async createReservation(reservationData: Omit<Reservation, 'id'>) {
    return this.request<Reservation>('/reservations', {
      method: 'POST',
      body: JSON.stringify(reservationData),
    });
  }

  async updateReservation(id: string, updates: Partial<Reservation>) {
    return this.request<Reservation>(`/reservations/${id}`, {
      method: 'PATCH',
      body: JSON.stringify(updates),
    });
  }

  async cancelReservation(id: string) {
    return this.request<Reservation>(`/reservations/${id}/cancel`, {
      method: 'POST',
    });
  }

  // ============ BÚSQUEDA ============
  
  async search(query: string, filters?: {
    type?: 'location' | 'poi' | 'business';
    category?: string;
    city?: string;
  }) {
    const searchParams = new URLSearchParams({ q: query });
    if (filters) {
      Object.entries(filters).forEach(([key, value]) => {
        if (value) searchParams.append(key, value);
      });
    }
    
    return this.request<{
      locations: Location[];
      pois: PointOfInterest[];
      businesses: any[];
    }>(`/search?${searchParams.toString()}`);
  }

  // ============ MÉTODOS DE CONVENIENCIA ============
  
  // Obtener destinos populares
  async getPopularDestinations() {
    return this.getPOIs({ 
      page: 1, 
      limit: 6 
    });
  }

  // Buscar lugares cerca de una ubicación
  async getNearbyPlaces(latitude: number, longitude: number, radius = 5000) {
    return this.request<{ data: PointOfInterest[] }>
      (`/search/nearby?lat=${latitude}&lng=${longitude}&radius=${radius}`);
  }

  // Obtener estadísticas del dashboard
  async getDashboardStats() {
    return this.request<{
      totalUsers: number;
      totalReservations: number;
      totalLocations: number;
      totalPOIs: number;
    }>('/dashboard/stats');
  }
}

// Instancia singleton del servicio API
export const karibeoAPI = new KaribeoAPI();

// Hooks personalizados para React Query (opcional)
export const useAuth = () => {
  return {
    login: karibeoAPI.login.bind(karibeoAPI),
    register: karibeoAPI.register.bind(karibeoAPI),
    logout: () => karibeoAPI.clearToken(),
    getProfile: karibeoAPI.getProfile.bind(karibeoAPI),
  };
};

export default karibeoAPI;