const Seller = require('../models/Store');
const User = require('../models/User');
const { deleteFile, getUploadsPath } = require('../utils/fileUtils');
const path = require('path');
const fs = require('fs').promises;

// Get all stores with pagination and search
const getAllStores = async (req, res) => {
  try {
    const {
      page = 1,
      limit = 10,
      search,
      status,
      city,
      sortBy = 'createdAt',
      sortOrder = 'desc'
    } = req.query;

    const options = {
      page: parseInt(page),
      limit: parseInt(limit),
      search: search || undefined,
      status: status || undefined,
      city: city || undefined
    };

    const result = await Seller.findAllActive(options);

    res.json({
      success: true,
      data: result.items,
      pagination: {
        currentPage: result.currentPage,
        totalPages: result.totalPages,
        totalStores: result.total,
        hasNextPage: result.hasNextPage,
        hasPreviousPage: result.hasPreviousPage
      },
      msg: 'Stores retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching stores:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching stores'
    });
  }
};

// Get store by ID with details
const getStoreById = async (req, res) => {
  try {
    const { id } = req.params;
    const store = await Seller.findByIdWithDetails(id);
    
    if (!store) {
      return res.status(404).json({
        success: false,
        msg: 'Store not found'
      });
    }
    
    res.json({
      success: true,
      data: store,
      msg: 'Store retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching store:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching store'
    });
  }
};

// Create new store
const createStore = async (req, res) => {
  let uploadedFiles = []; // Track uploaded files for cleanup

  try {
    // Initialize storeData with request body
    const storeData = { ...req.body };

    // Function to safely parse JSON or return default value
    const safeJsonParse = (data, defaultValue = {}) => {
      if (!data) return defaultValue;
      if (typeof data === 'object') return data;
      try {
        return JSON.parse(data);
      } catch (e) {
        return defaultValue;
      }
    };

    // Handle nested store data
    storeData.store = safeJsonParse(req.body.store, {
      storeName: req.body.storeName || '',
      categoryIds: req.body.categoryIds || [],
      productStatus: req.body.productStatus || 'Active',
      taxName: req.body.taxName || '',
      taxNumber: req.body.taxNumber || '',
      panNumber: req.body.panNumber || '',
      commission: req.body.commission || 0,
      description: req.body.description || ''
    });

    // Handle location data
    storeData.location = safeJsonParse(req.body.location, {
      street: req.body['location[street]'] || req.body.street || '',
      city: req.body['location[city]'] || req.body.city || '',
      state: req.body['location[state]'] || req.body.state || '',
      country: req.body['location[country]'] || req.body.country || 'India',
      pincode: req.body['location[pincode]'] || req.body.pincode || '',
      landmark: req.body['location[landmark]'] || req.body.landmark || '',
      locationPoint: {
        type: 'Point',
        coordinates: [0, 0]
      }
    });

    // Add location point if coordinates are provided
    if (req.body.latitude && req.body.longitude) {
      storeData.location.locationPoint = {
        type: 'Point',
        coordinates: [
          parseFloat(req.body.longitude),
          parseFloat(req.body.latitude)
        ]
      };
    }

    // Handle settings data
    storeData.settings = safeJsonParse(req.body.settings, {
      requireProductApproval: req.body.requireProductApproval === 'true' || false,
      viewCustomerDetails: req.body.viewCustomerDetails === 'true' || false
    });

    // Set default status if not provided
    storeData.status = storeData.status || 'active';

    // Validate required fields
    const requiredFields = [
      { field: 'name', message: 'Store owner name is required' },
      { field: 'email', message: 'Email is required' },
      { field: 'mobile', message: 'Mobile number is required' },
      { field: 'password', message: 'Password is required' },
      { field: 'store.storeName', message: 'Store name is required' },
      { field: 'location.street', message: 'Street address is required' },
      { field: 'location.city', message: 'City is required' },
      { field: 'location.state', message: 'State is required' },
      { field: 'location.country', message: 'Country is required' },
      { field: 'location.pincode', message: 'Pincode is required' }
    ];

    // Check required fields
    const validationErrors = [];
    for (const { field, message } of requiredFields) {
      const value = field.split('.').reduce((obj, key) => obj?.[key], storeData);
      if (!value || (typeof value === 'string' && !value.trim())) {
        validationErrors.push(message);
      }
    }

    if (validationErrors.length > 0) {
      throw new Error(`Validation failed: ${validationErrors.join(', ')}`);
    }

    // Handle uploaded files
    if (req.files) {
      const uploadsDir = path.join(process.cwd(), 'public', 'uploads', 'stores');
      await fs.mkdir(uploadsDir, { recursive: true });

      const fileTypes = ['logo', 'nationalIdCard', 'addressProof'];

      for (const fileType of fileTypes) {
        if (req.files[fileType]?.[0]) {
          const file = req.files[fileType][0];
          const fileExt = path.extname(file.originalname).toLowerCase();
          const allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf'];

          if (!allowedExtensions.includes(fileExt)) {
            throw new Error(`Invalid file type for ${fileType}. Allowed types: ${allowedExtensions.join(', ')}`);
          }

          // File is already saved by multer, just track its path
          uploadedFiles.push(file.path); // Track for cleanup

          if (!storeData.store) storeData.store = {};
          storeData.store[fileType] = `/uploads/stores/${file.filename}`;
        }
      }
    }

    // Create store and user together using the new method
    const result = await Seller.createStoreWithUser(storeData);

    res.status(201).json({
      success: true,
      data: {
        store: result.store,
        user: result.user
      },
      msg: 'Store and store manager created successfully'
    });
  } catch (error) {
    // No need to clean up records here as they're handled in the model's transaction

    // Clean up uploaded files if any
    for (const filePath of uploadedFiles) {
      try {
        await fs.unlink(filePath);
        console.log(`Cleaned up uploaded file: ${filePath}`);
      } catch (unlinkError) {
        console.error(`Error cleaning up uploaded file ${filePath}:`, unlinkError);
      }
    }

    console.error('Error creating store and store manager:', error);
    res.status(400).json({
      success: false,
      msg: error.message || 'Error creating store and store manager'
    });
  }
};

