# Phase 3: API & Backend Implementation

## Overview
Update API contracts, implement enhanced backend services, create new endpoints, and build comprehensive test suite for the enhanced fuel logs system.

## Prerequisites
- ✅ Phase 1 completed (database schema and core types)
- ✅ Phase 2 completed (enhanced business logic services)
- All business logic services tested and functional

## Updated Service Layer

### Enhanced Fuel Logs Service

**File**: `backend/src/features/fuel-logs/domain/fuel-logs.service.ts` (Updated)

```typescript
import { FuelLogsRepository } from '../data/fuel-logs.repository';
import { 
  FuelLog, CreateFuelLogRequest, UpdateFuelLogRequest, 
  FuelLogResponse, FuelStats, UnitSystem 
} from './fuel-logs.types';
import { EnhancedValidationService } from './enhanced-validation.service';
import { EfficiencyCalculationService } from './efficiency-calculation.service';
import { UnitConversionService } from './unit-conversion.service';
import { UserSettingsService } from '../external/user-settings.service';
import { logger } from '../../../core/logging/logger';
import { cacheService } from '../../../core/config/redis';
import pool from '../../../core/config/database';

export class FuelLogsService {
  private readonly cachePrefix = 'fuel-logs';
  private readonly cacheTTL = 300; // 5 minutes
  
  constructor(private repository: FuelLogsRepository) {}
  
  async createFuelLog(data: CreateFuelLogRequest, userId: string): Promise<FuelLogResponse> {
    logger.info('Creating enhanced fuel log', { 
      userId, 
      vehicleId: data.vehicleId,
      fuelType: data.fuelType,
      hasTrip: !!data.tripDistance,
      hasOdometer: !!data.odometerReading
    });
    
    // Get user settings for unit system
    const userSettings = await UserSettingsService.getUserSettings(userId);
    
    // Enhanced validation
    const validation = EnhancedValidationService.validateFuelLogData(data, userSettings.unitSystem);
    if (!validation.isValid) {
      throw new ValidationError(`Invalid fuel log data: ${validation.errors.join(', ')}`);
    }
    
    // Log warnings
    if (validation.warnings.length > 0) {
      logger.warn('Fuel log validation warnings', { warnings: validation.warnings });
    }
    
    // Verify vehicle ownership
    const vehicleCheck = await pool.query(
      'SELECT id FROM vehicles WHERE id = $1 AND user_id = $2',
      [data.vehicleId, userId]
    );
    
    if (vehicleCheck.rows.length === 0) {
      throw new Error('Vehicle not found or unauthorized');
    }
    
    // Calculate total cost
    const totalCost = data.fuelUnits * data.costPerUnit;
    
    // Get previous log for efficiency calculation
    const previousLog = data.odometerReading ? 
      await this.repository.getPreviousLogByOdometer(data.vehicleId, data.odometerReading) :
      await this.repository.getLatestLogForVehicle(data.vehicleId);
    
    // Calculate efficiency
    const efficiencyResult = EfficiencyCalculationService.calculateEfficiency(
      { ...data, totalCost },
      previousLog,
      userSettings.unitSystem
    );
    
    // Prepare fuel log data
    const fuelLogData = {
      ...data,
      userId,
      dateTime: new Date(data.dateTime),
      totalCost,
      mpg: efficiencyResult?.value || null,
      efficiencyCalculationMethod: efficiencyResult?.calculationMethod || null
    };
    
    // Create fuel log
    const fuelLog = await this.repository.create(fuelLogData);
    
    // Update vehicle odometer if provided
    if (data.odometerReading) {
      await pool.query(
        'UPDATE vehicles SET odometer_reading = $1 WHERE id = $2 AND (odometer_reading IS NULL OR odometer_reading < $1)',
        [data.odometerReading, data.vehicleId]
      );
    }
    
    // Invalidate caches
    await this.invalidateCaches(userId, data.vehicleId);
    
    return this.toResponse(fuelLog, userSettings.unitSystem);
  }
  
  async getFuelLogsByVehicle(
    vehicleId: string, 
    userId: string,
    options?: { unitSystem?: UnitSystem }
  ): Promise<FuelLogResponse[]> {
    
    // Verify vehicle ownership
    const vehicleCheck = await pool.query(
      'SELECT id FROM vehicles WHERE id = $1 AND user_id = $2',
      [vehicleId, userId]
    );
    
    if (vehicleCheck.rows.length === 0) {
      throw new Error('Vehicle not found or unauthorized');
    }
    
    // Get user settings
    const userSettings = await UserSettingsService.getUserSettings(userId);
    const unitSystem = options?.unitSystem || userSettings.unitSystem;
    
    const cacheKey = `${this.cachePrefix}:vehicle:${vehicleId}:${unitSystem}`;
    
    // Check cache
    const cached = await cacheService.get<FuelLogResponse[]>(cacheKey);
    if (cached) {
      return cached;
    }
    
    // Get from database
    const logs = await this.repository.findByVehicleId(vehicleId);
    const response = logs.map((log: FuelLog) => this.toResponse(log, unitSystem));
    
    // Cache result
    await cacheService.set(cacheKey, response, this.cacheTTL);
    
    return response;
  }
  
  async getEnhancedVehicleStats(vehicleId: string, userId: string): Promise<EnhancedFuelStats> {
    // Verify vehicle ownership
    const vehicleCheck = await pool.query(
      'SELECT id FROM vehicles WHERE id = $1 AND user_id = $2',
      [vehicleId, userId]
    );
    
    if (vehicleCheck.rows.length === 0) {
      throw new Error('Vehicle not found or unauthorized');
    }
    
    const userSettings = await UserSettingsService.getUserSettings(userId);
    const logs = await this.repository.findByVehicleId(vehicleId);
    
    if (logs.length === 0) {
      return this.getEmptyStats(userSettings.unitSystem);
    }
    
    // Calculate comprehensive stats
    const totalFuelUnits = logs.reduce((sum, log) => sum + log.fuelUnits, 0);
    const totalCost = logs.reduce((sum, log) => sum + log.totalCost, 0);
    const averageCostPerUnit = totalCost / totalFuelUnits;
    
    const totalDistance = EfficiencyCalculationService.calculateTotalDistance(logs, userSettings.unitSystem);
    const averageEfficiency = EfficiencyCalculationService.calculateAverageEfficiency(logs, userSettings.unitSystem);
    
    // Group by fuel type
    const fuelTypeBreakdown = this.calculateFuelTypeBreakdown(logs, userSettings.unitSystem);
    
    // Calculate trends (last 30 days vs previous 30 days)
    const trends = this.calculateEfficiencyTrends(logs, userSettings.unitSystem);
    
    const unitLabels = UnitConversionService.getUnitLabels(userSettings.unitSystem);
    
    return {
      logCount: logs.length,
      totalFuelUnits,
      totalCost,
      averageCostPerUnit,
      totalDistance,
      averageEfficiency: averageEfficiency?.value || 0,
      fuelTypeBreakdown,
      trends,
      unitLabels,
      dateRange: {
        earliest: logs[logs.length - 1]?.dateTime,
        latest: logs[0]?.dateTime
      }
    };
  }
  
  private toResponse(log: FuelLog, unitSystem: UnitSystem): FuelLogResponse {
    const unitLabels = UnitConversionService.getUnitLabels(unitSystem);
    
    // Convert efficiency to user's unit system if needed
    let displayEfficiency = log.mpg;
    if (log.mpg && unitSystem === UnitSystem.METRIC) {
      displayEfficiency = UnitConversionService.convertEfficiency(
        log.mpg,
        UnitSystem.IMPERIAL, // Assuming stored as MPG
        UnitSystem.METRIC
      );
    }
    
    return {
      id: log.id,
      userId: log.userId,
      vehicleId: log.vehicleId,
      dateTime: log.dateTime.toISOString(),
      
      // Distance information
      odometerReading: log.odometerReading,
      tripDistance: log.tripDistance,
      
      // Fuel information
      fuelType: log.fuelType,
      fuelGrade: log.fuelGrade,
      fuelUnits: log.fuelUnits,
      costPerUnit: log.costPerUnit,
      totalCost: log.totalCost,
      
      // Location
      locationData: log.locationData,
      
      // Calculated fields
      efficiency: displayEfficiency,
      efficiencyLabel: unitLabels.efficiencyUnits,
      
      // Metadata
      notes: log.notes,
      createdAt: log.createdAt.toISOString(),
      updatedAt: log.updatedAt.toISOString(),
      
      // Legacy fields (for backward compatibility)
      date: log.dateTime.toISOString().split('T')[0],
      odometer: log.odometerReading,
      gallons: log.fuelUnits, // May need conversion
      pricePerGallon: log.costPerUnit, // May need conversion
      mpg: log.mpg
    };
  }
}
```

