/**
 * 작업 중 문제 신고 모델
 * 부적합/안전 신고 관련 DB 쿼리
 */

const { getDb } = require('../dbPool');

// ==================== 신고 카테고리 관리 ====================

const getAllCategories = async () => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT category_id, category_type, category_name, description, display_order, is_active, created_at
     FROM issue_report_categories
     ORDER BY category_type, display_order, category_id`
  );
  return rows;
};

const getCategoriesByType = async (categoryType) => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT category_id, category_type, category_name, description, display_order
     FROM issue_report_categories
     WHERE category_type = ? AND is_active = TRUE
     ORDER BY display_order, category_id`,
    [categoryType]
  );
  return rows;
};

const createCategory = async (categoryData) => {
  const db = await getDb();
  const { category_type, category_name, description = null, display_order = 0 } = categoryData;

  const [result] = await db.query(
    `INSERT INTO issue_report_categories (category_type, category_name, description, display_order)
     VALUES (?, ?, ?, ?)`,
    [category_type, category_name, description, display_order]
  );

  return result.insertId;
};

const updateCategory = async (categoryId, categoryData) => {
  const db = await getDb();
  const { category_name, description, display_order, is_active } = categoryData;

  const [result] = await db.query(
    `UPDATE issue_report_categories
     SET category_name = ?, description = ?, display_order = ?, is_active = ?
     WHERE category_id = ?`,
    [category_name, description, display_order, is_active, categoryId]
  );

  return result;
};

const deleteCategory = async (categoryId) => {
  const db = await getDb();
  const [result] = await db.query(
    `DELETE FROM issue_report_categories WHERE category_id = ?`,
    [categoryId]
  );
  return result;
};

// ==================== 사전 정의 신고 항목 관리 ====================

const getItemsByCategory = async (categoryId) => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT item_id, category_id, item_name, description, severity, display_order
     FROM issue_report_items
     WHERE category_id = ? AND is_active = TRUE
     ORDER BY display_order, item_id`,
    [categoryId]
  );
  return rows;
};

const getAllItems = async () => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT iri.item_id, iri.category_id, iri.item_name, iri.description,
            iri.severity, iri.display_order, iri.is_active, iri.created_at,
            irc.category_name, irc.category_type
     FROM issue_report_items iri
     INNER JOIN issue_report_categories irc ON iri.category_id = irc.category_id
     ORDER BY irc.category_type, irc.display_order, iri.display_order, iri.item_id`
  );
  return rows;
};

const createItem = async (itemData) => {
  const db = await getDb();
  const { category_id, item_name, description = null, severity = 'medium', display_order = 0 } = itemData;

  const [result] = await db.query(
    `INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order)
     VALUES (?, ?, ?, ?, ?)`,
    [category_id, item_name, description, severity, display_order]
  );

  return result.insertId;
};

const updateItem = async (itemId, itemData) => {
  const db = await getDb();
  const { item_name, description, severity, display_order, is_active } = itemData;

  const [result] = await db.query(
    `UPDATE issue_report_items
     SET item_name = ?, description = ?, severity = ?, display_order = ?, is_active = ?
     WHERE item_id = ?`,
    [item_name, description, severity, display_order, is_active, itemId]
  );

  return result;
};

const deleteItem = async (itemId) => {
  const db = await getDb();
  const [result] = await db.query(
    `DELETE FROM issue_report_items WHERE item_id = ?`,
    [itemId]
  );
  return result;
};

// ==================== 문제 신고 관리 ====================

// 한국 시간 유틸리티 import
const { getKoreaDatetime } = require('../utils/dateUtils');

