const { getPool } = require('../middleware/auth');

// ==================== DB 마이그레이션 ====================

const runMigration = async () => {
  const db = getPool();
  try {
    // 컬럼 존재 여부 체크
    const [cols] = await db.query(
      `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
       WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'workplace_visit_requests'
       AND COLUMN_NAME IN ('request_type','visitor_name','department_id','check_in_time','check_out_time')`
    );
    const existing = cols.map(c => c.COLUMN_NAME);

    if (!existing.includes('request_type')) {
      await db.query(`ALTER TABLE workplace_visit_requests ADD COLUMN request_type ENUM('external','internal') NOT NULL DEFAULT 'external' AFTER request_id`);
      console.log('[migration] Added request_type column');
    }
    if (!existing.includes('visitor_name')) {
      await db.query(`ALTER TABLE workplace_visit_requests ADD COLUMN visitor_name VARCHAR(100) NULL AFTER visitor_company`);
      console.log('[migration] Added visitor_name column');
    }
    if (!existing.includes('department_id')) {
      await db.query(`ALTER TABLE workplace_visit_requests ADD COLUMN department_id INT NULL AFTER visitor_name`);
      console.log('[migration] Added department_id column');
    }
    if (!existing.includes('check_in_time')) {
      await db.query(`ALTER TABLE workplace_visit_requests ADD COLUMN check_in_time DATETIME NULL AFTER status`);
      console.log('[migration] Added check_in_time column');
    }
    if (!existing.includes('check_out_time')) {
      await db.query(`ALTER TABLE workplace_visit_requests ADD COLUMN check_out_time DATETIME NULL AFTER check_in_time`);
      console.log('[migration] Added check_out_time column');
    }

    // status ENUM 확장 (checked_in, checked_out 추가)
    await db.query(`ALTER TABLE workplace_visit_requests MODIFY COLUMN status ENUM('pending','approved','rejected','training_completed','checked_in','checked_out') NOT NULL DEFAULT 'pending'`);

    // 인덱스 추가 (이미 있으면 무시)
    try { await db.query(`CREATE INDEX idx_visit_date_type ON workplace_visit_requests (visit_date, request_type)`); } catch (e) { /* already exists */ }
    try { await db.query(`CREATE INDEX idx_checkin_time ON workplace_visit_requests (check_in_time)`); } catch (e) { /* already exists */ }

    console.log('[migration] workplace_visit_requests migration complete');
  } catch (err) {
    console.error('[migration] Error:', err.message);
  }
};

// ==================== 출입 신청 관리 ====================

const createVisitRequest = async (requestData) => {
  const db = getPool();
  const {
    requester_id,
    request_type = 'external',
    visitor_company,
    visitor_name = null,
    visitor_count = 1,
    department_id = null,
    category_id,
    workplace_id,
    visit_date,
    visit_time,
    purpose_id,
    notes = null
  } = requestData;

  // 내부 출입은 바로 approved
  const status = request_type === 'internal' ? 'approved' : 'pending';

  const [result] = await db.query(
    `INSERT INTO workplace_visit_requests
     (requester_id, request_type, visitor_company, visitor_name, visitor_count,
      department_id, category_id, workplace_id, visit_date, visit_time, purpose_id, notes, status)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [requester_id, request_type, visitor_company, visitor_name, visitor_count,
     department_id, category_id, workplace_id, visit_date, visit_time, purpose_id, notes, status]
  );

  return result.insertId;
};

const getAllVisitRequests = async (filters = {}) => {
  const db = getPool();
  let query = `
    SELECT
      vr.request_id, vr.requester_id, vr.request_type,
      vr.visitor_company, vr.visitor_name, vr.visitor_count,
      vr.department_id, vr.category_id, vr.workplace_id,
      vr.visit_date, vr.visit_time,
      vr.purpose_id, vr.notes, vr.status,
      vr.check_in_time, vr.check_out_time,
      vr.approved_by, vr.approved_at, vr.rejection_reason,
      vr.created_at, vr.updated_at,
      u.username as requester_name, u.name as requester_full_name,
      wc.category_name, w.workplace_name,
      vpt.purpose_name,
      approver.username as approver_name,
      d.department_name
    FROM workplace_visit_requests vr
    INNER JOIN sso_users u ON vr.requester_id = u.user_id
    INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id
    INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id
    INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id
    LEFT JOIN sso_users approver ON vr.approved_by = approver.user_id
    LEFT JOIN departments d ON vr.department_id = d.department_id
    WHERE 1=1
  `;

  const params = [];

  if (filters.status) {
    query += ` AND vr.status = ?`;
    params.push(filters.status);
  }
  if (filters.visit_date) {
    query += ` AND vr.visit_date = ?`;
    params.push(filters.visit_date);
  }
  if (filters.start_date && filters.end_date) {
    query += ` AND vr.visit_date BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }
  if (filters.requester_id) {
    query += ` AND vr.requester_id = ?`;
    params.push(filters.requester_id);
  }
  if (filters.category_id) {
    query += ` AND vr.category_id = ?`;
    params.push(filters.category_id);
  }
  if (filters.request_type) {
    query += ` AND vr.request_type = ?`;
    params.push(filters.request_type);
  }

  query += ` ORDER BY vr.visit_date DESC, vr.visit_time DESC, vr.created_at DESC`;

  const [rows] = await db.query(query, params);
  return rows;
};

