import { logger } from "../utils/logger";
import { query } from "../database/db";

// 환경 변수로 데이터 소스 선택
const DATA_SOURCE = process.env.MAINTENANCE_DATA_SOURCE || "memory";

export interface MaintenanceSchedule {
  id: string;
  vehicleNumber: string;
  vehicleType: string;
  maintenanceType: "정기점검" | "수리" | "타이어교체" | "오일교환" | "기타";
  scheduledDate: string;
  status: "scheduled" | "in_progress" | "completed" | "overdue";
  notes?: string;
  estimatedCost?: number;
  actualCost?: number;
  createdAt: string;
  updatedAt: string;
  startedAt?: string;
  completedAt?: string;
  mechanicName?: string;
  location?: string;
}

// 메모리 목 데이터
const mockSchedules: MaintenanceSchedule[] = [
  {
    id: "maint-1",
    vehicleNumber: "서울12가3456",
    vehicleType: "1톤 트럭",
    maintenanceType: "정기점검",
    scheduledDate: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString(),
    status: "scheduled",
    notes: "6개월 정기점검",
    estimatedCost: 300000,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    location: "본사 정비소",
  },
  {
    id: "maint-2",
    vehicleNumber: "경기34나5678",
    vehicleType: "2.5톤 트럭",
    maintenanceType: "오일교환",
    scheduledDate: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString(),
    status: "scheduled",
    estimatedCost: 150000,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    location: "본사 정비소",
  },
  {
    id: "maint-3",
    vehicleNumber: "인천56다7890",
    vehicleType: "라보",
    maintenanceType: "타이어교체",
    scheduledDate: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString(),
    status: "overdue",
    notes: "긴급",
    estimatedCost: 400000,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    location: "외부 정비소",
  },
  {
    id: "maint-4",
    vehicleNumber: "부산78라1234",
    vehicleType: "1톤 트럭",
    maintenanceType: "수리",
    scheduledDate: new Date().toISOString(),
    status: "in_progress",
    notes: "엔진 점검 중",
    estimatedCost: 800000,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
    startedAt: new Date().toISOString(),
    location: "본사 정비소",
  },
];

/**
 * 정비 일정 관리 서비스 (Memory/DB 하이브리드)
 */
export class MaintenanceService {
  private static instance: MaintenanceService;

  private constructor() {
    logger.info(`🔧 정비 일정 데이터 소스: ${DATA_SOURCE.toUpperCase()}`);
  }

  public static getInstance(): MaintenanceService {
    if (!MaintenanceService.instance) {
      MaintenanceService.instance = new MaintenanceService();
    }
    return MaintenanceService.instance;
  }

  public async getAllSchedules(filter?: {
    status?: string;
    vehicleNumber?: string;
  }): Promise<MaintenanceSchedule[]> {
    try {
      const schedules = DATA_SOURCE === "database"
        ? await this.loadSchedulesFromDB(filter)
        : this.loadSchedulesFromMemory(filter);

      // 자동으로 overdue 상태 업데이트
      const now = new Date();
      schedules.forEach((s) => {
        if (s.status === "scheduled" && new Date(s.scheduledDate) < now) {
          s.status = "overdue";
        }
      });

      // 정렬: 지연 > 진행중 > 예정 > 완료
      schedules.sort((a, b) => {
        const statusOrder = { overdue: 0, in_progress: 1, scheduled: 2, completed: 3 };
        if (a.status !== b.status) {
          return statusOrder[a.status] - statusOrder[b.status];
        }
        return new Date(a.scheduledDate).getTime() - new Date(b.scheduledDate).getTime();
      });

      return schedules;
    } catch (error) {
      logger.error("❌ 정비 일정 조회 오류:", error);
      throw error;
    }
  }

  public async updateScheduleStatus(
    id: string,
    status: MaintenanceSchedule["status"]
  ): Promise<MaintenanceSchedule> {
    try {
      if (DATA_SOURCE === "database") {
        return await this.updateScheduleStatusDB(id, status);
      } else {
        return this.updateScheduleStatusMemory(id, status);
      }
    } catch (error) {
      logger.error("❌ 정비 상태 업데이트 오류:", error);
      throw error;
    }
  }