// Update store
const updateStore = async (req, res) => {
  let uploadedFiles = []; // Track uploaded files for cleanup

  try {
    const { id } = req.params;
    const updateData = { ...req.body };

    // Parse JSON strings from FormData
    try {
      if (updateData.store && typeof updateData.store === 'string') {
        updateData.store = JSON.parse(updateData.store);
      }
      if (updateData.settings && typeof updateData.settings === 'string') {
        updateData.settings = JSON.parse(updateData.settings);
      }
    } catch (parseError) {
      return res.status(400).json({
        success: false,
        msg: 'Invalid JSON data in request'
      });
    }

    // If email is being updated, find the corresponding store manager
    if (updateData.email) {
      const storeManager = await User.findOne({
        email: updateData.email,
        role: 'store_manager'
      });

      if (!storeManager) {
        return res.status(400).json({
          success: false,
          msg: 'No store manager found with the provided email. Please create a store manager user first.'
        });
      }

      // Set the store manager reference
      updateData.storeManager = storeManager._id;
    }

    // Get the existing store to check for old images
    const existingStore = await Seller.findById(id);
    if (!existingStore) {
      return res.status(404).json({
        success: false,
        msg: 'Store not found'
      });
    }

    // Initialize store object if it doesn't exist
    updateData.store = updateData.store || {};

    // Handle uploaded files and track old files for cleanup
    const filesToCleanup = [];

    // Helper function to handle file updates
    const handleFileUpdate = async (fieldName) => {
      const fileField = req.files?.[fieldName]?.[0];
      const removeField = req.body[`remove${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}`];

      // If a new file is uploaded
      if (fileField) {
        // Mark old file for cleanup if it exists
        if (existingStore.store?.[fieldName]) {
          const oldFilename = existingStore.store[fieldName].split('/').pop();
          filesToCleanup.push(path.join(process.cwd(), 'public', 'uploads', 'stores', oldFilename));
        }
        // Set new file path and track for cleanup if update fails
        uploadedFiles.push(fileField.path);
        return `/uploads/stores/${fileField.filename}`;
      }
      // If file is being removed
      else if (removeField === 'true') {
        // Mark old file for cleanup if it exists
        if (existingStore.store?.[fieldName]) {
          const oldFilename = existingStore.store[fieldName].split('/').pop();
          filesToCleanup.push(path.join(process.cwd(), 'public', 'uploads', 'stores', oldFilename));
        }
        return ''; // Clear the file path
      }
      // If no change, keep existing value
      return existingStore.store?.[fieldName] || '';
    };

    // Handle each file field
    if (req.files || req.body.removeLogo || req.body.removeNationalIdCard || req.body.removeAddressProof) {
      updateData.store.logo = await handleFileUpdate('logo');
      updateData.store.nationalIdCard = await handleFileUpdate('nationalIdCard');
      updateData.store.addressProof = await handleFileUpdate('addressProof');
    }

    let updatedStore;
    try {
      // Update the store in the database
      updatedStore = await Seller.updateSeller(id, updateData);

      if (!updatedStore) {
        return res.status(404).json({
          success: false,
          msg: 'Store not found or update failed'
        });
      }

      // Clean up old files only after successful update
      for (const filePath of filesToCleanup) {
        try {
          await deleteFile(filePath);
          console.log(`Cleaned up old file: ${filePath}`);
        } catch (error) {
          console.error(`Error deleting old file ${filePath}:`, error);
          // Continue with other files even if one fails
        }
      }

      res.json({
        success: true,
        data: updatedStore,
        msg: 'Store updated successfully'
      });
    } catch (error) {
      // Clean up any uploaded files if the update failed
      for (const filePath of uploadedFiles) {
        try {
          await deleteFile(filePath);
          console.log(`Cleaned up uploaded file after failed update: ${filePath}`);
        } catch (cleanupError) {
          console.error(`Error cleaning up file after failed update: ${filePath}`, cleanupError);
        }
      }
      throw error; // Re-throw to be caught by the outer catch
    }
  } catch (error) {
    console.error('Error updating store:', error);
    res.status(400).json({
      success: false,
      msg: error.message || 'Error updating store'
    });
  }
};

