/**
 * 작업자 관리 컨트롤러
 *
 * 작업자 CRUD API 엔드포인트 핸들러
 *
 * @author TK-FB-Project
 * @since 2025-12-11
 */

const workerModel = require('../models/workerModel');
const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors');
const { asyncHandler } = require('../middlewares/errorHandler');
const logger = require('../utils/logger');
const cache = require('../utils/cache');
const { optimizedQueries } = require('../utils/queryOptimizer');
const { hangulToRoman, generateUniqueUsername } = require('../utils/hangulToRoman');
const bcrypt = require('bcryptjs');
const { getDb } = require('../dbPool');

/**
 * 작업자 생성
 */
exports.createWorker = asyncHandler(async (req, res) => {
  const workerData = req.body;
  const createAccount = req.body.create_account;

  logger.info('작업자 생성 요청', { name: workerData.worker_name, create_account: createAccount });

  const lastID = await workerModel.create(workerData);

  // 계정 생성 요청이 있으면 users 테이블에 계정 생성 + workers.user_id 연결
  if (createAccount && workerData.worker_name) {
    try {
      const db = await getDb();
      const username = await generateUniqueUsername(workerData.worker_name, db);
      const hashedPassword = await bcrypt.hash(process.env.DEFAULT_PASSWORD || 'changeme!1', 10);

      // User 역할 조회
      const [userRole] = await db.query('SELECT id FROM roles WHERE name = ?', ['User']);

      if (userRole && userRole.length > 0) {
        const [insertResult] = await db.query(
          `INSERT INTO users (username, password, name, role_id, created_at, updated_at)
           VALUES (?, ?, ?, ?, NOW(), NOW())`,
          [username, hashedPassword, workerData.worker_name, userRole[0].id]
        );

        // workers.user_id 연결
        const newUserId = insertResult.insertId;
        await db.query('UPDATE workers SET user_id = ? WHERE worker_id = ?', [newUserId, lastID]);

        logger.info('작업자 계정 자동 생성 성공', { worker_id: lastID, user_id: newUserId, username });
      }
    } catch (accountError) {
      logger.error('계정 생성 실패 (작업자는 생성됨)', { worker_id: lastID, error: accountError.message });
    }
  }

  // 작업자 관련 캐시 무효화
  await cache.invalidateCache.worker();

  logger.info('작업자 생성 성공', { worker_id: lastID });

  res.status(201).json({
    success: true,
    data: { worker_id: lastID },
    message: '작업자가 성공적으로 생성되었습니다'
  });
});

/**
 * 전체 작업자 조회 (캐싱 및 페이지네이션 적용)
 */
exports.getAllWorkers = asyncHandler(async (req, res) => {
  const { page = 1, limit = 100, search = '', status = '', department_id = null } = req.query;

  const cacheKey = cache.createKey('workers', 'list', page, limit, search, status, department_id);

  // 캐시에서 조회
  const cachedData = await cache.get(cacheKey);
  if (cachedData) {
    logger.debug('캐시 히트', { cacheKey });
    return res.json({
      success: true,
      data: cachedData.data,
      pagination: cachedData.pagination,
      message: '작업자 목록 조회 성공 (캐시)'
    });
  }

  // 최적화된 쿼리 사용
  const result = await optimizedQueries.getWorkersPaged(page, limit, search, status, department_id);

  // 캐시에 저장 (5분)
  await cache.set(cacheKey, result, cache.TTL.MEDIUM);
  logger.debug('캐시 저장', { cacheKey });

  res.json({
    success: true,
    data: result.data,
    pagination: result.pagination,
    message: '작업자 목록 조회 성공'
  });
});

/**
 * 단일 작업자 조회
 */
exports.getWorkerById = asyncHandler(async (req, res) => {
  const id = parseInt(req.params.user_id, 10);

  if (isNaN(id)) {
    throw new ValidationError('유효하지 않은 작업자 ID입니다');
  }

  const row = await workerModel.getByUserId(id);

  if (!row) {
    throw new NotFoundError('작업자를 찾을 수 없습니다');
  }

  res.json({
    success: true,
    data: row,
    message: '작업자 조회 성공'
  });
});

/**
 * 작업자 수정
 */