### New API Endpoints

#### Fuel Grade Endpoint

**File**: `backend/src/features/fuel-logs/api/fuel-grade.controller.ts`

```typescript
import { FastifyRequest, FastifyReply } from 'fastify';
import { FuelGradeService } from '../domain/fuel-grade.service';
import { FuelType } from '../domain/fuel-logs.types';
import { logger } from '../../../core/logging/logger';

export class FuelGradeController {
  
  async getFuelGrades(
    request: FastifyRequest<{ Params: { fuelType: FuelType } }>, 
    reply: FastifyReply
  ) {
    try {
      const { fuelType } = request.params;
      
      // Validate fuel type
      if (!Object.values(FuelType).includes(fuelType)) {
        return reply.code(400).send({
          error: 'Bad Request',
          message: `Invalid fuel type: ${fuelType}`
        });
      }
      
      const grades = FuelGradeService.getFuelGradeOptions(fuelType);
      
      return reply.code(200).send({
        fuelType,
        grades
      });
    } catch (error: any) {
      logger.error('Error getting fuel grades', { error, fuelType: request.params.fuelType });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to get fuel grades'
      });
    }
  }
  
  async getAllFuelTypes(request: FastifyRequest, reply: FastifyReply) {
    try {
      const fuelTypes = Object.values(FuelType).map(type => ({
        value: type,
        label: type.charAt(0).toUpperCase() + type.slice(1),
        grades: FuelGradeService.getFuelGradeOptions(type)
      }));
      
      return reply.code(200).send({ fuelTypes });
    } catch (error: any) {
      logger.error('Error getting fuel types', { error });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to get fuel types'
      });
    }
  }
}
```