// Toggle store status
const toggleStoreStatus = async (req, res) => {
  try {
    const { id } = req.params;
    const { status } = req.body;
    
    const updatedStore = await Seller.updateStatus(id, status);
    
    if (!updatedStore) {
      return res.status(404).json({
        success: false,
        msg: 'Store not found'
      });
    }
    
    res.json({
      success: true,
      data: updatedStore,
      msg: `Store status updated to ${status} successfully`
    });
  } catch (error) {
    console.error('Error updating store status:', error);
    res.status(400).json({
      success: false,
      msg: error.message || 'Error updating store status'
    });
  }
};

// Delete store (hard delete)
const deleteStore = async (req, res) => {
  try {
    const { id } = req.params;
    
    // Find the store first to get the image details before deletion
    const store = await Seller.findById(id);
    
    if (!store) {
      return res.status(404).json({
        success: false,
        msg: 'Store not found'
      });
    }
    
    // Function to delete a file with multiple possible paths
    const deleteStoreFile = async (filePath, fileType) => {
      if (!filePath) return false;
      
      // If it's an object with url property, use that
      if (typeof filePath === 'object' && filePath.url) {
        filePath = filePath.url;
      }

      if (!filePath) {
        console.log(`No valid path found for store ${fileType}`);
        return false;
      }

      // Extract just the filename from the path/URL
      const filename = path.basename(filePath);
      
      // Get the base uploads directory
      const uploadsBase = path.join(__dirname, '..', 'uploads');
      const uploadsStores = path.join(uploadsBase, 'stores');
      
      // Try different possible locations for the file
      const possiblePaths = [
        // Direct path if it's an absolute path
        filePath,
        // Relative to current working directory
        path.join(process.cwd(), filePath),
        // In the uploads/stores directory
        path.join(uploadsStores, filename),
        // In the uploads directory
        path.join(uploadsBase, filename),
        // In the Backend/uploads/stores directory (for development)
        path.join(process.cwd(), 'Backend', 'uploads', 'stores', filename),
        // In the Backend/uploads directory (for development)
        path.join(process.cwd(), 'Backend', 'uploads', filename)
      ];

      // Add Windows-style paths
      const windowsPaths = possiblePaths.map(p => p.replace(/\\/g, '/'));
      
      // Combine all possible paths and remove duplicates
      const allPaths = [...new Set([...possiblePaths, ...windowsPaths])];

      let deleted = false;
      
      // Try each possible path until we find and delete the file
      for (const currentPath of allPaths) {
        if (!currentPath) continue;
        
        try {
          console.log(`Attempting to delete store ${fileType} at: ${currentPath}`);
          
          // Check if file exists and is accessible
          try {
            await fs.access(currentPath);
            // If we get here, file exists and is accessible
            await deleteFile(currentPath);
            console.log(`Successfully deleted store ${fileType}: ${currentPath}`);
            deleted = true;
            break; // Stop after successful deletion
          } catch (accessError) {
            if (accessError.code === 'ENOENT') {
              // File doesn't exist, try next path
              continue;
            }
            // For other errors, log and continue
            console.error(`Error accessing ${fileType} at ${currentPath}:`, accessError);
          }
        } catch (error) {
          console.error(`Unexpected error while processing ${fileType} at ${currentPath}:`, error);
          // Continue to next path even if there's an error
        }
      }
      
      if (!deleted) {
        console.warn(`Could not find or delete the store ${fileType} at any of the following paths:`, allPaths);
      }
      
      return deleted;
    };

    // Delete all associated files
    try {
      console.log('Starting to delete store files...');
      
      // Delete logo
      if (store.logo) {
        console.log('Deleting logo:', store.logo);
        await deleteStoreFile(store.logo, 'logo');
      } else {
        console.log('No logo to delete');
      }
      
      // Delete national ID card if it exists
      if (store.nationalIdCard) {
        console.log('Deleting national ID card:', store.nationalIdCard);
        await deleteStoreFile(store.nationalIdCard, 'national ID card');
      } else {
        console.log('No national ID card to delete');
      }
      
      // Delete address proof if it exists
      if (store.addressProof) {
        console.log('Deleting address proof:', store.addressProof);
        await deleteStoreFile(store.addressProof, 'address proof');
      } else {
        console.log('No address proof to delete');
      }
      
      // If store has additional images array, delete those too
      if (store.images && Array.isArray(store.images) && store.images.length > 0) {
        console.log(`Deleting ${store.images.length} additional store images...`);
        await Promise.all(
          store.images.map((img, index) => {
            console.log(`Deleting additional image ${index + 1}:`, img);
            return deleteStoreFile(img, `additional image ${index + 1}`);
          })
        );
      } else {
        console.log('No additional images to delete');
      }
    } catch (error) {
      console.error('Error during store file deletion:', error);
      // Don't fail the entire operation if file deletion fails
    }
    
    // Now delete the store from the database using the model's delete method
    const deletedStore = await Seller.delete(id);
    
    if (!deletedStore) {
      return res.status(404).json({
        success: false,
        msg: 'Store not found or could not be deleted'
      });
    }
    
    // Also delete the associated user account if it exists
    try {
      // Try to find and delete by storeManager reference first
      let user = await User.findOneAndDelete({ storeManager: deletedStore._id });
      
      // If not found by reference, try by email as fallback
      if (!user && deletedStore.email) {
        user = await User.findOneAndDelete({ email: deletedStore.email });
      }
      
      if (user) {
        console.log(`Deleted associated user account: ${user.email || user._id}`);
      } else {
        console.log('No associated user account found to delete');
      }
    } catch (userError) {
      console.error('Error deleting associated user account:', userError);
      // Continue with the response even if user deletion fails
    }
    
    res.json({
      success: true,
      msg: 'Store, associated files, and user account (if any) deleted successfully'
    });
  } catch (error) {
    console.error('Error deleting store:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error deleting store'
    });
  }
};

