# Road Distance Implementation for Feasibility Checks

## Summary

Successfully updated the feasibility check system to use **road distance** instead of straight-line distance when calculating how far a customer location is from KMZ coverage polygon edges.

## What Changed

### Before
- Used straight-line distance (Haversine formula) converted from degrees to meters
- Simple calculation: `degrees × 111000 = meters`
- Fast but inaccurate for real-world scenarios

### After
- Uses Google Maps Distance Matrix API to calculate actual road distance
- Falls back to estimated road distance (straight-line × 1.4) if API unavailable
- More accurate representation of installation feasibility

## Implementation Details

### Files Modified

1. **`afinet-portal-backend/app/Services/KmzCoverageService.php`**
   - Added `GoogleMapsService` dependency injection
   - Created `findNearestPointOnPolygon()` method to find exact coordinates of nearest point on polygon edge
   - Created `findNearestPointOnLineSegment()` helper method
   - Updated `checkCoverage()` to call Google Maps API for road distance calculation
   - Added fallback mechanism with 1.4x multiplier for estimated road distance

### How It Works

1. **Inside Coverage Polygon** → High Feasibility
   - No distance calculation needed
   - Direct fiber connection available

2. **Outside Coverage Polygon** → Calculate Road Distance
   - Find nearest point on any polygon edge (geometric calculation)
   - Call Google Maps Distance Matrix API with:
     - Origin: Customer location
     - Destination: Nearest point on polygon edge
   - Get actual road distance in meters
   - If API fails: Use straight-line distance × 1.4 as estimate

3. **Apply Thresholds**
   - **Internet packages**: 100m (high), 500m (medium)
   - **Networking packages**: 50m (high), 200m (medium)

### Response Format

```php
[
    'feasibility' => 'high|medium|low',
    'zone' => 'harare|bulawayo',
    'distance_to_coverage' => 111, // meters (road distance)
    'distance_method' => 'road|estimated', // indicates if Google Maps API was used
    'message' => 'Location is near harare coverage area...',
]
```

## Testing

### Test Files Created

1. **`info/test-road-distance.php`**
   - Tests Google Maps Distance Matrix API directly
   - Verifies API key configuration
   - Shows road vs straight-line distance ratios

2. **`info/test-single-location.php`**
   - Tests single location feasibility check
   - Shows detailed output including distance method

3. **`info/test-kmz-coverage.php`** (updated)
   - Comprehensive coverage testing
   - Tests multiple locations in Harare and Bulawayo
   - Now includes `distance_method` in output

4. **`info/test-service-type-thresholds.php`**
   - Tests internet vs networking package thresholds
   - Verifies 100m/500m for internet, 50m/200m for networking
   - Tests edge cases and inside-polygon scenarios

### Test Results

```bash
# Test Google Maps API
php info/test-road-distance.php

# Results:
# Harare CBD to Avondale: 4278m road (1.31x straight-line)
# Bulawayo CBD to Suburbs: 3373m road (1.19x straight-line)
# ✅ API working correctly

# Test single location
php info/test-single-location.php

# Results:
# Harare CBD: 111m road distance to coverage
# Method: road (Google Maps API used)
# Feasibility: medium (within 500m threshold)
# ✅ Road distance calculation working

# Test service type thresholds
php info/test-service-type-thresholds.php

# Results:
# Location 111m from coverage:
#   - Internet package (100m threshold): MEDIUM ✅
#   - Networking package (50m threshold): MEDIUM ✅
# Inside coverage polygon: HIGH ✅
# ✅ Thresholds working correctly
```

## Benefits

1. **More Accurate Feasibility**
   - Road distance reflects actual installation requirements
   - Accounts for roads, terrain, and infrastructure

2. **Better Customer Experience**
   - More realistic installation estimates
   - Fewer surprises during site surveys

3. **Improved Business Logic**
   - Extension costs based on actual road distance
   - Better resource planning for installations

4. **Fallback Mechanism**
   - System continues working if Google Maps API unavailable
   - Uses 1.4x multiplier (typical road vs straight-line ratio)
   - Logs warnings for monitoring

## Configuration

### Required Environment Variables

```env
GOOGLE_MAPS_API_KEY=your_api_key_here
```

### Google Cloud Console Setup

1. Enable Distance Matrix API
2. Set up billing (required for API usage)
3. Configure API key restrictions (optional but recommended)

### Caching

- Road distance results are cached for 30 days
- Cache key format: `road_distance_{lat}_{lon}_{destLat}_{destLon}`
- Reduces API calls and improves performance

## Thresholds

The system uses different thresholds based on service type, determined by the questionnaire answers.

### Internet Packages (Shared Broadband, Dedicated Burst, etc.)
- **High Feasibility**: 0-100m road distance
- **Medium Feasibility**: 101-500m road distance
- **Low Feasibility**: >500m road distance

### Networking Packages (Metro-VPN, etc.)
- **High Feasibility**: 0-50m road distance
- **Medium Feasibility**: 51-200m road distance
- **Low Feasibility**: >200m road distance

### Inside Coverage Polygon
- **Always High Feasibility** regardless of thresholds
- No distance calculation needed
- Direct fiber connection available

### Threshold Logic
```php
// In FeasibilityController::calculateFeasibility()
$highFeasibilityThreshold = ($serviceType === 'internet') ? 100 : 50;
$mediumFeasibilityThreshold = ($serviceType === 'internet') ? 500 : 200;

// Passed to KmzCoverageService::checkCoverage()
$kmzCoverage = $this->kmzCoverageService->checkCoverage(
    $latitude, 
    $longitude, 
    $highFeasibilityThreshold,    // 100m or 50m
    $mediumFeasibilityThreshold   // 500m or 200m
);
```

## API Usage Considerations

### Cost
- Google Maps Distance Matrix API charges per request
- Caching reduces costs significantly
- Fallback mechanism prevents failures

### Rate Limits
- Standard quota: 100 elements per second
- Daily quota: Check Google Cloud Console
- Caching helps stay within limits

### Error Handling
- API failures logged with context
- Automatic fallback to estimated distance
- System remains functional during outages

## Next Steps

1. ✅ Implementation complete
2. ✅ Testing complete
3. ⏳ Monitor API usage and costs
4. ⏳ Adjust thresholds based on real-world data
5. ⏳ Consider batch processing for multiple locations

## Related Files

- `afinet-portal-backend/app/Services/KmzCoverageService.php`
- `afinet-portal-backend/app/Services/GoogleMapsService.php`
- `afinet-portal-backend/app/Http/Controllers/API/FeasibilityController.php`
- `info/test-road-distance.php`
- `info/test-single-location.php`
- `info/test-kmz-coverage.php`