### Enhanced Routes

**File**: `backend/src/features/fuel-logs/api/fuel-logs.routes.ts` (Updated)

```typescript
import { FastifyInstance, FastifyPluginOptions } from 'fastify';
import { FuelLogsController } from './fuel-logs.controller';
import { FuelGradeController } from './fuel-grade.controller';
import { 
  createFuelLogSchema, 
  updateFuelLogSchema,
  fuelLogParamsSchema,
  vehicleParamsSchema,
  fuelTypeParamsSchema
} from './fuel-logs.validators';

export async function fuelLogsRoutes(
  fastify: FastifyInstance,
  options: FastifyPluginOptions
) {
  const fuelLogsController = new FuelLogsController();
  const fuelGradeController = new FuelGradeController();
  
  // Existing fuel log CRUD endpoints (enhanced)
  fastify.post('/fuel-logs', {
    preHandler: [fastify.authenticate],
    schema: createFuelLogSchema
  }, fuelLogsController.createFuelLog.bind(fuelLogsController));
  
  fastify.get('/fuel-logs', {
    preHandler: [fastify.authenticate]
  }, fuelLogsController.getUserFuelLogs.bind(fuelLogsController));
  
  fastify.get('/fuel-logs/:id', {
    preHandler: [fastify.authenticate],
    schema: { params: fuelLogParamsSchema }
  }, fuelLogsController.getFuelLog.bind(fuelLogsController));
  
  fastify.put('/fuel-logs/:id', {
    preHandler: [fastify.authenticate],
    schema: {
      params: fuelLogParamsSchema,
      body: updateFuelLogSchema
    }
  }, fuelLogsController.updateFuelLog.bind(fuelLogsController));
  
  fastify.delete('/fuel-logs/:id', {
    preHandler: [fastify.authenticate],
    schema: { params: fuelLogParamsSchema }
  }, fuelLogsController.deleteFuelLog.bind(fuelLogsController));
  
  // Vehicle-specific endpoints (enhanced)
  fastify.get('/fuel-logs/vehicle/:vehicleId', {
    preHandler: [fastify.authenticate],
    schema: { params: vehicleParamsSchema }
  }, fuelLogsController.getFuelLogsByVehicle.bind(fuelLogsController));
  
  fastify.get('/fuel-logs/vehicle/:vehicleId/stats', {
    preHandler: [fastify.authenticate],
    schema: { params: vehicleParamsSchema }
  }, fuelLogsController.getEnhancedVehicleStats.bind(fuelLogsController));
  
  // NEW: Fuel type/grade endpoints
  fastify.get('/fuel-logs/fuel-types', {
    preHandler: [fastify.authenticate]
  }, fuelGradeController.getAllFuelTypes.bind(fuelGradeController));
  
  fastify.get('/fuel-logs/fuel-grades/:fuelType', {
    preHandler: [fastify.authenticate],
    schema: { params: fuelTypeParamsSchema }
  }, fuelGradeController.getFuelGrades.bind(fuelGradeController));
}

export function registerFuelLogsRoutes(fastify: FastifyInstance) {
  return fastify.register(fuelLogsRoutes, { prefix: '/api' });
}
```