// Search stores
const searchStores = async (req, res) => {
  try {
    const { q: query, page = 1, limit = 10 } = req.query;
    
    if (!query || !query.trim()) {
      return res.status(400).json({
        success: false,
        msg: 'Search query is required'
      });
    }
    
    const result = await Seller.searchSellers(query, {
      page: parseInt(page),
      limit: parseInt(limit)
    });
    
    res.json({
      success: true,
      data: result.items,
      pagination: {
        currentPage: result.currentPage,
        totalPages: result.totalPages,
        totalStores: result.total,
        hasNextPage: result.hasNextPage,
        hasPreviousPage: result.hasPreviousPage
      },
      msg: 'Search completed successfully'
    });
  } catch (error) {
    console.error('Error searching stores:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error searching stores'
    });
  }
};

// Get store statistics
const getStoreStatistics = async (req, res) => {
  try {
    const stats = await Seller.getSellerStatistics();
    
    res.json({
      success: true,
      data: stats,
      msg: 'Statistics retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching store statistics:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching statistics'
    });
  }
};

// Get stores by city
const getStoresByCity = async (req, res) => {
  try {
    const { city } = req.params;
    const stores = await Seller.getSellersByCity(city);
    
    res.json({
      success: true,
      data: stores,
      msg: 'Stores retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching stores by city:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching stores'
    });
  }
};

