/**
 * 차량 운행 이력 서비스
 */
import { getPool } from "../database/db";
import { v4 as uuidv4 } from "uuid";
import { calculateDistance } from "../utils/geoUtils";

interface StartTripParams {
  userId: string;
  companyCode: string;
  vehicleId?: number;
  departure?: string;
  arrival?: string;
  departureName?: string;
  destinationName?: string;
  latitude: number;
  longitude: number;
}

interface EndTripParams {
  tripId: string;
  userId: string;
  companyCode: string;
  latitude: number;
  longitude: number;
}

interface AddLocationParams {
  tripId: string;
  userId: string;
  companyCode: string;
  latitude: number;
  longitude: number;
  accuracy?: number;
  speed?: number;
}

interface TripListFilters {
  userId?: string;
  vehicleId?: number;
  status?: string;
  startDate?: string;
  endDate?: string;
  departure?: string;
  arrival?: string;
  limit?: number;
  offset?: number;
}

class VehicleTripService {
  private get pool() {
    return getPool();
  }

  /**
   * 운행 시작
   */
  async startTrip(params: StartTripParams) {
    const {
      userId,
      companyCode,
      vehicleId,
      departure,
      arrival,
      departureName,
      destinationName,
      latitude,
      longitude,
    } = params;

    const tripId = `TRIP-${Date.now()}-${uuidv4().substring(0, 8)}`;

    // 1. vehicle_trip_summary에 운행 기록 생성
    const summaryQuery = `
      INSERT INTO vehicle_trip_summary (
        trip_id, user_id, vehicle_id, departure, arrival, 
        departure_name, destination_name, start_time, status, company_code
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), 'active', $8)
      RETURNING *
    `;

    const summaryResult = await this.pool.query(summaryQuery, [
      tripId,
      userId,
      vehicleId || null,
      departure || null,
      arrival || null,
      departureName || null,
      destinationName || null,
      companyCode,
    ]);

    // 2. 시작 위치 기록
    const locationQuery = `
      INSERT INTO vehicle_location_history (
        trip_id, user_id, vehicle_id, latitude, longitude, 
        trip_status, departure, arrival, departure_name, destination_name,
        recorded_at, company_code
      ) VALUES ($1, $2, $3, $4, $5, 'start', $6, $7, $8, $9, NOW(), $10)
      RETURNING id
    `;

    await this.pool.query(locationQuery, [
      tripId,
      userId,
      vehicleId || null,
      latitude,
      longitude,
      departure || null,
      arrival || null,
      departureName || null,
      destinationName || null,
      companyCode,
    ]);

    return {
      tripId,
      summary: summaryResult.rows[0],
      startLocation: { latitude, longitude },
    };
  }