### Enhanced Validation Schemas

**File**: `backend/src/features/fuel-logs/api/fuel-logs.validators.ts` (Updated)

```typescript
import { Type } from '@sinclair/typebox';
import { FuelType } from '../domain/fuel-logs.types';

export const createFuelLogSchema = {
  body: Type.Object({
    vehicleId: Type.String({ format: 'uuid' }),
    dateTime: Type.String({ format: 'date-time' }),
    
    // Distance (one required)
    odometerReading: Type.Optional(Type.Number({ minimum: 0 })),
    tripDistance: Type.Optional(Type.Number({ minimum: 0 })),
    
    // Fuel system
    fuelType: Type.Enum(FuelType),
    fuelGrade: Type.Optional(Type.String()),
    fuelUnits: Type.Number({ minimum: 0.01 }),
    costPerUnit: Type.Number({ minimum: 0.01 }),
    
    // Location (optional)
    locationData: Type.Optional(Type.Object({
      address: Type.Optional(Type.String()),
      coordinates: Type.Optional(Type.Object({
        latitude: Type.Number({ minimum: -90, maximum: 90 }),
        longitude: Type.Number({ minimum: -180, maximum: 180 })
      })),
      googlePlaceId: Type.Optional(Type.String()),
      stationName: Type.Optional(Type.String())
    })),
    
    notes: Type.Optional(Type.String({ maxLength: 500 }))
  }),
  response: {
    201: Type.Object({
      id: Type.String({ format: 'uuid' }),
      userId: Type.String(),
      vehicleId: Type.String({ format: 'uuid' }),
      dateTime: Type.String({ format: 'date-time' }),
      odometerReading: Type.Optional(Type.Number()),
      tripDistance: Type.Optional(Type.Number()),
      fuelType: Type.Enum(FuelType),
      fuelGrade: Type.Optional(Type.String()),
      fuelUnits: Type.Number(),
      costPerUnit: Type.Number(),
      totalCost: Type.Number(),
      efficiency: Type.Optional(Type.Number()),
      efficiencyLabel: Type.String(),
      createdAt: Type.String({ format: 'date-time' }),
      updatedAt: Type.String({ format: 'date-time' })
    })
  }
};

export const updateFuelLogSchema = {
  body: Type.Partial(Type.Object({
    dateTime: Type.String({ format: 'date-time' }),
    odometerReading: Type.Number({ minimum: 0 }),
    tripDistance: Type.Number({ minimum: 0 }),
    fuelType: Type.Enum(FuelType),
    fuelGrade: Type.String(),
    fuelUnits: Type.Number({ minimum: 0.01 }),
    costPerUnit: Type.Number({ minimum: 0.01 }),
    locationData: Type.Object({
      address: Type.Optional(Type.String()),
      coordinates: Type.Optional(Type.Object({
        latitude: Type.Number({ minimum: -90, maximum: 90 }),
        longitude: Type.Number({ minimum: -180, maximum: 180 })
      })),
      googlePlaceId: Type.Optional(Type.String()),
      stationName: Type.Optional(Type.String())
    }),
    notes: Type.String({ maxLength: 500 })
  }))
};

export const fuelLogParamsSchema = Type.Object({
  id: Type.String({ format: 'uuid' })
});

export const vehicleParamsSchema = Type.Object({
  vehicleId: Type.String({ format: 'uuid' })
});

export const fuelTypeParamsSchema = Type.Object({
  fuelType: Type.Enum(FuelType)
});
```

