/**
 * 데일리 워크 레포트 분석 컨트롤러
 *
 * 작업 보고서 종합 분석 API 엔드포인트 핸들러
 *
 * @author TK-FB-Project
 * @since 2025-12-11
 */

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

/**
 * 분석용 필터 데이터 조회 (프로젝트, 작업자, 작업유형 목록)
 */
const getAnalysisFilters = asyncHandler(async (req, res) => {
  logger.info('분석 필터 데이터 조회 요청');

  const db = await getDb();

  try {
    const [[projects], [workers], [workTypes], [dateRange]] = await Promise.all([
      db.query(`
        SELECT DISTINCT p.project_id, p.project_name
        FROM projects p
        INNER JOIN daily_work_reports dwr ON p.project_id = dwr.project_id
        ORDER BY p.project_name
      `),
      db.query(`
        SELECT DISTINCT w.user_id, w.worker_name
        FROM workers w
        INNER JOIN daily_work_reports dwr ON w.user_id = dwr.user_id
        ORDER BY w.worker_name
      `),
      db.query(`
        SELECT DISTINCT wt.id as work_type_id, wt.name as work_type_name
        FROM work_types wt
        INNER JOIN daily_work_reports dwr ON wt.id = dwr.work_type_id
        ORDER BY wt.name
      `),
      db.query(`
        SELECT
          MIN(report_date) as min_date,
          MAX(report_date) as max_date
        FROM daily_work_reports
      `),
    ]);

    logger.info('분석 필터 데이터 조회 성공', {
      projects: projects.length,
      workers: workers.length,
      workTypes: workTypes.length
    });

    res.json({
      success: true,
      data: {
        projects,
        workers,
        workTypes,
        dateRange: dateRange[0]
      },
      message: '분석 필터 데이터 조회 성공'
    });
  } catch (error) {
    logger.error('분석 필터 데이터 조회 실패', { error: error.message });
    throw new DatabaseError('필터 데이터 조회 중 오류가 발생했습니다');
  }
});

/**
 * 기간별 작업 분석 데이터 조회
 */