const getVisitRequestById = async (requestId) => {
  const db = getPool();
  const [rows] = await db.query(
    `SELECT
      vr.request_id, vr.requester_id, vr.request_type,
      vr.visitor_company, vr.visitor_name, vr.visitor_count,
      vr.department_id, vr.category_id, vr.workplace_id,
      vr.visit_date, vr.visit_time,
      vr.purpose_id, vr.notes, vr.status,
      vr.check_in_time, vr.check_out_time,
      vr.approved_by, vr.approved_at, vr.rejection_reason,
      vr.created_at, vr.updated_at,
      u.username as requester_name, u.name as requester_full_name,
      wc.category_name, w.workplace_name,
      vpt.purpose_name,
      approver.username as approver_name,
      d.department_name
    FROM workplace_visit_requests vr
    INNER JOIN sso_users u ON vr.requester_id = u.user_id
    INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id
    INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id
    INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id
    LEFT JOIN sso_users approver ON vr.approved_by = approver.user_id
    LEFT JOIN departments d ON vr.department_id = d.department_id
    WHERE vr.request_id = ?`,
    [requestId]
  );
  return rows[0];
};

const updateVisitRequest = async (requestId, requestData) => {
  const db = getPool();
  const {
    visitor_company, visitor_count, category_id, workplace_id,
    visit_date, visit_time, purpose_id, notes
  } = requestData;

  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET visitor_company = ?, visitor_count = ?, category_id = ?, workplace_id = ?,
         visit_date = ?, visit_time = ?, purpose_id = ?, notes = ?, updated_at = NOW()
     WHERE request_id = ?`,
    [visitor_company, visitor_count, category_id, workplace_id,
     visit_date, visit_time, purpose_id, notes, requestId]
  );
  return result;
};

const deleteVisitRequest = async (requestId) => {
  const db = getPool();
  const [result] = await db.query(
    `DELETE FROM workplace_visit_requests WHERE request_id = ?`,
    [requestId]
  );
  return result;
};

const approveVisitRequest = async (requestId, approvedBy) => {
  const db = getPool();
  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET status = 'approved', approved_by = ?, approved_at = NOW(), updated_at = NOW()
     WHERE request_id = ?`,
    [approvedBy, requestId]
  );
  return result;
};

const rejectVisitRequest = async (requestId, rejectionData) => {
  const db = getPool();
  const { approved_by, rejection_reason } = rejectionData;

  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET status = 'rejected', approved_by = ?, approved_at = NOW(),
         rejection_reason = ?, updated_at = NOW()
     WHERE request_id = ?`,
    [approved_by, rejection_reason, requestId]
  );
  return result;
};

const updateVisitRequestStatus = async (requestId, status) => {
  const db = getPool();
  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET status = ?, updated_at = NOW()
     WHERE request_id = ?`,
    [status, requestId]
  );
  return result;
};

// ==================== 방문 목적 관리 ====================

const getAllVisitPurposes = async () => {
  const db = getPool();
  const [rows] = await db.query(
    `SELECT purpose_id, purpose_name, display_order, is_active, created_at
     FROM visit_purpose_types
     ORDER BY display_order ASC, purpose_id ASC`
  );
  return rows;
};

