const User = require('../models/User');
const asyncHandler = require('../middleware/async');
const ErrorResponse = require('../utils/errorResponse');
const axios = require('axios');

// @desc    Geocode address to coordinates
// @route   GET /api/v1/location/geocode
// @access  Public
const geocode = asyncHandler(async (req, res, next) => {
  const { address } = req.query;

  if (!address) {
    return next(new ErrorResponse('Please provide an address', 400));
  }

  try {
    // This is a placeholder - you'll need to implement actual geocoding logic
    // For example, using a geocoding service like Google Maps, Mapbox, etc.
    // For now, we'll return a mock response
    res.status(200).json({
      success: true,
      data: {
        address,
        coordinates: {
          lat: 0,
          lng: 0
        },
        formattedAddress: address
      }
    });
  } catch (err) {
    console.error('Geocoding error:', err);
    return next(new ErrorResponse('Geocoding failed', 500));
  }
});

// @desc    Get nearby stores
// @route   GET /api/v1/location/nearby-stores
// @access  Public
// @desc    Get current user's location
// @route   GET /api/v1/location/current
// @access  Private
const getCurrentLocation = asyncHandler(async (req, res, next) => {
  try {
    const user = await User.findById(req.user.id).select('location');
    
    if (!user || !user.location) {
      return res.status(200).json({
        success: true,
        data: null,
        message: 'No location data found for this user'
      });
    }

    res.status(200).json({
      success: true,
      data: user.location
    });
  } catch (err) {
    console.error('Error getting current location:', err);
    return next(new ErrorResponse('Error retrieving location', 500));
  }
});

// @desc    Get nearby stores
// @route   GET /api/v1/location/nearby-stores
// @access  Public
const getNearbyStores = asyncHandler(async (req, res, next) => {
  const { lat, lng, radius = 5000 } = req.query; // radius in meters

  if (!lat || !lng) {
    return next(new ErrorResponse('Please provide latitude and longitude', 400));
  }

  try {
    // This is a placeholder - implement your actual store finding logic here
    // For example, querying your database for stores within the specified radius
    // For now, we'll return a mock response
    res.status(200).json({
      success: true,
      count: 0,
      data: []
    });
  } catch (err) {
    console.error('Error finding nearby stores:', err);
    return next(new ErrorResponse('Error finding nearby stores', 500));
  }
});

// @desc    Update user's location
// @route   PUT /api/v1/location
// @access  Private
const updateUserLocation = asyncHandler(async (req, res, next) => {
  const {
    address,
    city,
    state,
    country,
    coordinates,
    formattedAddress,
    pincode
  } = req.body;

  // Validate required fields
  if (!city || !state) {
    return next(new ErrorResponse('City and state are required', 400));
  }

  const locationData = {
    address: address || '',
    city,
    state,
    country: country || 'India',
    coordinates: coordinates || [0, 0],
    formattedAddress: formattedAddress || `${address}, ${city}, ${state}, ${country || 'India'}`,
    pincode: pincode || ''
  };

  const user = await User.findByIdAndUpdate(
    req.user.id,
    { location: locationData },
    { new: true, runValidators: true }
  );

  res.status(200).json({
    success: true,
    data: user.location
  });
});

// @desc    Get user's saved location
// @route   GET /api/v1/location
// @access  Private
const getUserLocation = asyncHandler(async (req, res, next) => {
  const user = await User.findById(req.user.id).select('location');

  if (!user) {
    return next(new ErrorResponse('User not found', 404));
  }

  res.status(200).json({
    success: true,
    data: user.location || null
  });
});

// @desc    Delete user's location
// @route   DELETE /api/v1/location
// @access  Private
const deleteUserLocation = asyncHandler(async (req, res, next) => {
  await User.findByIdAndUpdate(
    req.user.id,
    { $unset: { location: 1 } },
    { new: true }
  );

  res.status(200).json({
    success: true,
    data: {}
  });
});

// @desc    Detect user's location
// @route   GET /api/v1/location/detect
// @access  Private
const detectLocation = asyncHandler(async (req, res, next) => {
  // Implementation for detecting location
  // This would typically use a geolocation service or IP-based detection
  res.status(200).json({
    success: true,
    message: 'Location detection endpoint'
  });
});

// @desc    Reverse geocode coordinates to address
// @route   GET /api/v1/location/reverse
// @access  Public
const reverseGeocode = async (req, res, next) => {
  try {
    const { lat, lon } = req.query;

    if (!lat || !lon) {
      return res.status(400).json({
        success: false,
        error: "Latitude and longitude are required"
      });
    }

    // In a real implementation, you would call a geocoding service here
    // For example, using a service like OpenStreetMap Nominatim or Google Maps Geocoding API

    res.status(200).json({
      success: true,
      data: {
        latitude: parseFloat(lat),
        longitude: parseFloat(lon),
        address: 'Sample address from coordinates',
        // Add more address components as needed
      }
    });
  } catch (error) {
    console.error('Reverse geocoding error:', error);
    res.status(500).json({
      success: false,
      error: "Failed to retrieve location information"
    });
  }
};

module.exports = {
  updateUserLocation,
  getUserLocation,
  deleteUserLocation,
  detectLocation,
  reverseGeocode,
  geocode,
  getNearbyStores,
  getCurrentLocation
};
