/**
 * 월별 작업자 상태 집계 컨트롤러
 *
 * 월별 캘린더 및 작업자 상태 집계 API 엔드포인트 핸들러
 *
 * @author TK-FB-Project
 * @since 2025-12-11
 */

const MonthlyStatusModel = require('../models/monthlyStatusModel');
const { ValidationError, ForbiddenError, DatabaseError } = require('../utils/errors');
const { asyncHandler } = require('../middlewares/errorHandler');
const logger = require('../utils/logger');

/**
 * 월별 캘린더 데이터 조회
 */
const getMonthlyCalendarData = asyncHandler(async (req, res) => {
  const { year, month } = req.query;

  if (!year || !month) {
    throw new ValidationError('연도(year)와 월(month)이 필요합니다', {
      required: ['year', 'month'],
      received: { year, month }
    });
  }

  const yearNum = parseInt(year);
  const monthNum = parseInt(month);

  if (yearNum < 2020 || yearNum > 2030 || monthNum < 1 || monthNum > 12) {
    throw new ValidationError('유효하지 않은 연도 또는 월입니다', {
      received: { year: yearNum, month: monthNum }
    });
  }

  logger.info('월별 캘린더 데이터 조회 요청', { year: yearNum, month: monthNum });

  try {
    const summaryData = await MonthlyStatusModel.getMonthlySummary(yearNum, monthNum);

    // 날짜별 객체로 변환
    const calendarData = {};
    summaryData.forEach(day => {
      const dateKey = day.date.toISOString().split('T')[0];
      calendarData[dateKey] = {
        totalWorkers: day.total_workers,
        workingWorkers: day.working_workers,
        hasIssues: day.has_issues,
        hasErrors: day.has_errors,
        hasOvertimeWarning: day.has_overtime_warning,
        incompleteWorkers: day.incomplete_workers,
        partialWorkers: day.partial_workers,
        errorWorkers: day.error_workers,
        overtimeWarningWorkers: day.overtime_warning_workers,
        totalHours: parseFloat(day.total_work_hours || 0),
        totalTasks: day.total_work_count,
        errorCount: day.total_error_count,
        lastUpdated: day.last_updated
      };
    });

    logger.info('월별 캘린더 데이터 조회 성공', {
      year: yearNum,
      month: monthNum,
      dayCount: Object.keys(calendarData).length
    });

    res.json({
      success: true,
      data: calendarData,
      message: `${year}년 ${month}월 캘린더 데이터를 성공적으로 조회했습니다`
    });
  } catch (error) {
    logger.error('월별 캘린더 데이터 조회 실패', {
      year: yearNum,
      month: monthNum,
      error: error.message
    });
    throw new DatabaseError('월별 캘린더 데이터 조회 중 오류가 발생했습니다');
  }
});

/**
 * 특정 날짜의 작업자별 상세 상태 조회
 */
const getDailyWorkerDetails = asyncHandler(async (req, res) => {
  const { date } = req.query;

  if (!date) {
    throw new ValidationError('날짜(date)가 필요합니다', {
      required: ['date'],
      received: { date }
    });
  }

  logger.info('일별 작업자 상세 조회 요청', { date });

  try {
    const workerDetails = await MonthlyStatusModel.getDailyWorkerStatus(date);

    // 데이터 변환
    const formattedData = workerDetails.map(worker => ({
      userId: worker.user_id,
      workerName: worker.worker_name,
      jobType: worker.job_type,
      totalHours: parseFloat(worker.total_work_hours || 0),
      actualWorkHours: parseFloat(worker.actual_work_hours || 0),
      vacationHours: parseFloat(worker.vacation_hours || 0),
      totalWorkCount: worker.total_work_count,
      regularWorkCount: worker.regular_work_count,
      errorWorkCount: worker.error_work_count,
      status: worker.work_status,
      hasVacation: worker.has_vacation,
      hasError: worker.has_error,
      hasIssues: worker.has_issues,
      lastUpdated: worker.last_updated
    }));

    // 요약 정보 계산
    const summary = {
      totalWorkers: formattedData.length,
      totalHours: formattedData.reduce((sum, w) => sum + w.totalHours, 0),
      totalTasks: formattedData.reduce((sum, w) => sum + w.totalWorkCount, 0),
      errorCount: formattedData.reduce((sum, w) => sum + w.errorWorkCount, 0)
    };

    logger.info('일별 작업자 상세 조회 성공', {
      date,
      workerCount: formattedData.length,
      totalHours: summary.totalHours
    });

    res.json({
      success: true,
      data: {
        workers: formattedData,
        summary
      },
      message: `${date} 작업자 상세 정보를 성공적으로 조회했습니다`
    });
  } catch (error) {
    logger.error('일별 작업자 상세 조회 실패', {
      date,
      error: error.message
    });
    throw new DatabaseError('일별 작업자 상세 조회 중 오류가 발생했습니다');
  }
});

/**
 * 월별 집계 재계산 (관리자용)
 */
const recalculateMonth = asyncHandler(async (req, res) => {
  const { year, month } = req.body;

  if (!year || !month) {
    throw new ValidationError('연도(year)와 월(month)이 필요합니다', {
      required: ['year', 'month'],
      received: { year, month }
    });
  }

  // 관리자 권한 확인
  if (req.user.role !== 'admin' && req.user.role !== 'system') {
    throw new ForbiddenError('관리자 권한이 필요합니다');
  }

  logger.info('월별 집계 재계산 시작', {
    year,
    month,
    requestedBy: req.user.username
  });

  try {
    const result = await MonthlyStatusModel.recalculateMonth(parseInt(year), parseInt(month));

    logger.info('월별 집계 재계산 성공', { year, month, result });

    res.json({
      success: true,
      data: result,
      message: `${year}년 ${month}월 집계 재계산이 완료되었습니다`
    });
  } catch (error) {
    logger.error('월별 집계 재계산 실패', {
      year,
      month,
      error: error.message
    });
    throw new DatabaseError('월별 집계 재계산 중 오류가 발생했습니다');
  }
});

/**
 * 집계 테이블 상태 확인 (관리자용)
 */
const getStatusInfo = asyncHandler(async (req, res) => {
  // 관리자 권한 확인
  if (req.user.role !== 'admin' && req.user.role !== 'system') {
    throw new ForbiddenError('관리자 권한이 필요합니다');
  }

  logger.info('집계 테이블 상태 확인 요청', {
    requestedBy: req.user.username
  });

  try {
    const statusInfo = await MonthlyStatusModel.getStatusInfo();

    logger.info('집계 테이블 상태 확인 성공');

    res.json({
      success: true,
      data: statusInfo,
      message: '집계 테이블 상태 정보를 성공적으로 조회했습니다'
    });
  } catch (error) {
    logger.error('집계 테이블 상태 확인 실패', {
      error: error.message
    });
    throw new DatabaseError('집계 테이블 상태 확인 중 오류가 발생했습니다');
  }
});

module.exports = {
  getMonthlyCalendarData,
  getDailyWorkerDetails,
  recalculateMonth,
  getStatusInfo
};