const createReport = async (reportData) => {
  const db = await getDb();
  const {
    reporter_id,
    factory_category_id = null,
    workplace_id = null,
    custom_location = null,
    tbm_session_id = null,
    visit_request_id = null,
    issue_category_id,
    issue_item_id = null,
    additional_description = null,
    photo_path1 = null,
    photo_path2 = null,
    photo_path3 = null,
    photo_path4 = null,
    photo_path5 = null
  } = reportData;

  const reportDate = getKoreaDatetime();

  const [result] = await db.query(
    `INSERT INTO work_issue_reports
     (reporter_id, report_date, factory_category_id, workplace_id, custom_location,
      tbm_session_id, visit_request_id, issue_category_id, issue_item_id,
      additional_description, photo_path1, photo_path2, photo_path3, photo_path4, photo_path5)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [reporter_id, reportDate, factory_category_id, workplace_id, custom_location,
     tbm_session_id, visit_request_id, issue_category_id, issue_item_id,
     additional_description, photo_path1, photo_path2, photo_path3, photo_path4, photo_path5]
  );

  await db.query(
    `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by)
     VALUES (?, NULL, 'reported', ?)`,
    [result.insertId, reporter_id]
  );

  return result.insertId;
};

const getAllReports = async (filters = {}) => {
  const db = await getDb();
  let query = `
    SELECT
      wir.report_id, wir.reporter_id, wir.report_date,
      wir.factory_category_id, wir.workplace_id, wir.custom_location,
      wir.tbm_session_id, wir.visit_request_id,
      wir.issue_category_id, wir.issue_item_id, wir.additional_description,
      wir.photo_path1, wir.photo_path2, wir.photo_path3, wir.photo_path4, wir.photo_path5,
      wir.status, wir.assigned_department, wir.assigned_user_id, wir.assigned_at,
      wir.resolution_notes, wir.resolved_at,
      wir.created_at, wir.updated_at,
      u.username as reporter_name, u.name as reporter_full_name,
      wc.category_name as factory_name,
      w.workplace_name,
      irc.category_type, irc.category_name as issue_category_name,
      iri.item_name as issue_item_name, iri.severity,
      assignee.username as assigned_user_name, assignee.name as assigned_full_name
    FROM work_issue_reports wir
    INNER JOIN users u ON wir.reporter_id = u.user_id
    LEFT JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id
    LEFT JOIN workplaces w ON wir.workplace_id = w.workplace_id
    INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id
    LEFT JOIN issue_report_items iri ON wir.issue_item_id = iri.item_id
    LEFT JOIN users assignee ON wir.assigned_user_id = assignee.user_id
    WHERE 1=1
  `;

  const params = [];

  if (filters.status) {
    query += ` AND wir.status = ?`;
    params.push(filters.status);
  }

  if (filters.category_type) {
    query += ` AND irc.category_type = ?`;
    params.push(filters.category_type);
  }

  if (filters.issue_category_id) {
    query += ` AND wir.issue_category_id = ?`;
    params.push(filters.issue_category_id);
  }

  if (filters.factory_category_id) {
    query += ` AND wir.factory_category_id = ?`;
    params.push(filters.factory_category_id);
  }

  if (filters.workplace_id) {
    query += ` AND wir.workplace_id = ?`;
    params.push(filters.workplace_id);
  }

  if (filters.reporter_id) {
    query += ` AND wir.reporter_id = ?`;
    params.push(filters.reporter_id);
  }

  if (filters.assigned_user_id) {
    query += ` AND wir.assigned_user_id = ?`;
    params.push(filters.assigned_user_id);
  }

  if (filters.start_date && filters.end_date) {
    query += ` AND DATE(wir.report_date) BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }

  if (filters.search) {
    query += ` AND (wir.additional_description LIKE ? OR iri.item_name LIKE ? OR wir.custom_location LIKE ?)`;
    const searchTerm = `%${filters.search}%`;
    params.push(searchTerm, searchTerm, searchTerm);
  }

  query += ` ORDER BY wir.report_date DESC, wir.report_id DESC`;

  if (filters.limit) {
    query += ` LIMIT ?`;
    params.push(parseInt(filters.limit));

    if (filters.offset) {
      query += ` OFFSET ?`;
      params.push(parseInt(filters.offset));
    }
  }

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