const getActiveVisitPurposes = async () => {
  const db = getPool();
  const [rows] = await db.query(
    `SELECT purpose_id, purpose_name, display_order, is_active, created_at
     FROM visit_purpose_types
     WHERE is_active = TRUE
     ORDER BY display_order ASC, purpose_id ASC`
  );
  return rows;
};

const createVisitPurpose = async (purposeData) => {
  const db = getPool();
  const { purpose_name, display_order = 0, is_active = true } = purposeData;

  const [result] = await db.query(
    `INSERT INTO visit_purpose_types (purpose_name, display_order, is_active)
     VALUES (?, ?, ?)`,
    [purpose_name, display_order, is_active]
  );
  return result.insertId;
};

const updateVisitPurpose = async (purposeId, purposeData) => {
  const db = getPool();
  const { purpose_name, display_order, is_active } = purposeData;

  const [result] = await db.query(
    `UPDATE visit_purpose_types
     SET purpose_name = ?, display_order = ?, is_active = ?
     WHERE purpose_id = ?`,
    [purpose_name, display_order, is_active, purposeId]
  );
  return result;
};

const deleteVisitPurpose = async (purposeId) => {
  const db = getPool();
  const [result] = await db.query(
    `DELETE FROM visit_purpose_types WHERE purpose_id = ?`,
    [purposeId]
  );
  return result;
};

// ==================== 안전교육 기록 관리 ====================

const createTrainingRecord = async (trainingData) => {
  const db = getPool();
  const {
    request_id, trainer_id, training_date,
    training_start_time, training_end_time = null, training_topics = null
  } = trainingData;

  const [result] = await db.query(
    `INSERT INTO safety_training_records
     (request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics)
     VALUES (?, ?, ?, ?, ?, ?)`,
    [request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics]
  );
  return result.insertId;
};

const getTrainingRecordByRequestId = async (requestId) => {
  const db = getPool();
  const [rows] = await db.query(
    `SELECT
      str.training_id, str.request_id, str.trainer_id, str.training_date,
      str.training_start_time, str.training_end_time, str.training_topics,
      str.signature_data, str.completed_at, str.created_at, str.updated_at,
      u.username as trainer_name, u.name as trainer_full_name
    FROM safety_training_records str
    INNER JOIN sso_users u ON str.trainer_id = u.user_id
    WHERE str.request_id = ?`,
    [requestId]
  );
  return rows[0];
};

const updateTrainingRecord = async (trainingId, trainingData) => {
  const db = getPool();
  const { training_date, training_start_time, training_end_time, training_topics } = trainingData;

  const [result] = await db.query(
    `UPDATE safety_training_records
     SET training_date = ?, training_start_time = ?, training_end_time = ?,
         training_topics = ?, updated_at = NOW()
     WHERE training_id = ?`,
    [training_date, training_start_time, training_end_time, training_topics, trainingId]
  );
  return result;
};

const completeTraining = async (trainingId, signatureData) => {
  const db = getPool();
  const [result] = await db.query(
    `UPDATE safety_training_records
     SET signature_data = ?, completed_at = NOW(), updated_at = NOW()
     WHERE training_id = ?`,
    [signatureData, trainingId]
  );
  return result;
};

const deleteTrainingRecord = async (trainingId) => {
  const db = getPool();
  const connection = await db.getConnection();
  try {
    await connection.beginTransaction();

    // 1. training record 조회 → request_id 획득
    const [rows] = await connection.query(
      'SELECT training_id, request_id FROM safety_training_records WHERE training_id = ?',
      [trainingId]
    );
    if (!rows.length) {
      await connection.rollback();
      return { affectedRows: 0 };
    }
    const requestId = rows[0].request_id;

    // 2. training record 삭제
    await connection.query('DELETE FROM safety_training_records WHERE training_id = ?', [trainingId]);

    // 3. 출입 신청 상태를 approved로 복원
    await connection.query(
      "UPDATE workplace_visit_requests SET status = 'approved', updated_at = NOW() WHERE request_id = ?",
      [requestId]
    );

    await connection.commit();
    return { affectedRows: 1 };
  } catch (err) {
    await connection.rollback();
    throw err;
  } finally {
    connection.release();
  }
};

