/**
 * 작업 분석 컨트롤러
 *
 * 작업 보고서 다차원 분석 API 엔드포인트 핸들러
 *
 * @author TK-FB-Project
 * @since 2025-12-11
 */

const WorkAnalysis = require('../models/WorkAnalysis');
const { getDb } = require('../dbPool');
const { ValidationError, DatabaseError } = require('../utils/errors');
const { asyncHandler } = require('../middlewares/errorHandler');
const logger = require('../utils/logger');

/**
 * 날짜 유효성 검사 헬퍼 함수
 */
const validateDateRange = (startDate, endDate) => {
  if (!startDate || !endDate) {
    throw new ValidationError('시작일과 종료일을 입력해주세요', {
      required: ['start', 'end'],
      received: { start: startDate, end: endDate }
    });
  }

  const start = new Date(startDate);
  const end = new Date(endDate);

  if (isNaN(start.getTime()) || isNaN(end.getTime())) {
    throw new ValidationError('올바른 날짜 형식을 입력해주세요', {
      format: 'YYYY-MM-DD',
      received: { start: startDate, end: endDate }
    });
  }

  if (start > end) {
    throw new ValidationError('시작일이 종료일보다 늦을 수 없습니다', {
      start: startDate,
      end: endDate
    });
  }

  // 너무 긴 기간 방지 (1년 제한)
  const diffTime = Math.abs(end - start);
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  if (diffDays > 365) {
    throw new ValidationError('조회 기간은 1년을 초과할 수 없습니다', {
      days: diffDays,
      max: 365
    });
  }

  return { start, end };
};

/**
 * 기본 통계 조회
 */
const getStats = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('기본 통계 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const stats = await workAnalysis.getBasicStats(start, end);

    logger.info('기본 통계 조회 성공', { start, end });

    res.json({
      success: true,
      data: stats,
      message: '기본 통계 조회 완료'
    });
  } catch (error) {
    logger.error('기본 통계 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('기본 통계 조회 중 오류가 발생했습니다');
  }
});

/**
 * 일별 작업시간 추이 조회
 */
const getDailyTrend = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('일별 추이 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const trendData = await workAnalysis.getDailyTrend(start, end);

    logger.info('일별 추이 조회 성공', { start, end, dataPoints: trendData.length });

    res.json({
      success: true,
      data: trendData,
      message: '일별 추이 조회 완료'
    });
  } catch (error) {
    logger.error('일별 추이 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('일별 추이 조회 중 오류가 발생했습니다');
  }
});

/**
 * 작업자별 통계 조회
 */
const getWorkerStats = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('작업자별 통계 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const workerStats = await workAnalysis.getWorkerStats(start, end);

    logger.info('작업자별 통계 조회 성공', {
      start,
      end,
      workerCount: workerStats.length
    });

    res.json({
      success: true,
      data: workerStats,
      message: '작업자별 통계 조회 완료'
    });
  } catch (error) {
    logger.error('작업자별 통계 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('작업자별 통계 조회 중 오류가 발생했습니다');
  }
});

/**
 * 프로젝트별 통계 조회
 */
const getProjectStats = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('프로젝트별 통계 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const projectStats = await workAnalysis.getProjectStats(start, end);

    logger.info('프로젝트별 통계 조회 성공', {
      start,
      end,
      projectCount: projectStats.length
    });

    res.json({
      success: true,
      data: projectStats,
      message: '프로젝트별 통계 조회 완료'
    });
  } catch (error) {
    logger.error('프로젝트별 통계 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('프로젝트별 통계 조회 중 오류가 발생했습니다');
  }
});

/**
 * 작업유형별 통계 조회
 */
const getWorkTypeStats = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('작업유형별 통계 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const workTypeStats = await workAnalysis.getWorkTypeStats(start, end);

    logger.info('작업유형별 통계 조회 성공', {
      start,
      end,
      workTypeCount: workTypeStats.length
    });

    res.json({
      success: true,
      data: workTypeStats,
      message: '작업유형별 통계 조회 완료'
    });
  } catch (error) {
    logger.error('작업유형별 통계 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('작업유형별 통계 조회 중 오류가 발생했습니다');
  }
});

/**
 * 최근 작업 현황 조회
 */
const getRecentWork = asyncHandler(async (req, res) => {
  const { start, end, limit = 10 } = req.query;
  validateDateRange(start, end);

  // limit 유효성 검사 (최대 5000까지 허용)
  const limitNum = parseInt(limit);
  if (isNaN(limitNum) || limitNum < 1 || limitNum > 5000) {
    throw new ValidationError('limit은 1~5000 사이의 숫자여야 합니다', {
      received: limit,
      min: 1,
      max: 5000
    });
  }

  logger.info('최근 작업 현황 조회 요청', { start, end, limit: limitNum });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const recentWork = await workAnalysis.getRecentWork(start, end, limitNum);

    logger.info('최근 작업 현황 조회 성공', {
      start,
      end,
      limit: limitNum,
      resultCount: recentWork.length
    });

    res.json({
      success: true,
      data: recentWork,
      message: '최근 작업 현황 조회 완료'
    });
  } catch (error) {
    logger.error('최근 작업 현황 조회 실패', {
      start,
      end,
      limit: limitNum,
      error: error.message
    });
    throw new DatabaseError('최근 작업 현황 조회 중 오류가 발생했습니다');
  }
});

/**
 * 요일별 패턴 분석 조회
 */