const getReportById = async (reportId) => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT
      wir.report_id, wir.reporter_id, wir.report_date,
      wir.factory_category_id, wir.workplace_id, wir.custom_location,
      wir.tbm_session_id, wir.visit_request_id,
      wir.issue_category_id, wir.issue_item_id, wir.additional_description,
      wir.photo_path1, wir.photo_path2, wir.photo_path3, wir.photo_path4, wir.photo_path5,
      wir.status, wir.assigned_department, wir.assigned_user_id, wir.assigned_at, wir.assigned_by,
      wir.resolution_notes, wir.resolution_photo_path1, wir.resolution_photo_path2,
      wir.resolved_at, wir.resolved_by,
      wir.modification_history,
      wir.created_at, wir.updated_at,
      u.username as reporter_name, u.name as reporter_full_name,
      wc.category_name as factory_name,
      w.workplace_name,
      irc.category_type, irc.category_name as issue_category_name,
      iri.item_name as issue_item_name, iri.severity,
      assignee.username as assigned_user_name, assignee.name as assigned_full_name,
      assigner.username as assigned_by_name,
      resolver.username as resolved_by_name
    FROM work_issue_reports wir
    INNER JOIN users u ON wir.reporter_id = u.user_id
    LEFT JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id
    LEFT JOIN workplaces w ON wir.workplace_id = w.workplace_id
    INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id
    LEFT JOIN issue_report_items iri ON wir.issue_item_id = iri.item_id
    LEFT JOIN users assignee ON wir.assigned_user_id = assignee.user_id
    LEFT JOIN users assigner ON wir.assigned_by = assigner.user_id
    LEFT JOIN users resolver ON wir.resolved_by = resolver.user_id
    WHERE wir.report_id = ?`,
    [reportId]
  );

  return rows[0];
};

const updateReport = async (reportId, reportData, userId) => {
  const db = await getDb();

  const [existing] = await db.query(
    `SELECT * FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (existing.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  const current = existing[0];

  const modifications = [];
  const now = new Date().toISOString();

  for (const key of Object.keys(reportData)) {
    if (current[key] !== reportData[key] && reportData[key] !== undefined) {
      modifications.push({
        field: key,
        old_value: current[key],
        new_value: reportData[key],
        modified_at: now,
        modified_by: userId
      });
    }
  }

  const existingHistory = current.modification_history ? JSON.parse(current.modification_history) : [];
  const newHistory = [...existingHistory, ...modifications];

  const {
    factory_category_id,
    workplace_id,
    custom_location,
    issue_category_id,
    issue_item_id,
    additional_description,
    photo_path1,
    photo_path2,
    photo_path3,
    photo_path4,
    photo_path5
  } = reportData;

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET factory_category_id = COALESCE(?, factory_category_id),
         workplace_id = COALESCE(?, workplace_id),
         custom_location = COALESCE(?, custom_location),
         issue_category_id = COALESCE(?, issue_category_id),
         issue_item_id = COALESCE(?, issue_item_id),
         additional_description = COALESCE(?, additional_description),
         photo_path1 = COALESCE(?, photo_path1),
         photo_path2 = COALESCE(?, photo_path2),
         photo_path3 = COALESCE(?, photo_path3),
         photo_path4 = COALESCE(?, photo_path4),
         photo_path5 = COALESCE(?, photo_path5),
         modification_history = ?,
         updated_at = NOW()
     WHERE report_id = ?`,
    [factory_category_id, workplace_id, custom_location,
     issue_category_id, issue_item_id, additional_description,
     photo_path1, photo_path2, photo_path3, photo_path4, photo_path5,
     JSON.stringify(newHistory), reportId]
  );

  return result;
};

const deleteReport = async (reportId) => {
  const db = await getDb();

  const [photos] = await db.query(
    `SELECT photo_path1, photo_path2, photo_path3, photo_path4, photo_path5,
            resolution_photo_path1, resolution_photo_path2
     FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  const [result] = await db.query(
    `DELETE FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  return { result, photos: photos[0] };
};

// ==================== 상태 관리 ====================

const receiveReport = async (reportId, userId) => {
  const db = await getDb();

  const [current] = await db.query(
    `SELECT status FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (current.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  if (current[0].status !== 'reported') {
    throw new Error('접수 대기 상태가 아닙니다.');
  }

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET status = 'received', updated_at = NOW()
     WHERE report_id = ?`,
    [reportId]
  );

  await db.query(
    `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by)
     VALUES (?, 'reported', 'received', ?)`,
    [reportId, userId]
  );

  return result;
};

const assignReport = async (reportId, assignData) => {
  const db = await getDb();
  const { assigned_department, assigned_user_id, assigned_by } = assignData;

  const [current] = await db.query(
    `SELECT status FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (current.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  const validStatuses = ['received', 'in_progress'];
  if (!validStatuses.includes(current[0].status)) {
    throw new Error('접수된 상태에서만 담당자 배정이 가능합니다.');
  }

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET assigned_department = ?, assigned_user_id = ?,
         assigned_at = NOW(), assigned_by = ?, updated_at = NOW()
     WHERE report_id = ?`,
    [assigned_department, assigned_user_id, assigned_by, reportId]
  );

  return result;
};

const startProcessing = async (reportId, userId) => {
  const db = await getDb();

  const [current] = await db.query(
    `SELECT status FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (current.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  if (current[0].status !== 'received') {
    throw new Error('접수된 상태에서만 처리를 시작할 수 있습니다.');
  }

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET status = 'in_progress', updated_at = NOW()
     WHERE report_id = ?`,
    [reportId]
  );

  await db.query(
    `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by)
     VALUES (?, 'received', 'in_progress', ?)`,
    [reportId, userId]
  );

  return result;
};

const completeReport = async (reportId, completionData) => {
  const db = await getDb();
  const { resolution_notes, resolution_photo_path1, resolution_photo_path2, resolved_by } = completionData;

  const [current] = await db.query(
    `SELECT status FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (current.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  if (current[0].status !== 'in_progress') {
    throw new Error('처리 중 상태에서만 완료할 수 있습니다.');
  }

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET status = 'completed', resolution_notes = ?,
         resolution_photo_path1 = ?, resolution_photo_path2 = ?,
         resolved_at = NOW(), resolved_by = ?, updated_at = NOW()
     WHERE report_id = ?`,
    [resolution_notes, resolution_photo_path1, resolution_photo_path2, resolved_by, reportId]
  );

  await db.query(
    `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by, change_reason)
     VALUES (?, 'in_progress', 'completed', ?, ?)`,
    [reportId, resolved_by, resolution_notes]
  );

  return result;
};

const closeReport = async (reportId, userId) => {
  const db = await getDb();

  const [current] = await db.query(
    `SELECT status FROM work_issue_reports WHERE report_id = ?`,
    [reportId]
  );

  if (current.length === 0) {
    throw new Error('신고를 찾을 수 없습니다.');
  }

  if (current[0].status !== 'completed') {
    throw new Error('완료된 상태에서만 종료할 수 있습니다.');
  }

  const [result] = await db.query(
    `UPDATE work_issue_reports
     SET status = 'closed', updated_at = NOW()
     WHERE report_id = ?`,
    [reportId]
  );

  await db.query(
    `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by)
     VALUES (?, 'completed', 'closed', ?)`,
    [reportId, userId]
  );

  return result;
};

const getStatusLogs = async (reportId) => {
  const db = await getDb();
  const [rows] = await db.query(
    `SELECT wisl.log_id, wisl.report_id, wisl.previous_status, wisl.new_status,
            wisl.changed_by, wisl.change_reason, wisl.changed_at,
            u.username as changed_by_name, u.name as changed_by_full_name
     FROM work_issue_status_logs wisl
     INNER JOIN users u ON wisl.changed_by = u.user_id
     WHERE wisl.report_id = ?
     ORDER BY wisl.changed_at ASC`,
    [reportId]
  );
  return rows;
};

// ==================== 통계 ====================

const getStatsSummary = async (filters = {}) => {
  const db = await getDb();

  let whereClause = '1=1';
  const params = [];

  if (filters.start_date && filters.end_date) {
    whereClause += ` AND DATE(report_date) BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }

  if (filters.factory_category_id) {
    whereClause += ` AND factory_category_id = ?`;
    params.push(filters.factory_category_id);
  }

  const [rows] = await db.query(
    `SELECT
      COUNT(*) as total,
      SUM(CASE WHEN status = 'reported' THEN 1 ELSE 0 END) as reported,
      SUM(CASE WHEN status = 'received' THEN 1 ELSE 0 END) as received,
      SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END) as in_progress,
      SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
      SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) as closed
     FROM work_issue_reports
     WHERE ${whereClause}`,
    params
  );

  return rows[0];
};