const getTrainingRecords = async (filters = {}) => {
  const db = getPool();
  let query = `
    SELECT
      str.training_id, str.request_id, str.trainer_id, str.training_date,
      str.training_start_time, str.training_end_time, str.training_topics,
      str.completed_at, str.created_at, str.updated_at,
      u.username as trainer_name, u.name as trainer_full_name,
      vr.visitor_company, vr.visitor_count, vr.visit_date
    FROM safety_training_records str
    INNER JOIN sso_users u ON str.trainer_id = u.user_id
    INNER JOIN workplace_visit_requests vr ON str.request_id = vr.request_id
    WHERE 1=1
  `;

  const params = [];

  if (filters.training_date) {
    query += ` AND str.training_date = ?`;
    params.push(filters.training_date);
  }
  if (filters.start_date && filters.end_date) {
    query += ` AND str.training_date BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }
  if (filters.trainer_id) {
    query += ` AND str.trainer_id = ?`;
    params.push(filters.trainer_id);
  }

  query += ` ORDER BY str.training_date DESC, str.training_start_time DESC`;

  const [rows] = await db.query(query, params);
  return rows;
};

// ==================== 작업장 분류/작업장 조회 ====================

const getAllCategories = async () => {
  const db = getPool();
  const [rows] = await db.query(
    'SELECT category_id, category_name FROM workplace_categories ORDER BY category_name'
  );
  return rows;
};

const getWorkplacesByCategory = async (categoryId) => {
  const db = getPool();
  let query = 'SELECT workplace_id, workplace_name, category_id FROM workplaces';
  const params = [];
  if (categoryId) {
    query += ' WHERE category_id = ?';
    params.push(categoryId);
  }
  query += ' ORDER BY workplace_name';
  const [rows] = await db.query(query, params);
  return rows;
};

// ==================== 체크인/체크아웃 ====================

const checkIn = async (requestId, userId) => {
  const db = getPool();
  // 승인 또는 교육완료 상태만 체크인 가능
  const [rows] = await db.query(
    `SELECT request_id, requester_id, status, request_type FROM workplace_visit_requests WHERE request_id = ?`,
    [requestId]
  );
  if (!rows.length) return { error: '신청을 찾을 수 없습니다.', status: 404 };
  const req = rows[0];

  const allowedStatuses = req.request_type === 'internal'
    ? ['approved']
    : ['approved', 'training_completed'];
  if (!allowedStatuses.includes(req.status)) {
    return { error: `체크인 불가 상태입니다. (현재: ${req.status})`, status: 400 };
  }

  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET status = 'checked_in', check_in_time = NOW(), updated_at = NOW()
     WHERE request_id = ?`,
    [requestId]
  );
  return { success: true, result };
};

const checkOut = async (requestId, userId) => {
  const db = getPool();
  const [rows] = await db.query(
    `SELECT request_id, requester_id, status FROM workplace_visit_requests WHERE request_id = ?`,
    [requestId]
  );
  if (!rows.length) return { error: '신청을 찾을 수 없습니다.', status: 404 };
  if (rows[0].status !== 'checked_in') {
    return { error: `체크아웃 불가 상태입니다. (현재: ${rows[0].status})`, status: 400 };
  }

  const [result] = await db.query(
    `UPDATE workplace_visit_requests
     SET status = 'checked_out', check_out_time = NOW(), updated_at = NOW()
     WHERE request_id = ?`,
    [requestId]
  );
  return { success: true, result };
};

// ==================== 통합 대시보드 ====================