## Repository Layer Updates

### Enhanced Repository

**File**: `backend/src/features/fuel-logs/data/fuel-logs.repository.ts` (Updated)

```typescript
import { Pool } from 'pg';
import { FuelLog, CreateFuelLogData } from '../domain/fuel-logs.types';

export interface CreateFuelLogData {
  userId: string;
  vehicleId: string;
  dateTime: Date;
  odometerReading?: number;
  tripDistance?: number;
  fuelType: string;
  fuelGrade?: string;
  fuelUnits: number;
  costPerUnit: number;
  totalCost: number;
  locationData?: any;
  notes?: string;
  mpg?: number;
  efficiencyCalculationMethod?: string;
}

export class FuelLogsRepository {
  constructor(private pool: Pool) {}
  
  async create(data: CreateFuelLogData): Promise<FuelLog> {
    const query = `
      INSERT INTO fuel_logs (
        user_id, vehicle_id, date_time, odometer_reading, trip_distance,
        fuel_type, fuel_grade, fuel_units, cost_per_unit, total_cost,
        location_data, notes, mpg, efficiency_calculation_method,
        created_at, updated_at
      ) VALUES (
        $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, NOW(), NOW()
      ) RETURNING *
    `;
    
    const values = [
      data.userId,
      data.vehicleId,
      data.dateTime,
      data.odometerReading || null,
      data.tripDistance || null,
      data.fuelType,
      data.fuelGrade || null,
      data.fuelUnits,
      data.costPerUnit,
      data.totalCost,
      data.locationData ? JSON.stringify(data.locationData) : null,
      data.notes || null,
      data.mpg || null,
      data.efficiencyCalculationMethod || null
    ];
    
    const result = await this.pool.query(query, values);
    return this.mapRowToFuelLog(result.rows[0]);
  }
  
  async getPreviousLogByOdometer(vehicleId: string, currentOdometer: number): Promise<FuelLog | null> {
    const query = `
      SELECT * FROM fuel_logs 
      WHERE vehicle_id = $1 
        AND odometer_reading IS NOT NULL 
        AND odometer_reading < $2
      ORDER BY odometer_reading DESC, date_time DESC
      LIMIT 1
    `;
    
    const result = await this.pool.query(query, [vehicleId, currentOdometer]);
    return result.rows.length > 0 ? this.mapRowToFuelLog(result.rows[0]) : null;
  }
  
  async getLatestLogForVehicle(vehicleId: string): Promise<FuelLog | null> {
    const query = `
      SELECT * FROM fuel_logs 
      WHERE vehicle_id = $1
      ORDER BY date_time DESC, created_at DESC
      LIMIT 1
    `;
    
    const result = await this.pool.query(query, [vehicleId]);
    return result.rows.length > 0 ? this.mapRowToFuelLog(result.rows[0]) : null;
  }
  
  async findByVehicleId(vehicleId: string): Promise<FuelLog[]> {
    const query = `
      SELECT * FROM fuel_logs 
      WHERE vehicle_id = $1 
      ORDER BY date_time DESC, created_at DESC
    `;
    
    const result = await this.pool.query(query, [vehicleId]);
    return result.rows.map(row => this.mapRowToFuelLog(row));
  }
  
  private mapRowToFuelLog(row: any): FuelLog {
    return {
      id: row.id,
      userId: row.user_id,
      vehicleId: row.vehicle_id,
      dateTime: row.date_time,
      odometerReading: row.odometer_reading,
      tripDistance: row.trip_distance,
      fuelType: row.fuel_type,
      fuelGrade: row.fuel_grade,
      fuelUnits: parseFloat(row.fuel_units),
      costPerUnit: parseFloat(row.cost_per_unit),
      totalCost: parseFloat(row.total_cost),
      locationData: row.location_data ? JSON.parse(row.location_data) : null,
      notes: row.notes,
      mpg: row.mpg ? parseFloat(row.mpg) : null,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
      
      // Legacy field mapping
      date: row.date_time,
      odometer: row.odometer_reading,
      gallons: parseFloat(row.fuel_units), // Assuming stored in user's preferred units
      pricePerGallon: parseFloat(row.cost_per_unit)
    };
  }
}
```

