/**
 * @ai-summary Fastify route handlers for stations API
 * @ai-context HTTP request/response handling with Fastify reply methods
 */

import { FastifyRequest, FastifyReply } from 'fastify';
import { StationsService } from '../domain/stations.service';
import { StationsRepository } from '../data/stations.repository';
import { pool } from '../../../core/config/database';
import { logger } from '../../../core/logging/logger';
import {
  StationSearchBody,
  SaveStationBody,
  StationParams,
  UpdateSavedStationBody
} from '../domain/stations.types';
import { googleMapsClient } from '../external/google-maps/google-maps.client';

export class StationsController {
  private stationsService: StationsService;

  constructor() {
    const repository = new StationsRepository(pool);
    this.stationsService = new StationsService(repository);
  }
  
  async searchStations(request: FastifyRequest<{ Body: StationSearchBody }>, reply: FastifyReply) {
    try {
      const userId = (request as any).user.sub;
      const { latitude, longitude, radius, fuelType } = request.body;
      
      if (!latitude || !longitude) {
        return reply.code(400).send({ 
          error: 'Bad Request',
          message: 'Latitude and longitude are required' 
        });
      }
      
      const result = await this.stationsService.searchNearbyStations({
        latitude,
        longitude,
        radius,
        fuelType
      }, userId);
      
      return reply.code(200).send(result);
    } catch (error: any) {
      logger.error('Error searching stations', { error, userId: (request as any).user?.sub });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to search stations'
      });
    }
  }
  
  async saveStation(request: FastifyRequest<{ Body: SaveStationBody }>, reply: FastifyReply) {
    try {
      const userId = (request as any).user.sub;
      const {
        placeId,
        nickname,
        notes,
        isFavorite,
        has93Octane,
        has93OctaneEthanolFree
      } = request.body;
      
      if (!placeId) {
        return reply.code(400).send({ 
          error: 'Bad Request',
          message: 'Place ID is required' 
        });
      }
      
      const result = await this.stationsService.saveStation(placeId, userId, {
        nickname,
        notes,
        isFavorite,
        has93Octane,
        has93OctaneEthanolFree
      });
      
      return reply.code(201).send(result);
    } catch (error: any) {
      logger.error('Error saving station', { error, userId: (request as any).user?.sub });
      
      if (error.message.includes('not found')) {
        return reply.code(404).send({
          error: 'Not Found',
          message: error.message
        });
      }
      
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to save station'
      });
    }
  }

  async updateSavedStation(
    request: FastifyRequest<{ Params: StationParams; Body: UpdateSavedStationBody }>,
    reply: FastifyReply
  ) {
    try {
      const userId = (request as any).user.sub;
      const { placeId } = request.params;

      const result = await this.stationsService.updateSavedStation(placeId, userId, request.body);

      return reply.code(200).send(result);
    } catch (error: any) {
      logger.error('Error updating saved station', {
        error,
        placeId: request.params.placeId,
        userId: (request as any).user?.sub
      });

      if (error.message.includes('not found')) {
        return reply.code(404).send({
          error: 'Not Found',
          message: error.message
        });
      }

      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to update saved station'
      });
    }
  }
  
  async getSavedStations(request: FastifyRequest, reply: FastifyReply) {
    try {
      const userId = (request as any).user.sub;
      const result = await this.stationsService.getUserSavedStations(userId);
      
      return reply.code(200).send(result);
    } catch (error: any) {
      logger.error('Error getting saved stations', { error, userId: (request as any).user?.sub });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to get saved stations'
      });
    }
  }
  
  async removeSavedStation(request: FastifyRequest<{ Params: StationParams }>, reply: FastifyReply) {
    try {
      const userId = (request as any).user.sub;
      const { placeId } = request.params;

      await this.stationsService.removeSavedStation(placeId, userId);

      return reply.code(204).send();
    } catch (error: any) {
      logger.error('Error removing saved station', { error, placeId: request.params.placeId, userId: (request as any).user?.sub });

      if (error.message.includes('not found')) {
        return reply.code(404).send({
          error: 'Not Found',
          message: error.message
        });
      }

      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to remove saved station'
      });
    }
  }

  async getStationPhoto(request: FastifyRequest<{ Params: { reference: string } }>, reply: FastifyReply) {
    try {
      const { reference } = request.params;

      if (!reference) {
        return reply.code(400).send({
          error: 'Bad Request',
          message: 'Photo reference is required'
        });
      }

      const photoBuffer = await googleMapsClient.fetchPhoto(reference);

      return reply
        .code(200)
        .header('Content-Type', 'image/jpeg')
        .header('Cache-Control', 'public, max-age=86400')
        .send(photoBuffer);
    } catch (error: any) {
      logger.error('Error fetching station photo', {
        error,
        reference: request.params.reference
      });
      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Failed to fetch station photo'
      });
    }
  }
}