  /**
   * 운행 종료
   */
  async endTrip(params: EndTripParams) {
    const { tripId, userId, companyCode, latitude, longitude } = params;

    // 1. 운행 정보 조회
    const tripQuery = `
      SELECT * FROM vehicle_trip_summary 
      WHERE trip_id = $1 AND company_code = $2 AND status = 'active'
    `;
    const tripResult = await this.pool.query(tripQuery, [tripId, companyCode]);

    if (tripResult.rows.length === 0) {
      throw new Error("활성 운행을 찾을 수 없습니다.");
    }

    const trip = tripResult.rows[0];

    // 2. 마지막 위치 기록
    const locationQuery = `
      INSERT INTO vehicle_location_history (
        trip_id, user_id, vehicle_id, latitude, longitude, 
        trip_status, departure, arrival, departure_name, destination_name,
        recorded_at, company_code
      ) VALUES ($1, $2, $3, $4, $5, 'end', $6, $7, $8, $9, NOW(), $10)
      RETURNING id
    `;

    await this.pool.query(locationQuery, [
      tripId,
      userId,
      trip.vehicle_id,
      latitude,
      longitude,
      trip.departure,
      trip.arrival,
      trip.departure_name,
      trip.destination_name,
      companyCode,
    ]);

    // 3. 총 거리 및 위치 수 계산
    const statsQuery = `
      SELECT 
        COUNT(*) as location_count,
        MIN(recorded_at) as start_time,
        MAX(recorded_at) as end_time
      FROM vehicle_location_history
      WHERE trip_id = $1 AND company_code = $2
    `;
    const statsResult = await this.pool.query(statsQuery, [tripId, companyCode]);
    const stats = statsResult.rows[0];

    // 4. 모든 위치 데이터로 총 거리 계산
    const locationsQuery = `
      SELECT latitude, longitude 
      FROM vehicle_location_history
      WHERE trip_id = $1 AND company_code = $2
      ORDER BY recorded_at ASC
    `;
    const locationsResult = await this.pool.query(locationsQuery, [tripId, companyCode]);
    
    let totalDistance = 0;
    const locations = locationsResult.rows;
    for (let i = 1; i < locations.length; i++) {
      const prev = locations[i - 1];
      const curr = locations[i];
      totalDistance += calculateDistance(
        prev.latitude,
        prev.longitude,
        curr.latitude,
        curr.longitude
      );
    }

    // 5. 운행 시간 계산 (분)
    const startTime = new Date(stats.start_time);
    const endTime = new Date(stats.end_time);
    const durationMinutes = Math.round((endTime.getTime() - startTime.getTime()) / 60000);

    // 6. 운행 요약 업데이트
    const updateQuery = `
      UPDATE vehicle_trip_summary 
      SET 
        end_time = NOW(),
        total_distance = $1,
        duration_minutes = $2,
        location_count = $3,
        status = 'completed'
      WHERE trip_id = $4 AND company_code = $5
      RETURNING *
    `;

    const updateResult = await this.pool.query(updateQuery, [
      totalDistance.toFixed(3),
      durationMinutes,
      stats.location_count,
      tripId,
      companyCode,
    ]);

    return {
      tripId,
      summary: updateResult.rows[0],
      totalDistance: parseFloat(totalDistance.toFixed(3)),
      durationMinutes,
      locationCount: parseInt(stats.location_count),
    };
  }

  /**
   * 위치 기록 추가 (연속 추적)
   */
  async addLocation(params: AddLocationParams) {
    const { tripId, userId, companyCode, latitude, longitude, accuracy, speed } = params;

    // 1. 운행 정보 조회
    const tripQuery = `
      SELECT * FROM vehicle_trip_summary 
      WHERE trip_id = $1 AND company_code = $2 AND status = 'active'
    `;
    const tripResult = await this.pool.query(tripQuery, [tripId, companyCode]);

    if (tripResult.rows.length === 0) {
      throw new Error("활성 운행을 찾을 수 없습니다.");
    }

    const trip = tripResult.rows[0];

    // 2. 이전 위치 조회 (거리 계산용)
    const prevLocationQuery = `
      SELECT latitude, longitude 
      FROM vehicle_location_history
      WHERE trip_id = $1 AND company_code = $2
      ORDER BY recorded_at DESC
      LIMIT 1
    `;
    const prevResult = await this.pool.query(prevLocationQuery, [tripId, companyCode]);
    
    let distanceFromPrev = 0;
    if (prevResult.rows.length > 0) {
      const prev = prevResult.rows[0];
      distanceFromPrev = calculateDistance(
        prev.latitude,
        prev.longitude,
        latitude,
        longitude
      );
    }

    // 3. 위치 기록 추가
    const locationQuery = `
      INSERT INTO vehicle_location_history (
        trip_id, user_id, vehicle_id, latitude, longitude, 
        accuracy, speed, distance_from_prev,
        trip_status, departure, arrival, departure_name, destination_name,
        recorded_at, company_code
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 'tracking', $9, $10, $11, $12, NOW(), $13)
      RETURNING id
    `;

    const result = await this.pool.query(locationQuery, [
      tripId,
      userId,
      trip.vehicle_id,
      latitude,
      longitude,
      accuracy || null,
      speed || null,
      distanceFromPrev > 0 ? distanceFromPrev.toFixed(3) : null,
      trip.departure,
      trip.arrival,
      trip.departure_name,
      trip.destination_name,
      companyCode,
    ]);

    // 4. 운행 요약의 위치 수 업데이트
    await this.pool.query(
      `UPDATE vehicle_trip_summary SET location_count = location_count + 1 WHERE trip_id = $1`,
      [tripId]
    );

    return {
      locationId: result.rows[0].id,
      distanceFromPrev: parseFloat(distanceFromPrev.toFixed(3)),
    };
  }