const getWeekdayPattern = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('요일별 패턴 분석 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const weekdayPattern = await workAnalysis.getWeekdayPattern(start, end);

    logger.info('요일별 패턴 분석 성공', { start, end });

    res.json({
      success: true,
      data: weekdayPattern,
      message: '요일별 패턴 분석 완료'
    });
  } catch (error) {
    logger.error('요일별 패턴 분석 실패', { start, end, error: error.message });
    throw new DatabaseError('요일별 패턴 분석 중 오류가 발생했습니다');
  }
});

/**
 * 에러 분석 조회
 */
const getErrorAnalysis = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('에러 분석 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const errorAnalysis = await workAnalysis.getErrorAnalysis(start, end);

    logger.info('에러 분석 성공', { start, end });

    res.json({
      success: true,
      data: errorAnalysis,
      message: '에러 분석 완료'
    });
  } catch (error) {
    logger.error('에러 분석 실패', { start, end, error: error.message });
    throw new DatabaseError('에러 분석 중 오류가 발생했습니다');
  }
});

/**
 * 월별 비교 분석 조회
 */
const getMonthlyComparison = asyncHandler(async (req, res) => {
  const { year = new Date().getFullYear() } = req.query;

  const yearNum = parseInt(year);
  if (isNaN(yearNum) || yearNum < 2000 || yearNum > 2050) {
    throw new ValidationError('올바른 연도를 입력해주세요', {
      received: year,
      min: 2000,
      max: 2050
    });
  }

  logger.info('월별 비교 분석 요청', { year: yearNum });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const monthlyData = await workAnalysis.getMonthlyComparison(yearNum);

    logger.info('월별 비교 분석 성공', { year: yearNum });

    res.json({
      success: true,
      data: monthlyData,
      message: '월별 비교 분석 완료'
    });
  } catch (error) {
    logger.error('월별 비교 분석 실패', { year: yearNum, error: error.message });
    throw new DatabaseError('월별 비교 분석 중 오류가 발생했습니다');
  }
});

/**
 * 작업자별 전문분야 분석 조회
 */
const getWorkerSpecialization = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('작업자별 전문분야 분석 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);
    const specializationData = await workAnalysis.getWorkerSpecialization(start, end);

    // 작업자별로 그룹화하여 정리
    const groupedData = specializationData.reduce((acc, item) => {
      if (!acc[item.user_id]) {
        acc[item.user_id] = [];
      }
      acc[item.user_id].push({
        work_type_id: item.work_type_id,
        project_id: item.project_id,
        totalHours: item.totalHours,
        totalReports: item.totalReports,
        percentage: item.percentage
      });
      return acc;
    }, {});

    logger.info('작업자별 전문분야 분석 성공', {
      start,
      end,
      workerCount: Object.keys(groupedData).length
    });

    res.json({
      success: true,
      data: groupedData,
      message: '작업자별 전문분야 분석 완료'
    });
  } catch (error) {
    logger.error('작업자별 전문분야 분석 실패', { start, end, error: error.message });
    throw new DatabaseError('작업자별 전문분야 분석 중 오류가 발생했습니다');
  }
});

/**
 * 대시보드용 종합 데이터 조회
 */
const getDashboardData = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('대시보드 데이터 조회 요청', { start, end });

  try {
    const db = await getDb();
    const workAnalysis = new WorkAnalysis(db);

    // 병렬로 여러 데이터 조회
    const [
      stats,
      dailyTrend,
      workerStats,
      projectStats,
      workTypeStats,
      recentWork
    ] = await Promise.all([
      workAnalysis.getBasicStats(start, end),
      workAnalysis.getDailyTrend(start, end),
      workAnalysis.getWorkerStats(start, end),
      workAnalysis.getProjectStats(start, end),
      workAnalysis.getWorkTypeStats(start, end),
      workAnalysis.getRecentWork(start, end, 10)
    ]);

    logger.info('대시보드 데이터 조회 성공', { start, end });

    res.json({
      success: true,
      data: {
        stats,
        dailyTrend,
        workerStats,
        projectStats,
        workTypeStats,
        recentWork
      },
      message: '대시보드 데이터 조회 완료'
    });
  } catch (error) {
    logger.error('대시보드 데이터 조회 실패', { start, end, error: error.message });
    throw new DatabaseError('대시보드 데이터 조회 중 오류가 발생했습니다');
  }
});

const workAnalysisService = require('../services/workAnalysisService');

/**
 * 프로젝트별-작업별 시간 분석 (총시간, 정규시간, 에러시간)
 */
const getProjectWorkTypeAnalysis = asyncHandler(async (req, res) => {
  const { start, end } = req.query;
  validateDateRange(start, end);

  logger.info('프로젝트별-작업별 시간 분석 요청', { start, end });

  try {
    const result = await workAnalysisService.getProjectWorkTypeAnalysis(start, end);

    logger.info('프로젝트별-작업별 시간 분석 성공', {
      start,
      end,
      projectCount: result.summary.total_projects,
      workTypeCount: result.summary.total_work_types,
      totalHours: result.summary.grand_total_hours
    });

    res.json({
      success: true,
      data: result,
      message: '프로젝트별-작업별 시간 분석 완료'
    });
  } catch (error) {
    logger.error('프로젝트별-작업별 시간 분석 실패', {
      start,
      end,
      error: error.message
    });
    // Service throws DatabaseError wrapper or Error
    if (error.name === 'DatabaseError') {
      throw error;
    }
    throw new DatabaseError('프로젝트별-작업별 시간 분석 중 오류가 발생했습니다');
  }
});

module.exports = {
  getStats,
  getDailyTrend,
  getWorkerStats,
  getProjectStats,
  getWorkTypeStats,
  getRecentWork,
  getWeekdayPattern,
  getErrorAnalysis,
  getMonthlyComparison,
  getWorkerSpecialization,
  getDashboardData,
  getProjectWorkTypeAnalysis
};