const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
  const { start_date, end_date, project_id, user_id } = req.query;

  if (!start_date || !end_date) {
    throw new ValidationError('start_date와 end_date가 필요합니다', {
      required: ['start_date', 'end_date'],
      received: { start_date, end_date },
      example: 'start_date=2025-08-01&end_date=2025-08-31'
    });
  }

  logger.info('기간별 분석 데이터 조회 요청', {
    start_date,
    end_date,
    project_id,
    user_id
  });

  const db = await getDb();

  try {
    // 기본 조건
    let whereConditions = ['dwr.report_date BETWEEN ? AND ?'];
    let queryParams = [start_date, end_date];

    if (project_id) {
      whereConditions.push('dwr.project_id = ?');
      queryParams.push(project_id);
    }

    if (user_id) {
      whereConditions.push('dwr.user_id = ?');
      queryParams.push(user_id);
    }

    const whereClause = whereConditions.join(' AND ');

    // 1. 전체 요약 통계
    const overallSql = `
      SELECT
        COUNT(*) as total_entries,
        SUM(dwr.work_hours) as total_hours,
        COUNT(DISTINCT dwr.user_id) as unique_workers,
        COUNT(DISTINCT dwr.project_id) as unique_projects,
        COUNT(DISTINCT dwr.report_date) as working_days,
        AVG(dwr.work_hours) as avg_hours_per_entry,
        COUNT(DISTINCT dwr.created_by) as contributors,
        COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_entries,
        ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate
      FROM daily_work_reports dwr
      WHERE ${whereClause}
    `;

    const [
      [overallStats],
      [dailyStats],
      [dailyErrorStats],
      [errorAnalysis],
      [workTypeAnalysis],
      [workerAnalysis],
      [projectAnalysis],
    ] = await Promise.all([
      // 1. 전체 요약 통계
      db.query(overallSql, queryParams),
      // 2. 일별 통계
      db.query(`
        SELECT
          dwr.report_date,
          SUM(dwr.work_hours) as daily_hours,
          COUNT(*) as daily_entries,
          COUNT(DISTINCT dwr.user_id) as daily_workers
        FROM daily_work_reports dwr
        WHERE ${whereClause}
        GROUP BY dwr.report_date
        ORDER BY dwr.report_date ASC
      `, queryParams),
      // 3. 일별 에러 통계
      db.query(`
        SELECT
          dwr.report_date,
          COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as daily_errors,
          COUNT(*) as daily_total,
          ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as daily_error_rate
        FROM daily_work_reports dwr
        WHERE ${whereClause}
        GROUP BY dwr.report_date
        ORDER BY dwr.report_date ASC
      `, queryParams),
      // 4. 에러 유형별 분석
      db.query(`
        SELECT
          et.id as error_type_id,
          et.name as error_type_name,
          COUNT(*) as error_count,
          SUM(dwr.work_hours) as error_hours,
          ROUND((COUNT(*) / (SELECT COUNT(*) FROM daily_work_reports WHERE error_type_id IS NOT NULL)) * 100, 2) as error_percentage
        FROM daily_work_reports dwr
        LEFT JOIN error_types et ON dwr.error_type_id = et.id
        WHERE ${whereClause} AND dwr.error_type_id IS NOT NULL
        GROUP BY et.id, et.name
        ORDER BY error_count DESC
      `, queryParams),
      // 5. 작업 유형별 분석
      db.query(`
        SELECT
          wt.id as work_type_id,
          wt.name as work_type_name,
          COUNT(*) as work_count,
          SUM(dwr.work_hours) as total_hours,
          AVG(dwr.work_hours) as avg_hours,
          COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count,
          ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate
        FROM daily_work_reports dwr
        LEFT JOIN work_types wt ON dwr.work_type_id = wt.id
        WHERE ${whereClause}
        GROUP BY wt.id, wt.name
        ORDER BY total_hours DESC
      `, queryParams),
      // 6. 작업자별 성과 분석
      db.query(`
        SELECT
          w.user_id,
          w.worker_name,
          COUNT(*) as total_entries,
          SUM(dwr.work_hours) as total_hours,
          AVG(dwr.work_hours) as avg_hours_per_entry,
          COUNT(DISTINCT dwr.project_id) as projects_worked,
          COUNT(DISTINCT dwr.report_date) as working_days,
          COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count,
          ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate
        FROM daily_work_reports dwr
        LEFT JOIN workers w ON dwr.user_id = w.user_id
        WHERE ${whereClause}
        GROUP BY w.user_id, w.worker_name
        ORDER BY total_hours DESC
      `, queryParams),
      // 7. 프로젝트별 분석
      db.query(`
        SELECT
          p.project_id,
          p.project_name,
          COUNT(*) as total_entries,
          SUM(dwr.work_hours) as total_hours,
          COUNT(DISTINCT dwr.user_id) as workers_count,
          COUNT(DISTINCT dwr.report_date) as working_days,
          AVG(dwr.work_hours) as avg_hours_per_entry,
          COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count,
          ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate
        FROM daily_work_reports dwr
        LEFT JOIN projects p ON dwr.project_id = p.project_id
        WHERE ${whereClause}
        GROUP BY p.project_id, p.project_name
        ORDER BY total_hours DESC
      `, queryParams),
    ]);

    logger.info('기간별 분석 데이터 조회 성공', {
      start_date,
      end_date,
      total_entries: overallStats[0].total_entries,
      total_hours: overallStats[0].total_hours
    });

    res.json({
      success: true,
      data: {
        summary: overallStats[0],
        dailyStats,
        dailyErrorStats,
        errorAnalysis,
        workTypeAnalysis,
        workerAnalysis,
        projectAnalysis,
        period: { start_date, end_date },
        filters: { project_id, user_id }
      },
      message: '기간별 분석 데이터 조회 성공'
    });
  } catch (error) {
    logger.error('기간별 분석 데이터 조회 실패', {
      start_date,
      end_date,
      error: error.message
    });
    throw new DatabaseError('기간별 분석 데이터 조회 중 오류가 발생했습니다');
  }
});

/**
 * 프로젝트별 상세 분석
 */
