import { Response } from "express";
import { logger } from "../utils/logger";
import { AuthenticatedRequest } from "../types/auth";
import { ApiResponse } from "../types/common";
import { query, queryOne } from "../database/db";
import { auditLogService, getClientIp } from "../services/auditLogService";

/**
 * 부서 목록 조회 (회사별)
 */
export async function getDepartments(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { companyCode } = req.params;
    const userCompanyCode = req.user?.companyCode;

    logger.info("부서 목록 조회", { companyCode, userCompanyCode });

    // 최고 관리자가 아니면 자신의 회사만 조회 가능
    if (userCompanyCode !== "*" && userCompanyCode !== companyCode) {
      res.status(403).json({
        success: false,
        message: "해당 회사의 부서를 조회할 권한이 없습니다.",
      });
      return;
    }

    // 부서 목록 조회 (부서원 수 포함)
    const departments = await query<any>(`
      SELECT 
        d.dept_code,
        d.dept_name,
        d.company_code,
        d.parent_dept_code,
        COUNT(DISTINCT ud.user_id) as member_count
      FROM dept_info d
      LEFT JOIN user_dept ud ON d.dept_code = ud.dept_code
      WHERE d.company_code = $1
      GROUP BY d.dept_code, d.dept_name, d.company_code, d.parent_dept_code
      ORDER BY d.dept_name
    `, [companyCode]);

    // 응답 형식 변환
    const formattedDepartments = departments.map((dept) => ({
      dept_code: dept.dept_code,
      dept_name: dept.dept_name,
      company_code: dept.company_code,
      parent_dept_code: dept.parent_dept_code,
      memberCount: parseInt(dept.member_count || "0"),
    }));

    res.status(200).json({
      success: true,
      data: formattedDepartments,
    });
  } catch (error) {
    logger.error("부서 목록 조회 실패", error);
    res.status(500).json({
      success: false,
      message: "부서 목록 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서 상세 조회
 */
export async function getDepartment(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode } = req.params;

    const department = await queryOne<any>(`
      SELECT 
        dept_code,
        dept_name,
        company_code,
        parent_dept_code
      FROM dept_info
      WHERE dept_code = $1
    `, [deptCode]);

    if (!department) {
      res.status(404).json({
        success: false,
        message: "부서를 찾을 수 없습니다.",
      });
      return;
    }

    res.status(200).json({
      success: true,
      data: department,
    });
  } catch (error) {
    logger.error("부서 상세 조회 실패", error);
    res.status(500).json({
      success: false,
      message: "부서 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서 생성
 */
export async function createDepartment(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { companyCode } = req.params;
    const { dept_name, parent_dept_code } = req.body;

    if (!dept_name || !dept_name.trim()) {
      res.status(400).json({
        success: false,
        message: "부서명을 입력해주세요.",
      });
      return;
    }

    // 같은 회사 내 중복 부서명 확인
    const duplicate = await queryOne<any>(`
      SELECT dept_code, dept_name
      FROM dept_info
      WHERE company_code = $1 AND dept_name = $2
    `, [companyCode, dept_name.trim()]);

    if (duplicate) {
      res.status(409).json({
        success: false,
        message: `"${dept_name}" 부서가 이미 존재합니다.`,
        isDuplicate: true,
      });
      return;
    }

    // 회사 이름 조회
    const company = await queryOne<any>(`
      SELECT company_name FROM company_mng WHERE company_code = $1
    `, [companyCode]);

    const companyName = company?.company_name || companyCode;

    // 부서 코드 생성 (전역 카운트: DEPT_1, DEPT_2, ...)
    const codeResult = await queryOne<any>(`
      SELECT COALESCE(MAX(CAST(SUBSTRING(dept_code FROM 6) AS INTEGER)), 0) + 1 as next_number
      FROM dept_info 
      WHERE dept_code ~ '^DEPT_[0-9]+$'
    `);

    const nextNumber = codeResult?.next_number || 1;
    const deptCode = `DEPT_${nextNumber}`;

    // 부서 생성
    const result = await query<any>(`
      INSERT INTO dept_info (
        dept_code,
        dept_name,
        company_code,
        company_name,
        parent_dept_code,
        status,
        regdate
      ) VALUES ($1, $2, $3, $4, $5, $6, NOW())
      RETURNING *
    `, [
      deptCode,
      dept_name.trim(),
      companyCode,
      companyName,
      parent_dept_code || null,
      'active',
    ]);

    logger.info("부서 생성 성공", { deptCode, dept_name });

    auditLogService.log({
      companyCode: companyCode || req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "CREATE",
      resourceType: "DATA",
      resourceId: deptCode,
      resourceName: dept_name.trim(),
      tableName: "dept_info",
      summary: `부서 "${dept_name.trim()}" 생성`,
      changes: { after: { deptCode, deptName: dept_name.trim(), parentDeptCode: parent_dept_code } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(201).json({
      success: true,
      message: "부서가 생성되었습니다.",
      data: result[0],
    });
  } catch (error) {
    logger.error("부서 생성 실패", error);
    res.status(500).json({
      success: false,
      message: "부서 생성 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서 수정
 */
export async function updateDepartment(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode } = req.params;
    const { dept_name, parent_dept_code } = req.body;

    if (!dept_name || !dept_name.trim()) {
      res.status(400).json({
        success: false,
        message: "부서명을 입력해주세요.",
      });
      return;
    }

    const result = await query<any>(`
      UPDATE dept_info
      SET 
        dept_name = $1,
        parent_dept_code = $2
      WHERE dept_code = $3
      RETURNING *
    `, [dept_name.trim(), parent_dept_code || null, deptCode]);

    if (result.length === 0) {
      res.status(404).json({
        success: false,
        message: "부서를 찾을 수 없습니다.",
      });
      return;
    }

    logger.info("부서 수정 성공", { deptCode });

    auditLogService.log({
      companyCode: req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "UPDATE",
      resourceType: "DATA",
      resourceId: deptCode,
      resourceName: dept_name.trim(),
      tableName: "dept_info",
      summary: `부서 "${dept_name.trim()}" 수정`,
      changes: { after: { deptName: dept_name.trim(), parentDeptCode: parent_dept_code } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(200).json({
      success: true,
      message: "부서가 수정되었습니다.",
      data: result[0],
    });
  } catch (error) {
    logger.error("부서 수정 실패", error);
    res.status(500).json({
      success: false,
      message: "부서 수정 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서 삭제
 */
export async function deleteDepartment(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode } = req.params;

    // 하위 부서 확인
    const hasChildren = await queryOne<any>(`
      SELECT COUNT(*) as count
      FROM dept_info
      WHERE parent_dept_code = $1
    `, [deptCode]);

    if (parseInt(hasChildren?.count || "0") > 0) {
      res.status(400).json({
        success: false,
        message: "하위 부서가 있는 부서는 삭제할 수 없습니다. 먼저 하위 부서를 삭제해주세요.",
      });
      return;
    }

    // 부서원 삭제 (부서 삭제 전에 먼저 삭제)
    const deletedMembers = await query<any>(`
      DELETE FROM user_dept
      WHERE dept_code = $1
      RETURNING user_id
    `, [deptCode]);

    const memberCount = deletedMembers.length;

    // 부서 삭제
    const result = await query<any>(`
      DELETE FROM dept_info
      WHERE dept_code = $1
      RETURNING dept_code, dept_name
    `, [deptCode]);

    if (result.length === 0) {
      res.status(404).json({
        success: false,
        message: "부서를 찾을 수 없습니다.",
      });
      return;
    }

    logger.info("부서 삭제 성공", { 
      deptCode, 
      deptName: result[0].dept_name,
      deletedMemberCount: memberCount 
    });

    auditLogService.log({
      companyCode: req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "DELETE",
      resourceType: "DATA",
      resourceId: deptCode,
      resourceName: result[0].dept_name,
      tableName: "dept_info",
      summary: `부서 "${result[0].dept_name}" 삭제${memberCount > 0 ? ` (부서원 ${memberCount}명 제외)` : ""}`,
      changes: { before: { deptCode, deptName: result[0].dept_name } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(200).json({
      success: true,
      message: memberCount > 0 
        ? `부서가 삭제되었습니다. (부서원 ${memberCount}명 제외됨)` 
        : "부서가 삭제되었습니다.",
    });
  } catch (error) {
    logger.error("부서 삭제 실패", error);
    res.status(500).json({
      success: false,
      message: "부서 삭제 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서원 목록 조회
 */
export async function getDepartmentMembers(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode } = req.params;

    const members = await query<any>(`
      SELECT 
        u.user_id,
        u.user_name,
        u.email,
        u.tel as phone,
        u.cell_phone,
        u.position_name,
        ud.dept_code,
        d.dept_name,
        ud.is_primary
      FROM user_dept ud
      JOIN user_info u ON ud.user_id = u.user_id
      JOIN dept_info d ON ud.dept_code = d.dept_code
      WHERE ud.dept_code = $1
      ORDER BY ud.is_primary DESC, u.user_name
    `, [deptCode]);

    res.status(200).json({
      success: true,
      data: members,
    });
  } catch (error) {
    logger.error("부서원 목록 조회 실패", error);
    res.status(500).json({
      success: false,
      message: "부서원 목록 조회 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 사용자 검색 (부서원 추가용)
 */
export async function searchUsers(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { companyCode } = req.params;
    const { search } = req.query;

    if (!search || typeof search !== 'string') {
      res.status(400).json({
        success: false,
        message: "검색어를 입력해주세요.",
      });
      return;
    }

    // 사용자 검색 (ID 또는 이름)
    const users = await query<any>(`
      SELECT 
        user_id,
        user_name,
        email,
        position_name,
        company_code
      FROM user_info
      WHERE company_code = $1
        AND (
          user_id ILIKE $2 OR 
          user_name ILIKE $2
        )
      ORDER BY user_name
      LIMIT 20
    `, [companyCode, `%${search}%`]);

    res.status(200).json({
      success: true,
      data: users,
    });
  } catch (error) {
    logger.error("사용자 검색 실패", error);
    res.status(500).json({
      success: false,
      message: "사용자 검색 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서원 추가
 */
export async function addDepartmentMember(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode } = req.params;
    const { user_id } = req.body;

    if (!user_id) {
      res.status(400).json({
        success: false,
        message: "사용자 ID를 입력해주세요.",
      });
      return;
    }

    // 사용자 존재 확인
    const user = await queryOne<any>(`
      SELECT user_id, user_name
      FROM user_info
      WHERE user_id = $1
    `, [user_id]);

    if (!user) {
      res.status(404).json({
        success: false,
        message: "사용자를 찾을 수 없습니다.",
      });
      return;
    }

    // 이미 부서원인지 확인
    const existing = await queryOne<any>(`
      SELECT *
      FROM user_dept
      WHERE user_id = $1 AND dept_code = $2
    `, [user_id, deptCode]);

    if (existing) {
      res.status(409).json({
        success: false,
        message: "이미 해당 부서의 부서원입니다.",
        isDuplicate: true,
      });
      return;
    }

    // 주 부서가 있는지 확인
    const hasPrimary = await queryOne<any>(`
      SELECT *
      FROM user_dept
      WHERE user_id = $1 AND is_primary = true
    `, [user_id]);

    // 부서원 추가
    await query<any>(`
      INSERT INTO user_dept (user_id, dept_code, is_primary, created_at)
      VALUES ($1, $2, $3, NOW())
    `, [user_id, deptCode, !hasPrimary]);

    logger.info("부서원 추가 성공", { user_id, deptCode });

    res.status(201).json({
      success: true,
      message: "부서원이 추가되었습니다.",
    });
  } catch (error) {
    logger.error("부서원 추가 실패", error);
    res.status(500).json({
      success: false,
      message: "부서원 추가 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 부서원 제거
 */
export async function removeDepartmentMember(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode, userId } = req.params;

    const result = await query<any>(`
      DELETE FROM user_dept
      WHERE user_id = $1 AND dept_code = $2
      RETURNING *
    `, [userId, deptCode]);

    if (result.length === 0) {
      res.status(404).json({
        success: false,
        message: "해당 부서원을 찾을 수 없습니다.",
      });
      return;
    }

    logger.info("부서원 제거 성공", { userId, deptCode });

    res.status(200).json({
      success: true,
      message: "부서원이 제거되었습니다.",
    });
  } catch (error) {
    logger.error("부서원 제거 실패", error);
    res.status(500).json({
      success: false,
      message: "부서원 제거 중 오류가 발생했습니다.",
    });
  }
}

/**
 * 주 부서 설정
 */
export async function setPrimaryDepartment(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const { deptCode, userId } = req.params;

    // 다른 부서의 주 부서 해제
    await query<any>(`
      UPDATE user_dept
      SET is_primary = false
      WHERE user_id = $1
    `, [userId]);

    // 해당 부서를 주 부서로 설정
    await query<any>(`
      UPDATE user_dept
      SET is_primary = true
      WHERE user_id = $1 AND dept_code = $2
    `, [userId, deptCode]);

    logger.info("주 부서 설정 성공", { userId, deptCode });

    res.status(200).json({
      success: true,
      message: "주 부서가 설정되었습니다.",
    });
  } catch (error) {
    logger.error("주 부서 설정 실패", error);
    res.status(500).json({
      success: false,
      message: "주 부서 설정 중 오류가 발생했습니다.",
    });
  }
}