const getEntryDashboard = async (date) => {
  const db = getPool();
  const query = `
    SELECT 'visit' as source, vr.request_type, vr.visitor_company, vr.visitor_name,
           vr.visitor_count, wc.category_name, w.workplace_name,
           vr.visit_date as entry_date, vr.visit_time as entry_time,
           vr.check_in_time, vr.check_out_time, vr.status,
           u.name COLLATE utf8mb4_general_ci as reporter_name, vpt.purpose_name, NULL as source_note
    FROM workplace_visit_requests vr
    LEFT JOIN workplace_categories wc ON vr.category_id = wc.category_id
    LEFT JOIN workplaces w ON vr.workplace_id = w.workplace_id
    LEFT JOIN sso_users u ON vr.requester_id = u.user_id
    LEFT JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id
    WHERE vr.visit_date = ? AND vr.status NOT IN ('pending','rejected')

    UNION ALL

    SELECT 'tbm' as source, 'internal' as request_type, NULL as visitor_company, wk.worker_name COLLATE utf8mb4_general_ci as visitor_name,
           1 as visitor_count, NULL as category_name, ts.work_location COLLATE utf8mb4_general_ci as workplace_name,
           ts.session_date as entry_date, TIME(ts.created_at) as entry_time,
           ts.created_at as check_in_time, ts.end_time as check_out_time,
           CASE WHEN ta.is_present=1 THEN 'checked_in' ELSE 'absent' END as status,
           leader.worker_name COLLATE utf8mb4_general_ci as reporter_name, '작업(TBM)' as purpose_name, 'TBM 세션 기준' as source_note
    FROM tbm_team_assignments ta
    JOIN tbm_sessions ts ON ta.session_id = ts.session_id
    JOIN workers wk ON ta.worker_id = wk.worker_id
    LEFT JOIN workers leader ON ts.leader_user_id = leader.user_id
    WHERE ts.session_date = ? AND ts.status != 'cancelled'

    UNION ALL

    SELECT 'partner' as source, 'external' as request_type,
           pc.company_name as visitor_company, pwc.worker_names COLLATE utf8mb4_general_ci as visitor_name,
           pwc.actual_worker_count as visitor_count, NULL as category_name, ps.workplace_name COLLATE utf8mb4_general_ci,
           DATE(pwc.check_in_time) as entry_date, TIME(pwc.check_in_time) as entry_time,
           pwc.check_in_time, pwc.check_out_time,
           CASE WHEN pwc.check_out_time IS NOT NULL THEN 'checked_out' ELSE 'checked_in' END as status,
           u2.name COLLATE utf8mb4_general_ci as reporter_name, ps.work_description COLLATE utf8mb4_general_ci as purpose_name, NULL as source_note
    FROM partner_work_checkins pwc
    JOIN partner_schedules ps ON pwc.schedule_id = ps.id
    JOIN partner_companies pc ON pwc.company_id = pc.id
    LEFT JOIN sso_users u2 ON pwc.checked_by = u2.user_id
    WHERE DATE(pwc.check_in_time) = ?

    ORDER BY entry_date DESC, check_in_time DESC
  `;

  const [rows] = await db.query(query, [date, date, date]);
  return rows;
};

const getEntryStats = async (date) => {
  const db = getPool();

  // 방문자 (visit source — request_type별 분리)
  const [visitStats] = await db.query(
    `SELECT request_type, SUM(visitor_count) as cnt
     FROM workplace_visit_requests
     WHERE visit_date = ? AND status = 'checked_in'
     GROUP BY request_type`,
    [date]
  );

  // 협력업체
  const [partnerStats] = await db.query(
    `SELECT COALESCE(SUM(actual_worker_count), 0) as cnt
     FROM partner_work_checkins
     WHERE DATE(check_in_time) = ? AND check_out_time IS NULL`,
    [date]
  );

  // TBM (참고용)
  const [tbmStats] = await db.query(
    `SELECT COUNT(*) as cnt FROM tbm_team_assignments ta
     JOIN tbm_sessions ts ON ta.session_id = ts.session_id
     WHERE ts.session_date = ? AND ts.status != 'cancelled' AND ta.is_present = 1`,
    [date]
  );

  const external = visitStats.find(v => v.request_type === 'external');
  const internal = visitStats.find(v => v.request_type === 'internal');

  return {
    external_visit: Number(external?.cnt || 0),
    internal_visit: Number(internal?.cnt || 0),
    partner: Number(partnerStats[0]?.cnt || 0),
    tbm: Number(tbmStats[0]?.cnt || 0)
  };
};

// ==================== 부서 목록 조회 ====================

const getAllDepartments = async () => {
  const db = getPool();
  const [rows] = await db.query(
    'SELECT department_id, department_name FROM departments WHERE is_active = 1 ORDER BY department_name'
  );
  return rows;
};

module.exports = {
  runMigration,
  createVisitRequest,
  getAllVisitRequests,
  getVisitRequestById,
  updateVisitRequest,
  deleteVisitRequest,
  approveVisitRequest,
  rejectVisitRequest,
  updateVisitRequestStatus,
  checkIn,
  checkOut,
  getEntryDashboard,
  getEntryStats,
  getAllVisitPurposes,
  getActiveVisitPurposes,
  createVisitPurpose,
  updateVisitPurpose,
  deleteVisitPurpose,
  createTrainingRecord,
  getTrainingRecordByRequestId,
  updateTrainingRecord,
  deleteTrainingRecord,
  completeTraining,
  getTrainingRecords,
  getAllCategories,
  getWorkplacesByCategory,
  getAllDepartments
};