// Get active stores for dropdown/selection
const getActiveStores = async (req, res) => {
  try {
    const stores = await Seller.find({ status: true })
      .select('name')
      .sort({ name: 1 })
      .lean();
    
    res.json({
      success: true,
      data: stores,
      msg: 'Active stores retrieved successfully'
    });
  } catch (error) {
    console.error('Error fetching active stores:', error);
    res.status(500).json({
      success: false,
      msg: error.message || 'Error fetching active stores'
    });
  }
};

// Get nearby stores by coordinates
// @desc    Get stores available for assignment to a pharmacist (not already assigned)
// @route   GET /api/v1/pharmacist/:id/available-stores
// @access  Private (Admin)
const getAvailableStoresForPharmacist = async (req, res) => {
  try {
    const { id: pharmacistId } = req.params;
    
    // This is a placeholder - implement your actual logic to get available stores
    // For example:
    // 1. Get the pharmacist's currently assigned stores
    // 2. Find all active stores that are not in the assigned stores list
    // const pharmacist = await User.findById(pharmacistId);
    // const assignedStoreIds = pharmacist.assignedStores || [];
    // const availableStores = await Store.find({
    //   _id: { $nin: assignedStoreIds },
    //   status: 'active'
    // }).select('name address city state');
    
    res.status(200).json({
      success: true,
      count: 0,
      data: []
    });
  } catch (error) {
    console.error('Error getting available stores for pharmacist:', error);
    res.status(500).json({
      success: false,
      message: 'Error getting available stores',
      error: error.message,
    });
  }
};