  // ==================== DATABASE 메서드 ====================

  private async loadSchedulesFromDB(filter?: {
    status?: string;
    vehicleNumber?: string;
  }): Promise<MaintenanceSchedule[]> {
    let sql = `
      SELECT 
        id, vehicle_number as "vehicleNumber", vehicle_type as "vehicleType",
        maintenance_type as "maintenanceType", scheduled_date as "scheduledDate",
        status, notes, estimated_cost as "estimatedCost", actual_cost as "actualCost",
        created_at as "createdAt", updated_at as "updatedAt",
        started_at as "startedAt", completed_at as "completedAt",
        mechanic_name as "mechanicName", location
      FROM maintenance_schedules
      WHERE 1=1
    `;
    const params: any[] = [];
    let paramIndex = 1;

    if (filter?.status) {
      sql += ` AND status = $${paramIndex++}`;
      params.push(filter.status);
    }
    if (filter?.vehicleNumber) {
      sql += ` AND vehicle_number = $${paramIndex++}`;
      params.push(filter.vehicleNumber);
    }

    const rows = await query(sql, params);
    return rows.map((row: any) => ({
      ...row,
      scheduledDate: new Date(row.scheduledDate).toISOString(),
      createdAt: new Date(row.createdAt).toISOString(),
      updatedAt: new Date(row.updatedAt).toISOString(),
      startedAt: row.startedAt ? new Date(row.startedAt).toISOString() : undefined,
      completedAt: row.completedAt ? new Date(row.completedAt).toISOString() : undefined,
    }));
  }

  private async updateScheduleStatusDB(
    id: string,
    status: MaintenanceSchedule["status"]
  ): Promise<MaintenanceSchedule> {
    let additionalSet = "";
    if (status === "in_progress") {
      additionalSet = ", started_at = NOW()";
    } else if (status === "completed") {
      additionalSet = ", completed_at = NOW()";
    }

    const rows = await query(
      `UPDATE maintenance_schedules 
       SET status = $1, updated_at = NOW() ${additionalSet}
       WHERE id = $2
       RETURNING 
         id, vehicle_number as "vehicleNumber", vehicle_type as "vehicleType",
         maintenance_type as "maintenanceType", scheduled_date as "scheduledDate",
         status, notes, estimated_cost as "estimatedCost",
         created_at as "createdAt", updated_at as "updatedAt",
         started_at as "startedAt", completed_at as "completedAt",
         mechanic_name as "mechanicName", location`,
      [status, id]
    );

    if (rows.length === 0) {
      throw new Error(`정비 일정을 찾을 수 없습니다: ${id}`);
    }

    const row = rows[0];
    return {
      ...row,
      scheduledDate: new Date(row.scheduledDate).toISOString(),
      createdAt: new Date(row.createdAt).toISOString(),
      updatedAt: new Date(row.updatedAt).toISOString(),
      startedAt: row.startedAt ? new Date(row.startedAt).toISOString() : undefined,
      completedAt: row.completedAt ? new Date(row.completedAt).toISOString() : undefined,
    };
  }

  // ==================== MEMORY 메서드 ====================

  private loadSchedulesFromMemory(filter?: {
    status?: string;
    vehicleNumber?: string;
  }): MaintenanceSchedule[] {
    let schedules = [...mockSchedules];

    if (filter?.status) {
      schedules = schedules.filter((s) => s.status === filter.status);
    }
    if (filter?.vehicleNumber) {
      schedules = schedules.filter((s) => s.vehicleNumber === filter.vehicleNumber);
    }

    return schedules;
  }

  private updateScheduleStatusMemory(
    id: string,
    status: MaintenanceSchedule["status"]
  ): MaintenanceSchedule {
    const schedule = mockSchedules.find((s) => s.id === id);

    if (!schedule) {
      throw new Error(`정비 일정을 찾을 수 없습니다: ${id}`);
    }

    schedule.status = status;
    schedule.updatedAt = new Date().toISOString();

    if (status === "in_progress") {
      schedule.startedAt = new Date().toISOString();
    } else if (status === "completed") {
      schedule.completedAt = new Date().toISOString();
    }

    return schedule;
  }
}