## Comprehensive Test Suite

### Service Layer Tests

**File**: `backend/src/features/fuel-logs/tests/unit/enhanced-fuel-logs.service.test.ts`

```typescript
import { FuelLogsService } from '../../domain/fuel-logs.service';
import { FuelLogsRepository } from '../../data/fuel-logs.repository';
import { FuelType, UnitSystem } from '../../domain/fuel-logs.types';
import { UserSettingsService } from '../../external/user-settings.service';

// Mock dependencies
jest.mock('../../data/fuel-logs.repository');
jest.mock('../../external/user-settings.service');
jest.mock('../../../core/config/database');
jest.mock('../../../core/config/redis');

describe('Enhanced FuelLogsService', () => {
  let service: FuelLogsService;
  let mockRepository: jest.Mocked<FuelLogsRepository>;
  
  beforeEach(() => {
    mockRepository = new FuelLogsRepository({} as any) as jest.Mocked<FuelLogsRepository>;
    service = new FuelLogsService(mockRepository);
    
    // Mock user settings
    (UserSettingsService.getUserSettings as jest.Mock).mockResolvedValue({
      unitSystem: UnitSystem.IMPERIAL,
      currencyCode: 'USD',
      timeZone: 'America/New_York'
    });
  });
  
  describe('createFuelLog', () => {
    it('should create fuel log with trip distance', async () => {
      const createData = {
        vehicleId: 'vehicle-id',
        dateTime: '2024-01-15T10:30:00Z',
        tripDistance: 300,
        fuelType: FuelType.GASOLINE,
        fuelGrade: '87',
        fuelUnits: 10,
        costPerUnit: 3.50,
        notes: 'Test fuel log'
      };
      
      // Mock vehicle check
      (pool.query as jest.Mock)
        .mockResolvedValueOnce({ rows: [{ id: 'vehicle-id' }] }) // Vehicle exists
        .mockResolvedValueOnce({}); // Odometer update (not applicable for trip distance)
      
      mockRepository.create.mockResolvedValue({
        id: 'fuel-log-id',
        userId: 'user-id',
        ...createData,
        totalCost: 35.0,
        mpg: 30,
        createdAt: new Date(),
        updatedAt: new Date()
      } as any);
      
      const result = await service.createFuelLog(createData, 'user-id');
      
      expect(result.id).toBe('fuel-log-id');
      expect(result.totalCost).toBe(35.0);
      expect(result.efficiency).toBe(30);
      expect(mockRepository.create).toHaveBeenCalledWith(
        expect.objectContaining({
          tripDistance: 300,
          totalCost: 35.0
        })
      );
    });
    
    it('should validate distance requirement', async () => {
      const createData = {
        vehicleId: 'vehicle-id',
        dateTime: '2024-01-15T10:30:00Z',
        fuelType: FuelType.GASOLINE,
        fuelGrade: '87',
        fuelUnits: 10,
        costPerUnit: 3.50
        // Missing both tripDistance and odometerReading
      };
      
      await expect(service.createFuelLog(createData, 'user-id'))
        .rejects.toThrow('Either odometer reading or trip distance is required');
    });
    
    it('should validate fuel grade for fuel type', async () => {
      const createData = {
        vehicleId: 'vehicle-id',
        dateTime: '2024-01-15T10:30:00Z',
        tripDistance: 300,
        fuelType: FuelType.GASOLINE,
        fuelGrade: '#1', // Invalid for gasoline
        fuelUnits: 10,
        costPerUnit: 3.50
      };
      
      await expect(service.createFuelLog(createData, 'user-id'))
        .rejects.toThrow('Invalid fuel grade');
    });
  });
  
  describe('getEnhancedVehicleStats', () => {
    it('should calculate comprehensive vehicle statistics', async () => {
      const mockLogs = [
        {
          fuelUnits: 10,
          totalCost: 35,
          tripDistance: 300,
          mpg: 30,
          fuelType: FuelType.GASOLINE,
          dateTime: new Date('2024-01-15')
        },
        {
          fuelUnits: 12,
          totalCost: 42,
          tripDistance: 350,
          mpg: 29,
          fuelType: FuelType.GASOLINE,
          dateTime: new Date('2024-01-10')
        }
      ];
      
      // Mock vehicle check
      (pool.query as jest.Mock).mockResolvedValue({ rows: [{ id: 'vehicle-id' }] });
      
      mockRepository.findByVehicleId.mockResolvedValue(mockLogs as any);
      
      const stats = await service.getEnhancedVehicleStats('vehicle-id', 'user-id');
      
      expect(stats.logCount).toBe(2);
      expect(stats.totalFuelUnits).toBe(22);
      expect(stats.totalCost).toBe(77);
      expect(stats.averageCostPerUnit).toBeCloseTo(3.5, 2);
      expect(stats.totalDistance).toBe(650);
      expect(stats.averageEfficiency).toBeCloseTo(29.5, 1);
    });
  });
});
```

