// models/tbmTransferModel.js - TBM 작업자 이동 모델
const { getDb } = require('../dbPool');

const TbmTransferModel = {
  /**
   * 작업자 이동 실행 (보내기/빼오기)
   * 트랜잭션: source work_hours 업데이트 + dest INSERT + 로그 INSERT
   */
  async createTransfer(transferData) {
    const db = await getDb();
    const conn = await db.getConnection();
    try {
      await conn.beginTransaction();

      const {
        transfer_type, user_id, source_session_id, dest_session_id,
        hours, initiated_by, transfer_date,
        project_id, work_type_id, task_id, workplace_category_id, workplace_id
      } = transferData;

      // 1. source 세션에서 해당 작업자의 work_hours 업데이트
      const [sourceRows] = await conn.query(
        'SELECT assignment_id, work_hours FROM tbm_team_assignments WHERE session_id = ? AND user_id = ?',
        [source_session_id, user_id]
      );

      if (sourceRows.length === 0) {
        await conn.rollback();
        return { success: false, message: '원본 세션에서 해당 작업자를 찾을 수 없습니다.' };
      }

      const currentHours = sourceRows[0].work_hours === null ? 8 : parseFloat(sourceRows[0].work_hours);
      const newSourceHours = currentHours - parseFloat(hours);

      if (newSourceHours < 0) {
        await conn.rollback();
        return { success: false, message: '이동 시간이 현재 배정 시간보다 큽니다.' };
      }

      await conn.query(
        'UPDATE tbm_team_assignments SET work_hours = ? WHERE session_id = ? AND user_id = ?',
        [newSourceHours, source_session_id, user_id]
      );

      // 2. dest 세션에 작업자 INSERT (이미 있으면 work_hours 증가)
      const [destRows] = await conn.query(
        'SELECT assignment_id, work_hours FROM tbm_team_assignments WHERE session_id = ? AND user_id = ?',
        [dest_session_id, user_id]
      );

      if (destRows.length > 0) {
        const existingHours = destRows[0].work_hours === null ? 8 : parseFloat(destRows[0].work_hours);
        await conn.query(
          'UPDATE tbm_team_assignments SET work_hours = ? WHERE session_id = ? AND user_id = ?',
          [existingHours + parseFloat(hours), dest_session_id, user_id]
        );
      } else {
        await conn.query(
          `INSERT INTO tbm_team_assignments
           (session_id, user_id, work_hours, project_id, work_type_id, task_id, workplace_category_id, workplace_id, is_present)
           VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)`,
          [dest_session_id, user_id, parseFloat(hours),
           project_id || null, work_type_id || null, task_id || null,
           workplace_category_id || null, workplace_id || null]
        );
      }

      // 3. tbm_transfers에 로그 INSERT
      const [logResult] = await conn.query(
        `INSERT INTO tbm_transfers
         (transfer_date, user_id, source_session_id, dest_session_id, hours, transfer_type, initiated_by)
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [transfer_date, user_id, source_session_id, dest_session_id, parseFloat(hours), transfer_type, initiated_by]
      );

      // 4. 합계 시간 검증 (경고만, 차단 안함)
      const [totalRows] = await conn.query(
        `SELECT SUM(COALESCE(work_hours, 8)) as total_hours
         FROM tbm_team_assignments
         WHERE user_id = ?
           AND session_id IN (SELECT session_id FROM tbm_sessions WHERE session_date = ?)`,
        [user_id, transfer_date]
      );
      const totalHours = totalRows[0] ? parseFloat(totalRows[0].total_hours) : 0;

      await conn.commit();

      const result = {
        success: true,
        transfer_id: logResult.insertId,
        total_hours: totalHours
      };

      if (totalHours > 8) {
        result.warning = `해당 작업자의 당일 합계가 ${totalHours}h입니다 (8h 초과).`;
      }

      return result;
    } catch (err) {
      try { await conn.rollback(); } catch (e) {}
      throw err;
    } finally {
      conn.release();
    }
  },

  /**
   * 이동 취소 (원복)
   */
  async cancelTransfer(transferId) {
    const db = await getDb();
    const conn = await db.getConnection();
    try {
      await conn.beginTransaction();

      // 1. 이동 로그 조회
      const [transfers] = await conn.query(
        'SELECT * FROM tbm_transfers WHERE transfer_id = ?',
        [transferId]
      );

      if (transfers.length === 0) {
        await conn.rollback();
        return { success: false, message: '이동 기록을 찾을 수 없습니다.' };
      }

      const t = transfers[0];

      // 2. dest 세션에서 작업자 work_hours 감소 (또는 삭제)
      const [destRows] = await conn.query(
        'SELECT assignment_id, work_hours FROM tbm_team_assignments WHERE session_id = ? AND user_id = ?',
        [t.dest_session_id, t.user_id]
      );

      if (destRows.length > 0) {
        const destHours = destRows[0].work_hours === null ? 8 : parseFloat(destRows[0].work_hours);
        const newDestHours = destHours - parseFloat(t.hours);

        if (newDestHours <= 0) {
          await conn.query(
            'DELETE FROM tbm_team_assignments WHERE session_id = ? AND user_id = ?',
            [t.dest_session_id, t.user_id]
          );
        } else {
          await conn.query(
            'UPDATE tbm_team_assignments SET work_hours = ? WHERE session_id = ? AND user_id = ?',
            [newDestHours, t.dest_session_id, t.user_id]
          );
        }
      }

      // 3. source 세션에서 작업자 work_hours 복원
      const [sourceRows] = await conn.query(
        'SELECT assignment_id, work_hours FROM tbm_team_assignments WHERE session_id = ? AND user_id = ?',
        [t.source_session_id, t.user_id]
      );

      if (sourceRows.length > 0) {
        const sourceHours = sourceRows[0].work_hours === null ? 8 : parseFloat(sourceRows[0].work_hours);
        const restoredHours = sourceHours + parseFloat(t.hours);
        await conn.query(
          'UPDATE tbm_team_assignments SET work_hours = ? WHERE session_id = ? AND user_id = ?',
          [restoredHours >= 8 ? null : restoredHours, t.source_session_id, t.user_id]
        );
      }

      // 4. 이동 로그 삭제
      await conn.query('DELETE FROM tbm_transfers WHERE transfer_id = ?', [transferId]);

      await conn.commit();
      return { success: true };
    } catch (err) {
      try { await conn.rollback(); } catch (e) {}
      throw err;
    } finally {
      conn.release();
    }
  },

  /**
   * 당일 이동 내역 조회
   */
  async getTransfersByDate(date) {
    const db = await getDb();
    const sql = `
      SELECT
        t.*,
        w.worker_name,
        w.job_type,
        sl.worker_name as source_leader_name,
        dl.worker_name as dest_leader_name,
        u.name as initiated_by_name
      FROM tbm_transfers t
      INNER JOIN workers w ON t.user_id = w.user_id
      LEFT JOIN tbm_sessions ss ON t.source_session_id = ss.session_id
      LEFT JOIN workers sl ON ss.leader_id = sl.user_id
      LEFT JOIN tbm_sessions ds ON t.dest_session_id = ds.session_id
      LEFT JOIN workers dl ON ds.leader_id = dl.user_id
      LEFT JOIN sso_users u ON t.initiated_by = u.user_id
      WHERE t.transfer_date = ?
      ORDER BY t.created_at DESC
    `;
    const [rows] = await db.query(sql, [date]);
    return rows;
  },

  /**
   * 당일 전 작업자 배정 현황 조회
   */
  async getWorkerAssignmentsByDate(date) {
    const db = await getDb();

    // 1. 해당 날짜의 모든 배정 가져오기
    const [assignments] = await db.query(`
      SELECT
        ta.user_id,
        ta.session_id,
        ta.work_hours,
        w.worker_name,
        w.job_type,
        s.leader_user_id,
        lw.worker_name as leader_name,
        s.status as session_status
      FROM tbm_team_assignments ta
      INNER JOIN tbm_sessions s ON ta.session_id = s.session_id
      INNER JOIN workers w ON ta.user_id = w.user_id
      LEFT JOIN workers lw ON s.leader_user_id = lw.user_id
      WHERE s.session_date = ?
      ORDER BY w.worker_name
    `, [date]);

    // 2. 모든 작업자 가져오기 (배정 안 된 사람도 포함)
    const [allWorkers] = await db.query(
      "SELECT user_id, worker_name, job_type FROM workers WHERE status = 'active' ORDER BY worker_name"
    );

    // 3. 작업자별 배정 현황 구성
    const workerMap = {};
    allWorkers.forEach(w => {
      workerMap[w.user_id] = {
        user_id: w.user_id,
        worker_name: w.worker_name,
        job_type: w.job_type,
        sessions: [],
        total_hours: 0,
        available: true
      };
    });

    assignments.forEach(a => {
      const hours = a.work_hours === null ? 8 : parseFloat(a.work_hours);
      if (workerMap[a.user_id]) {
        workerMap[a.user_id].sessions.push({
          session_id: a.session_id,
          leader_name: a.leader_name,
          work_hours: hours,
          session_status: a.session_status
        });
        workerMap[a.user_id].total_hours += hours;
      }
    });

    Object.values(workerMap).forEach(w => {
      w.available = w.total_hours < 8;
    });

    return Object.values(workerMap);
  }
};

module.exports = TbmTransferModel;