// @desc    Get nearby stores by coordinates
// @route   GET /api/v1/stores/nearby
// @access  Public
const getNearbyStores = async (req, res) => {
  try {
    const { lat, lng, distance = 5000, limit = 10 } = req.query;
    console.log('Received request with params:', { lat, lng, distance, limit });

    if (!lat || !lng) {
      return res.status(400).json({
        success: false,
        msg: 'Please provide latitude and longitude parameters'
      });
    }

    const longitude = parseFloat(lng);
    const latitude = parseFloat(lat);
    const maxDistance = parseInt(distance);
    const resultLimit = Math.min(parseInt(limit) || 10, 100); // Limit max results to 100

    // Validate coordinates
    if (isNaN(longitude) || isNaN(latitude) || 
        longitude < -180 || longitude > 180 || 
        latitude < -90 || latitude > 90) {
      return res.status(400).json({
        success: false,
        msg: 'Invalid coordinates provided. Longitude must be between -180 and 180, and latitude between -90 and 90.'
      });
    }

    // Validate max distance (in meters)
    if (isNaN(maxDistance) || maxDistance <= 0 || maxDistance > 100000) {
      return res.status(400).json({
        success: false,
        msg: 'Invalid distance. Must be a positive number up to 100,000 meters (100km).'
      });
    }

    console.log('Searching for stores near:', { longitude, latitude, maxDistance });

    // Helper function to calculate distance using Haversine formula
    const calculateDistance = (lat1, lon1, lat2, lon2) => {
      const R = 6371000; // Earth's radius in meters
      const dLat = (lat2 - lat1) * Math.PI / 180;
      const dLon = (lon2 - lon1) * 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(dLon/2) * Math.sin(dLon/2);
      const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      return R * c; // Distance in meters
    };

    // Helper function to process and filter stores
    const processStores = (stores) => {
      return stores
        .map(store => {
          try {
            if (!store?.store?.location?.coordinates || 
                store.store.location.coordinates.length !== 2) {
              return null;
            }

            const [storeLng, storeLat] = store.store.location.coordinates.map(Number);
            const storeDeliveryRadius = parseFloat(store.store.deliveryRadius) || 0;

            if (isNaN(storeLng) || isNaN(storeLat) || storeLng === 0 || storeLat === 0) {
              return null;
            }

            const distance = calculateDistance(latitude, longitude, storeLat, storeLng);
            const isWithinDeliveryRadius = distance <= (storeDeliveryRadius || maxDistance);

            return {
              ...store,
              distance: Math.round(distance * 100) / 100, // Round to 2 decimal places
              isWithinDeliveryRadius
            };
          } catch (error) {
            console.error('Error processing store:', store?._id, error);
            return null;
          }
        })
        .filter(store => store !== null && store.isWithinDeliveryRadius)
        .sort((a, b) => a.distance - b.distance)
        .slice(0, resultLimit);
    };

    // Try using MongoDB's geospatial query if index exists
    try {
      // Check if geospatial index exists
      const indexes = await Seller.collection.indexes();
      const hasGeoIndex = indexes.some(index => {
        const key = index.key;
        return key && key['store.location'] === '2dsphere';
      });

      if (hasGeoIndex) {
        try {
          // First, get the nearby stores using $geoNear (must be first stage)
          const stores = await Seller.aggregate([{
            $geoNear: {
              near: {
                type: 'Point',
                coordinates: [longitude, latitude]
              },
              query: {
                status: 'active',
                'store.isActive': true,
                'store.location': { 
                  $exists: true,
                  $ne: null,
                  $type: 'object'
                }
              },
              distanceField: 'distance',
              maxDistance: maxDistance,
              spherical: true,
              key: 'store.location',
              distanceMultiplier: 1 // Return distance in meters
            }
          }, {
            // Filter by delivery radius
            $addFields: {
              maxAllowedDistance: {
                $ifNull: ['$store.deliveryRadius', maxDistance]
              }
            }
          }, {
            $match: {
              $expr: {
                $lte: ['$distance', '$maxAllowedDistance']
              }
            }
          }, {
            $sort: { distance: 1 }
          }, {
            $limit: resultLimit
          }, {
            $project: {
              _id: 1,
              name: 1,
              email: 1,
              mobile: 1,
              store: 1,
              status: 1,
              distance: { $round: ['$distance', 2] }
            }
          }]);

          if (stores && stores.length > 0) {
            console.log(`Found ${stores.length} stores using geospatial query`);
            
            // Format stores to match frontend expectations
            const formattedStores = stores.map(store => ({
              ...store,
              name: store.name || store.store?.storeName || 'Unnamed Store',
              storeName: store.store?.storeName,
              distanceKm: Math.round((store.distance / 1000) * 10) / 10, // Convert to km with 1 decimal
              store: {
                ...store.store,
                _id: store._id,
                name: store.name || store.store?.storeName || 'Unnamed Store',
                storeName: store.store?.storeName,
                deliveryRadius: store.store?.deliveryRadius || 5000,
                location: {
                  ...store.store?.location,
                  coordinates: store.store?.location?.coordinates || [0, 0],
                  address: store.store?.location?.address || '',
                  city: store.store?.location?.city || '',
                  state: store.store?.location?.state || '',
                  country: store.store?.location?.country || '',
                  pincode: store.store?.location?.pincode || '',
                  formattedAddress: store.store?.location?.formattedAddress || 
                    [
                      store.store?.location?.address,
                      store.store?.location?.city,
                      store.store?.location?.state,
                      store.store?.location?.country,
                      store.store?.location?.pincode
                    ].filter(Boolean).join(', ')
                }
              }
            }));

            return res.json({
              success: true,
              count: formattedStores.length,
              data: formattedStores,
              _debug: {
                searchMethod: 'geospatial',
                searchLocation: { lat: latitude, lng: longitude },
                maxDistance: maxDistance
              }
            });
          }
        } catch (geoError) {
          console.error('Error in geospatial query:', geoError);
          // Fall through to manual calculation
        }
      }
    } catch (geoError) {
      console.error('Error before geospatial query, falling back to manual calculation:', geoError);
    }

    // Fall back to manual calculation if geospatial query fails or returns no results
    console.log('Using manual store calculation method');
    
    try {
      // First, try to find any active stores to verify the query
      const activeStoreCount = await Seller.countDocuments({ status: 'active' });
      console.log(`Total active stores in database: ${activeStoreCount}`);
      
      // Get all stores with minimal filtering first
      const allStores = await Seller.find({})
        .select('name email mobile store.location store.deliveryRadius store.storeName status store.isActive')
        .lean();
        
      console.log(`Fetched ${allStores.length} stores from database`);

      console.log(`Found ${allStores.length} stores for manual distance calculation`);
      
      // Log all stores for debugging
      console.log('All stores found:', JSON.stringify(allStores.map(store => ({
        _id: store._id,
        storeName: store.store?.storeName,
        coordinates: store.store?.location?.coordinates,
        isActive: store.status === 'active' && store.store?.isActive === true
      })), null, 2));
      
      // Filter stores with valid coordinates first
      const storesWithValidCoords = allStores.filter(store => {
        const coords = store?.store?.location?.coordinates;
        const isStoreActive = store.status === 'Active' && store.store?.isActive === true;
        
        const isValid = Array.isArray(coords) && 
               coords.length === 2 && 
               typeof coords[0] === 'number' && 
               typeof coords[1] === 'number' &&
               coords[0] !== 0 && 
               coords[1] !== 0 &&
               isStoreActive;
        
        if (!isValid) {
          console.log('Store filtered out:', {
            _id: store._id,
            status: store.status,
            storeIsActive: store.store?.isActive,
            rootIsActive: store.isActive,
            coordinates: coords,
            reason: store.status !== 'Active' ? `Status is ${store.status} (expected 'Active')` :
                    store.store?.isActive !== true ? 'store.isActive is not true' :
                    !Array.isArray(coords) ? 'Coordinates not an array' : 
                    coords.length !== 2 ? 'Coordinates not 2 elements' :
                    typeof coords[0] !== 'number' || typeof coords[1] !== 'number' ? 'Non-number coordinates' :
                    coords[0] === 0 || coords[1] === 0 ? 'Zero coordinates' : 'Unknown'
          });
        }
        
        return isValid;
      });
      
      console.log(`Found ${storesWithValidCoords.length} stores with valid coordinates`);
      
      // Process stores with consistent distance calculation
      console.log('Searching for stores near:', { latitude, longitude, maxDistance });
      const nearbyStores = storesWithValidCoords
        .map(store => {
          try {
            const [storeLng, storeLat] = store.store.location.coordinates;
            
            // Skip if coordinates are invalid
            if (!storeLat || !storeLng) return null;
            
            // Calculate distance in meters using Haversine formula
            const R = 6371000; // Earth's radius in meters
            const lat1 = latitude * Math.PI / 180;
            const lat2 = storeLat * Math.PI / 180;
            const deltaLat = (storeLat - latitude) * Math.PI / 180;
            const deltaLon = (storeLng - longitude) * Math.PI / 180;
            
            const a = 
              Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
              Math.cos(lat1) * Math.cos(lat2) * 
              Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
            const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            const distance = R * c;
            
            console.log('Store distance calculation:', {
              storeId: store._id,
              storeCoords: [storeLng, storeLat],
              searchCoords: [longitude, latitude],
              distance,
              storeDeliveryRadius: store.store.deliveryRadius || maxDistance,
              isWithinRadius: distance <= (store.store.deliveryRadius || maxDistance)
            });
            
            // Get store's delivery radius or use default
            const storeDeliveryRadius = store.store.deliveryRadius || maxDistance;
            const isWithinDeliveryRadius = distance <= storeDeliveryRadius;
            
            return {
              ...store,
              distance: Math.round(distance * 100) / 100, // Round to 2 decimal places
              isWithinDeliveryRadius
            };
          } catch (error) {
            console.error('Error processing store:', store._id, error);
            return null;
          }
        })
        .filter(store => store !== null && store.isWithinDeliveryRadius)
        .sort((a, b) => a.distance - b.distance)
        .slice(0, resultLimit);
      
      console.log(`Found ${nearbyStores.length} stores within ${maxDistance}m using manual calculation`);
      
      // Format stores to match frontend expectations
      const formattedStores = nearbyStores.map(store => ({
        _id: store._id,
        name: store.name || store.store?.storeName || 'Unnamed Store',
        storeName: store.store?.storeName,
        distanceKm: Math.round((store.distance / 1000) * 10) / 10, // Convert to km with 1 decimal
        store: {
          ...store.store,
          _id: store._id,
          name: store.name || store.store?.storeName || 'Unnamed Store',
          storeName: store.store?.storeName,
          deliveryRadius: store.store?.deliveryRadius || 5000,
          location: {
            ...store.store?.location,
            coordinates: store.store?.location?.coordinates || [0, 0],
            address: store.store?.location?.address || '',
            city: store.store?.location?.city || '',
            state: store.store?.location?.state || '',
            country: store.store?.location?.country || '',
            pincode: store.store?.location?.pincode || '',
            formattedAddress: store.store?.location?.formattedAddress || 
              [
                store.store?.location?.address,
                store.store?.location?.city,
                store.store?.location?.state,
                store.store?.location?.country,
                store.store?.location?.pincode
              ].filter(Boolean).join(', ')
          }
        }
      }));

      return res.json({
        success: true,
        count: formattedStores.length,
        data: formattedStores,
        message: formattedStores.length === 0 ? 'No stores found within the specified distance.' : undefined,
        _debug: {
          searchMethod: 'manual',
          totalStores: allStores.length,
          storesWithinDistance: formattedStores.length,
          searchLocation: { lat: latitude, lng: longitude },
          maxDistance: maxDistance
        }
      });
    } catch (error) {
      console.error('Error in manual store calculation:', error);
      return res.status(500).json({
        success: false,
        msg: 'Error finding nearby stores',
        error: error.message
      });
    }
  } catch (error) {
    console.error('Error in getNearbyStores:', error);
    res.status(500).json({
      success: false,
      msg: 'Error finding nearby stores',
      error: error.message,
      stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
    });
  }
};

module.exports = {
  getAllStores,
  getStoreById,
  createStore,
  updateStore,
  toggleStoreStatus,
  deleteStore,
  searchStores,
  getStoreStatistics,
  getStoresByCity,
  getActiveStores,
  getNearbyStores,
  getAvailableStoresForPharmacist
};