### Integration Tests

**File**: `backend/src/features/fuel-logs/tests/integration/enhanced-fuel-logs.integration.test.ts`

```typescript
import request from 'supertest';
import { app } from '../../../app';
import { pool } from '../../../core/config/database';
import { FuelType } from '../../domain/fuel-logs.types';

describe('Enhanced Fuel Logs API Integration', () => {
  let authToken: string;
  let vehicleId: string;
  
  beforeAll(async () => {
    // Setup test data
    authToken = await getTestAuthToken();
    vehicleId = await createTestVehicle();
  });
  
  afterAll(async () => {
    // Cleanup
    await cleanupTestData();
    await pool.end();
  });
  
  describe('POST /api/fuel-logs', () => {
    it('should create fuel log with enhanced fields', async () => {
      const fuelLogData = {
        vehicleId,
        dateTime: '2024-01-15T10:30:00Z',
        tripDistance: 300,
        fuelType: FuelType.GASOLINE,
        fuelGrade: '87',
        fuelUnits: 10,
        costPerUnit: 3.50,
        locationData: {
          address: '123 Main St, Anytown, USA',
          stationName: 'Shell Station'
        },
        notes: 'Full tank'
      };
      
      const response = await request(app)
        .post('/api/fuel-logs')
        .set('Authorization', `Bearer ${authToken}`)
        .send(fuelLogData)
        .expect(201);
      
      expect(response.body.id).toBeDefined();
      expect(response.body.tripDistance).toBe(300);
      expect(response.body.fuelType).toBe(FuelType.GASOLINE);
      expect(response.body.fuelGrade).toBe('87');
      expect(response.body.totalCost).toBe(35.0);
      expect(response.body.efficiency).toBe(30); // 300 miles / 10 gallons
      expect(response.body.efficiencyLabel).toBe('mpg');
    });
    
    it('should validate distance requirement', async () => {
      const fuelLogData = {
        vehicleId,
        dateTime: '2024-01-15T10:30:00Z',
        fuelType: FuelType.GASOLINE,
        fuelGrade: '87',
        fuelUnits: 10,
        costPerUnit: 3.50
        // Missing both tripDistance and odometerReading
      };
      
      const response = await request(app)
        .post('/api/fuel-logs')
        .set('Authorization', `Bearer ${authToken}`)
        .send(fuelLogData)
        .expect(400);
      
      expect(response.body.message).toContain('Either odometer reading or trip distance is required');
    });
  });
  
  describe('GET /api/fuel-logs/fuel-grades/:fuelType', () => {
    it('should return gasoline fuel grades', async () => {
      const response = await request(app)
        .get('/api/fuel-logs/fuel-grades/gasoline')
        .set('Authorization', `Bearer ${authToken}`)
        .expect(200);
      
      expect(response.body.fuelType).toBe('gasoline');
      expect(response.body.grades).toHaveLength(5);
      expect(response.body.grades[0]).toEqual({
        value: '87',
        label: '87 (Regular)',
        description: 'Regular unleaded gasoline'
      });
    });
    
    it('should return empty grades for electric', async () => {
      const response = await request(app)
        .get('/api/fuel-logs/fuel-grades/electric')
        .set('Authorization', `Bearer ${authToken}`)
        .expect(200);
      
      expect(response.body.fuelType).toBe('electric');
      expect(response.body.grades).toHaveLength(0);
    });
  });
  
  describe('GET /api/fuel-logs/fuel-types', () => {
    it('should return all fuel types with grades', async () => {
      const response = await request(app)
        .get('/api/fuel-logs/fuel-types')
        .set('Authorization', `Bearer ${authToken}`)
        .expect(200);
      
      expect(response.body.fuelTypes).toHaveLength(3);
      
      const gasoline = response.body.fuelTypes.find(ft => ft.value === 'gasoline');
      expect(gasoline.grades).toHaveLength(5);
      
      const electric = response.body.fuelTypes.find(ft => ft.value === 'electric');
      expect(electric.grades).toHaveLength(0);
    });
  });
});
```