const getStatsByCategory = async (filters = {}) => {
  const db = await getDb();

  let whereClause = '1=1';
  const params = [];

  if (filters.start_date && filters.end_date) {
    whereClause += ` AND DATE(wir.report_date) BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }

  const [rows] = await db.query(
    `SELECT
      irc.category_type, irc.category_name,
      COUNT(*) as count
     FROM work_issue_reports wir
     INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id
     WHERE ${whereClause}
     GROUP BY irc.category_id
     ORDER BY irc.category_type, count DESC`,
    params
  );

  return rows;
};

const getStatsByWorkplace = async (filters = {}) => {
  const db = await getDb();

  let whereClause = 'wir.workplace_id IS NOT NULL';
  const params = [];

  if (filters.start_date && filters.end_date) {
    whereClause += ` AND DATE(wir.report_date) BETWEEN ? AND ?`;
    params.push(filters.start_date, filters.end_date);
  }

  if (filters.factory_category_id) {
    whereClause += ` AND wir.factory_category_id = ?`;
    params.push(filters.factory_category_id);
  }

  const [rows] = await db.query(
    `SELECT
      wir.factory_category_id, wc.category_name as factory_name,
      wir.workplace_id, w.workplace_name,
      COUNT(*) as count
     FROM work_issue_reports wir
     INNER JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id
     INNER JOIN workplaces w ON wir.workplace_id = w.workplace_id
     WHERE ${whereClause}
     GROUP BY wir.factory_category_id, wir.workplace_id
     ORDER BY count DESC`,
    params
  );

  return rows;
};

module.exports = {
  // 카테고리
  getAllCategories,
  getCategoriesByType,
  createCategory,
  updateCategory,
  deleteCategory,

  // 항목
  getItemsByCategory,
  getAllItems,
  createItem,
  updateItem,
  deleteItem,

  // 신고
  createReport,
  getAllReports,
  getReportById,
  updateReport,
  deleteReport,

  // 상태 관리
  receiveReport,
  assignReport,
  startProcessing,
  completeReport,
  closeReport,
  getStatusLogs,

  // 통계
  getStatsSummary,
  getStatsByCategory,
  getStatsByWorkplace
};