const getProjectAnalysis = asyncHandler(async (req, res) => {
  const { start_date, end_date, project_id } = req.query;

  if (!start_date || !end_date) {
    throw new ValidationError('start_date와 end_date가 필요합니다', {
      required: ['start_date', 'end_date'],
      received: { start_date, end_date }
    });
  }

  logger.info('프로젝트별 분석 조회 요청', {
    start_date,
    end_date,
    project_id
  });

  const db = await getDb();

  try {
    let whereConditions = ['dwr.report_date BETWEEN ? AND ?'];
    let queryParams = [start_date, end_date];

    if (project_id) {
      whereConditions.push('dwr.project_id = ?');
      queryParams.push(project_id);
    }

    const whereClause = whereConditions.join(' AND ');

    const projectStatsSql = `
      SELECT
        dwr.project_id,
        p.project_name,
        SUM(dwr.work_hours) as total_hours,
        COUNT(*) as total_entries,
        COUNT(DISTINCT dwr.user_id) as workers_count,
        COUNT(DISTINCT dwr.report_date) as working_days,
        AVG(dwr.work_hours) as avg_hours_per_entry
      FROM daily_work_reports dwr
      LEFT JOIN projects p ON dwr.project_id = p.project_id
      WHERE ${whereClause}
      GROUP BY dwr.project_id
      ORDER BY total_hours DESC
    `;

    const [projectStats] = await db.query(projectStatsSql, queryParams);

    logger.info('프로젝트별 분석 조회 성공', {
      start_date,
      end_date,
      projectCount: projectStats.length
    });

    res.json({
      success: true,
      data: {
        projectStats,
        period: { start_date, end_date }
      },
      message: '프로젝트별 분석 조회 성공'
    });
  } catch (error) {
    logger.error('프로젝트별 분석 조회 실패', {
      start_date,
      end_date,
      error: error.message
    });
    throw new DatabaseError('프로젝트별 분석 데이터 조회 중 오류가 발생했습니다');
  }
});

/**
 * 작업자별 상세 분석
 */
const getWorkerAnalysis = asyncHandler(async (req, res) => {
  const { start_date, end_date, user_id } = req.query;

  if (!start_date || !end_date) {
    throw new ValidationError('start_date와 end_date가 필요합니다', {
      required: ['start_date', 'end_date'],
      received: { start_date, end_date }
    });
  }

  logger.info('작업자별 분석 조회 요청', {
    start_date,
    end_date,
    user_id
  });

  const db = await getDb();

  try {
    let whereConditions = ['dwr.report_date BETWEEN ? AND ?'];
    let queryParams = [start_date, end_date];

    if (user_id) {
      whereConditions.push('dwr.user_id = ?');
      queryParams.push(user_id);
    }

    const whereClause = whereConditions.join(' AND ');

    const workerStatsSql = `
      SELECT
        dwr.user_id,
        w.worker_name,
        SUM(dwr.work_hours) as total_hours,
        COUNT(*) as total_entries,
        COUNT(DISTINCT dwr.project_id) as projects_worked,
        COUNT(DISTINCT dwr.report_date) as working_days,
        AVG(dwr.work_hours) as avg_hours_per_entry
      FROM daily_work_reports dwr
      LEFT JOIN workers w ON dwr.user_id = w.user_id
      WHERE ${whereClause}
      GROUP BY dwr.user_id
      ORDER BY total_hours DESC
    `;

    const [workerStats] = await db.query(workerStatsSql, queryParams);

    logger.info('작업자별 분석 조회 성공', {
      start_date,
      end_date,
      workerCount: workerStats.length
    });

    res.json({
      success: true,
      data: {
        workerStats,
        period: { start_date, end_date }
      },
      message: '작업자별 분석 조회 성공'
    });
  } catch (error) {
    logger.error('작업자별 분석 조회 실패', {
      start_date,
      end_date,
      error: error.message
    });
    throw new DatabaseError('작업자별 분석 데이터 조회 중 오류가 발생했습니다');
  }
});

module.exports = {
  getAnalysisFilters,
  getAnalyticsByPeriod,
  getProjectAnalysis,
  getWorkerAnalysis
};