## Implementation Tasks

### Service Layer Updates
1. ✅ Update FuelLogsService with enhanced business logic
2. ✅ Integrate validation and efficiency calculation services
3. ✅ Add user settings integration
4. ✅ Implement comprehensive stats calculations

### API Layer Updates
1. ✅ Create FuelGradeController for dynamic grades
2. ✅ Update existing controllers with enhanced validation
3. ✅ Add new API endpoints for fuel types/grades
4. ✅ Update validation schemas

### Repository Updates
1. ✅ Update repository for new database fields
2. ✅ Add methods for enhanced queries
3. ✅ Implement proper data mapping

### Testing Implementation
1. ✅ Create comprehensive unit test suite
2. ✅ Implement integration tests for all endpoints
3. ✅ Add validation testing
4. ✅ Test business logic edge cases

## Success Criteria

### Phase 3 Complete When:
- ✅ All API endpoints functional with enhanced data
- ✅ Comprehensive validation working correctly
- ✅ Fuel type/grade system fully operational
- ✅ Unit conversion integration functional
- ✅ Enhanced statistics calculations working
- ✅ Complete test suite passes (>90% coverage)
- ✅ All new endpoints documented and tested
- ✅ Backward compatibility maintained

### Ready for Phase 4 When:
- All backend services tested and stable
- API contracts finalized and documented
- Frontend integration points clearly defined
- Enhanced business logic fully functional

---

**Next Phase**: [Phase 4 - Frontend Implementation](FUEL-LOGS-PHASE-4.md)