exports.updateWorker = asyncHandler(async (req, res) => {
  const id = parseInt(req.params.user_id, 10);

  if (isNaN(id)) {
    throw new ValidationError('유효하지 않은 작업자 ID입니다');
  }

  const workerData = { ...req.body, user_id: id };
  const createAccount = req.body.create_account;

  // 먼저 현재 작업자 정보 조회 (계정 여부 확인용, user_id 기준)
  const currentWorker = await workerModel.getByUserId(id);

  if (!currentWorker) {
    throw new NotFoundError('작업자를 찾을 수 없습니다');
  }

  // 작업자 정보 업데이트
  const changes = await workerModel.update(workerData);

  // 계정 생성/해제 처리
  const db = await getDb();
  const hasAccount = currentWorker.user_id !== null && currentWorker.user_id !== undefined;
  let accountAction = null;
  let accountUsername = null;

  if (createAccount && !hasAccount && workerData.worker_name) {
    // 계정 생성
    try {
      const username = await generateUniqueUsername(workerData.worker_name, db);
      const hashedPassword = await bcrypt.hash(process.env.DEFAULT_PASSWORD || 'changeme!1', 10);

      const [userRole] = await db.query('SELECT id FROM roles WHERE name = ?', ['User']);

      if (userRole && userRole.length > 0) {
        const [insertResult] = await db.query(
          `INSERT INTO users (username, password, name, role_id, created_at, updated_at)
           VALUES (?, ?, ?, ?, NOW(), NOW())`,
          [username, hashedPassword, workerData.worker_name, userRole[0].id]
        );

        // workers.user_id 연결
        const newUserId = insertResult.insertId;
        await db.query('UPDATE workers SET user_id = ? WHERE user_id = ?', [newUserId, id]);

        accountAction = 'created';
        accountUsername = username;
        logger.info('작업자 계정 생성 성공', { user_id: id, new_user_id: newUserId, username });
      }
    } catch (accountError) {
      logger.error('계정 생성 실패', { user_id: id, error: accountError.message });
      accountAction = 'failed';
    }
  }

  if (!createAccount && hasAccount) {
    // 계정 연동 해제 (workers.user_id = NULL)
    try {
      await db.query('UPDATE workers SET user_id = NULL WHERE user_id = ?', [id]);
      accountAction = 'unlinked';
      logger.info('작업자 계정 연동 해제 성공', { user_id: id });
    } catch (unlinkError) {
      logger.error('계정 연동 해제 실패', { user_id: id, error: unlinkError.message });
      accountAction = 'unlink_failed';
    }
  } else if (createAccount && hasAccount) {
    accountAction = 'already_exists';
  }

  // 작업자 관련 캐시 무효화
  logger.info('작업자 수정 후 캐시 무효화', { user_id: id });
  await cache.invalidateCache.worker();

  logger.info('작업자 수정 성공', { user_id: id });

  // 응답 메시지 구성
  let message = '작업자 정보가 성공적으로 수정되었습니다';
  if (accountAction === 'created') {
    message += ` (계정 생성 완료: ${accountUsername}, 초기 비밀번호: 1234)`;
  } else if (accountAction === 'unlinked') {
    message += ' (계정 연동 해제 완료)';
  } else if (accountAction === 'already_exists') {
    message += ' (이미 계정이 존재합니다)';
  } else if (accountAction === 'failed') {
    message += ' (계정 생성 실패)';
  }

  res.json({
    success: true,
    data: {
      changes,
      account_action: accountAction,
      account_username: accountUsername
    },
    message
  });
});

/**
 * 작업자 삭제
 */
exports.removeWorker = asyncHandler(async (req, res) => {
  const id = parseInt(req.params.user_id, 10);

  if (isNaN(id)) {
    throw new ValidationError('유효하지 않은 작업자 ID입니다');
  }

  const changes = await workerModel.remove(id);

  if (changes === 0) {
    throw new NotFoundError('작업자를 찾을 수 없습니다');
  }

  // 작업자 관련 캐시 무효화
  logger.info('작업자 삭제 후 캐시 무효화 시작', { user_id: id });
  await cache.invalidateCache.worker();
  await cache.delPattern('workers:*');
  await cache.flush();
  logger.info('작업자 삭제 후 캐시 무효화 완료', { user_id: id });

  res.json({
    success: true,
    message: '작업자가 성공적으로 삭제되었습니다'
  });
});