  /**
   * 운행 이력 목록 조회
   */
  async getTripList(companyCode: string, filters: TripListFilters) {
    const conditions: string[] = ["company_code = $1"];
    const params: any[] = [companyCode];
    let paramIndex = 2;

    if (filters.userId) {
      conditions.push(`user_id = $${paramIndex++}`);
      params.push(filters.userId);
    }

    if (filters.vehicleId) {
      conditions.push(`vehicle_id = $${paramIndex++}`);
      params.push(filters.vehicleId);
    }

    if (filters.status) {
      conditions.push(`status = $${paramIndex++}`);
      params.push(filters.status);
    }

    if (filters.startDate) {
      conditions.push(`start_time >= $${paramIndex++}`);
      params.push(filters.startDate);
    }

    if (filters.endDate) {
      conditions.push(`start_time <= $${paramIndex++}`);
      params.push(filters.endDate + " 23:59:59");
    }

    if (filters.departure) {
      conditions.push(`departure = $${paramIndex++}`);
      params.push(filters.departure);
    }

    if (filters.arrival) {
      conditions.push(`arrival = $${paramIndex++}`);
      params.push(filters.arrival);
    }

    const whereClause = conditions.join(" AND ");

    // 총 개수 조회
    const countQuery = `SELECT COUNT(*) as total FROM vehicle_trip_summary WHERE ${whereClause}`;
    const countResult = await this.pool.query(countQuery, params);
    const total = parseInt(countResult.rows[0].total);

    // 목록 조회
    const limit = filters.limit || 50;
    const offset = filters.offset || 0;

    const listQuery = `
      SELECT 
        vts.*,
        ui.user_name,
        v.vehicle_number
      FROM vehicle_trip_summary vts
      LEFT JOIN user_info ui ON vts.user_id = ui.user_id
      LEFT JOIN vehicles v ON vts.vehicle_id = v.id
      WHERE ${whereClause}
      ORDER BY vts.start_time DESC
      LIMIT $${paramIndex++} OFFSET $${paramIndex++}
    `;

    params.push(limit, offset);
    const listResult = await this.pool.query(listQuery, params);

    return {
      data: listResult.rows,
      total,
    };
  }

  /**
   * 운행 상세 조회 (경로 포함)
   */
  async getTripDetail(tripId: string, companyCode: string) {
    // 1. 운행 요약 조회
    const summaryQuery = `
      SELECT 
        vts.*,
        ui.user_name,
        v.vehicle_number
      FROM vehicle_trip_summary vts
      LEFT JOIN user_info ui ON vts.user_id = ui.user_id
      LEFT JOIN vehicles v ON vts.vehicle_id = v.id
      WHERE vts.trip_id = $1 AND vts.company_code = $2
    `;
    const summaryResult = await this.pool.query(summaryQuery, [tripId, companyCode]);

    if (summaryResult.rows.length === 0) {
      return null;
    }

    // 2. 경로 데이터 조회
    const routeQuery = `
      SELECT 
        id, latitude, longitude, accuracy, speed, 
        distance_from_prev, trip_status, recorded_at
      FROM vehicle_location_history
      WHERE trip_id = $1 AND company_code = $2
      ORDER BY recorded_at ASC
    `;
    const routeResult = await this.pool.query(routeQuery, [tripId, companyCode]);

    return {
      summary: summaryResult.rows[0],
      route: routeResult.rows,
    };
  }

  /**
   * 활성 운행 조회
   */
  async getActiveTrip(userId: string, companyCode: string) {
    const query = `
      SELECT * FROM vehicle_trip_summary 
      WHERE user_id = $1 AND company_code = $2 AND status = 'active'
      ORDER BY start_time DESC
      LIMIT 1
    `;
    const result = await this.pool.query(query, [userId, companyCode]);
    return result.rows[0] || null;
  }

  /**
   * 운행 취소
   */
  async cancelTrip(tripId: string, companyCode: string) {
    const query = `
      UPDATE vehicle_trip_summary 
      SET status = 'cancelled', end_time = NOW()
      WHERE trip_id = $1 AND company_code = $2 AND status = 'active'
      RETURNING *
    `;
    const result = await this.pool.query(query, [tripId, companyCode]);
    return result.rows[0] || null;
  }
}

export const vehicleTripService = new VehicleTripService();
