import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { query, queryOne, transaction } from "../database/db";

// ============================================================
// 결재 정의 (Approval Definitions) CRUD
// ============================================================

export class ApprovalDefinitionController {
  // 결재 유형 목록 조회
  static async getDefinitions(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { is_active, search } = req.query;

      const conditions: string[] = ["company_code = $1"];
      const params: any[] = [companyCode];
      let idx = 2;

      if (is_active) {
        conditions.push(`is_active = $${idx}`);
        params.push(is_active);
        idx++;
      }

      if (search) {
        conditions.push(`(definition_name ILIKE $${idx} OR definition_name_eng ILIKE $${idx})`);
        params.push(`%${search}%`);
        idx++;
      }

      const rows = await query<any>(
        `SELECT * FROM approval_definitions WHERE ${conditions.join(" AND ")} ORDER BY definition_id ASC`,
        params
      );

      return res.json({ success: true, data: rows });
    } catch (error) {
      console.error("결재 유형 목록 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 유형 목록 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 유형 상세 조회
  static async getDefinition(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const row = await queryOne<any>(
        "SELECT * FROM approval_definitions WHERE definition_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!row) {
        return res.status(404).json({ success: false, message: "결재 유형을 찾을 수 없습니다." });
      }

      return res.json({ success: true, data: row });
    } catch (error) {
      console.error("결재 유형 상세 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 유형 상세 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 유형 생성
  static async createDefinition(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const {
        definition_name,
        definition_name_eng,
        description,
        default_template_id,
        max_steps = 5,
        allow_self_approval = false,
        allow_cancel = true,
        is_active = "Y",
      } = req.body;

      if (!definition_name) {
        return res.status(400).json({ success: false, message: "결재 유형명은 필수입니다." });
      }

      const userId = req.user?.userId || "system";
      const [row] = await query<any>(
        `INSERT INTO approval_definitions (
          definition_name, definition_name_eng, description, default_template_id,
          max_steps, allow_self_approval, allow_cancel, is_active,
          company_code, created_by, updated_by
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $10)
        RETURNING *`,
        [
          definition_name, definition_name_eng, description, default_template_id,
          max_steps, allow_self_approval, allow_cancel, is_active,
          companyCode, userId,
        ]
      );

      return res.status(201).json({ success: true, data: row, message: "결재 유형이 생성되었습니다." });
    } catch (error) {
      console.error("결재 유형 생성 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 유형 생성 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 유형 수정
  static async updateDefinition(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const existing = await queryOne<any>(
        "SELECT definition_id FROM approval_definitions WHERE definition_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!existing) {
        return res.status(404).json({ success: false, message: "결재 유형을 찾을 수 없습니다." });
      }

      const {
        definition_name, definition_name_eng, description, default_template_id,
        max_steps, allow_self_approval, allow_cancel, is_active,
      } = req.body;

      const fields: string[] = [];
      const params: any[] = [];
      let idx = 1;

      if (definition_name !== undefined) { fields.push(`definition_name = $${idx++}`); params.push(definition_name); }
      if (definition_name_eng !== undefined) { fields.push(`definition_name_eng = $${idx++}`); params.push(definition_name_eng); }
      if (description !== undefined) { fields.push(`description = $${idx++}`); params.push(description); }
      if (default_template_id !== undefined) { fields.push(`default_template_id = $${idx++}`); params.push(default_template_id); }
      if (max_steps !== undefined) { fields.push(`max_steps = $${idx++}`); params.push(max_steps); }
      if (allow_self_approval !== undefined) { fields.push(`allow_self_approval = $${idx++}`); params.push(allow_self_approval); }
      if (allow_cancel !== undefined) { fields.push(`allow_cancel = $${idx++}`); params.push(allow_cancel); }
      if (is_active !== undefined) { fields.push(`is_active = $${idx++}`); params.push(is_active); }

      fields.push(`updated_by = $${idx++}`, `updated_at = NOW()`);
      params.push(req.user?.userId || "system");
      params.push(id, companyCode);

      const [row] = await query<any>(
        `UPDATE approval_definitions SET ${fields.join(", ")}
         WHERE definition_id = $${idx++} AND company_code = $${idx++} RETURNING *`,
        params
      );

      return res.json({ success: true, data: row, message: "결재 유형이 수정되었습니다." });
    } catch (error) {
      console.error("결재 유형 수정 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 유형 수정 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 유형 삭제
  static async deleteDefinition(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const existing = await queryOne<any>(
        "SELECT definition_id FROM approval_definitions WHERE definition_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!existing) {
        return res.status(404).json({ success: false, message: "결재 유형을 찾을 수 없습니다." });
      }

      await query<any>(
        "DELETE FROM approval_definitions WHERE definition_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      return res.json({ success: true, message: "결재 유형이 삭제되었습니다." });
    } catch (error) {
      console.error("결재 유형 삭제 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 유형 삭제 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }
}

// ============================================================
// 결재선 템플릿 (Approval Line Templates) CRUD
// ============================================================

export class ApprovalTemplateController {
  // 템플릿 목록 조회
  static async getTemplates(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { definition_id, is_active } = req.query;

      const conditions: string[] = ["t.company_code = $1"];
      const params: any[] = [companyCode];
      let idx = 2;

      if (definition_id) {
        conditions.push(`t.definition_id = $${idx++}`);
        params.push(definition_id);
      }
      if (is_active) {
        conditions.push(`t.is_active = $${idx++}`);
        params.push(is_active);
      }

      const rows = await query<any>(
        `SELECT t.*, d.definition_name
         FROM approval_line_templates t
         LEFT JOIN approval_definitions d ON t.definition_id = d.definition_id AND t.company_code = d.company_code
         WHERE ${conditions.join(" AND ")}
         ORDER BY t.template_id ASC`,
        params
      );

      return res.json({ success: true, data: rows });
    } catch (error) {
      console.error("결재선 템플릿 목록 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재선 템플릿 목록 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 템플릿 상세 조회 (단계 포함)
  static async getTemplate(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const template = await queryOne<any>(
        `SELECT t.*, d.definition_name
         FROM approval_line_templates t
         LEFT JOIN approval_definitions d ON t.definition_id = d.definition_id AND t.company_code = d.company_code
         WHERE t.template_id = $1 AND t.company_code = $2`,
        [id, companyCode]
      );

      if (!template) {
        return res.status(404).json({ success: false, message: "결재선 템플릿을 찾을 수 없습니다." });
      }

      const steps = await query<any>(
        "SELECT * FROM approval_line_template_steps WHERE template_id = $1 AND company_code = $2 ORDER BY step_order ASC",
        [id, companyCode]
      );

      return res.json({ success: true, data: { ...template, steps } });
    } catch (error) {
      console.error("결재선 템플릿 상세 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재선 템플릿 상세 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 템플릿 생성 (단계 포함 트랜잭션)
  static async createTemplate(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { template_name, description, definition_id, is_active = "Y", steps = [] } = req.body;

      if (!template_name) {
        return res.status(400).json({ success: false, message: "템플릿명은 필수입니다." });
      }

      const userId = req.user?.userId || "system";

      let result: any;
      await transaction(async (client) => {
        const { rows } = await client.query(
          `INSERT INTO approval_line_templates (template_name, description, definition_id, is_active, company_code, created_by, updated_by)
           VALUES ($1, $2, $3, $4, $5, $6, $6) RETURNING *`,
          [template_name, description, definition_id, is_active, companyCode, userId]
        );
        result = rows[0];

        // 단계 일괄 삽입
        if (Array.isArray(steps) && steps.length > 0) {
          for (const step of steps) {
            await client.query(
              `INSERT INTO approval_line_template_steps
               (template_id, step_order, approver_type, approver_user_id, approver_position, approver_dept_code, approver_label, company_code)
               VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
              [
                result.template_id,
                step.step_order,
                step.approver_type || "user",
                step.approver_user_id || null,
                step.approver_position || null,
                step.approver_dept_code || null,
                step.approver_label || null,
                companyCode,
              ]
            );
          }
        }
      });

      return res.status(201).json({ success: true, data: result, message: "결재선 템플릿이 생성되었습니다." });
    } catch (error) {
      console.error("결재선 템플릿 생성 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재선 템플릿 생성 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 템플릿 수정
  static async updateTemplate(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const existing = await queryOne<any>(
        "SELECT template_id FROM approval_line_templates WHERE template_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!existing) {
        return res.status(404).json({ success: false, message: "결재선 템플릿을 찾을 수 없습니다." });
      }

      const { template_name, description, definition_id, is_active, steps } = req.body;
      const userId = req.user?.userId || "system";

      let result: any;
      await transaction(async (client) => {
        const fields: string[] = [];
        const params: any[] = [];
        let idx = 1;

        if (template_name !== undefined) { fields.push(`template_name = $${idx++}`); params.push(template_name); }
        if (description !== undefined) { fields.push(`description = $${idx++}`); params.push(description); }
        if (definition_id !== undefined) { fields.push(`definition_id = $${idx++}`); params.push(definition_id); }
        if (is_active !== undefined) { fields.push(`is_active = $${idx++}`); params.push(is_active); }
        fields.push(`updated_by = $${idx++}`, `updated_at = NOW()`);
        params.push(userId, id, companyCode);

        const { rows } = await client.query(
          `UPDATE approval_line_templates SET ${fields.join(", ")}
           WHERE template_id = $${idx++} AND company_code = $${idx++} RETURNING *`,
          params
        );
        result = rows[0];

        // 단계 재등록 (steps 배열이 주어진 경우 전체 교체)
        if (Array.isArray(steps)) {
          await client.query(
            "DELETE FROM approval_line_template_steps WHERE template_id = $1 AND company_code = $2",
            [id, companyCode]
          );
          for (const step of steps) {
            await client.query(
              `INSERT INTO approval_line_template_steps
               (template_id, step_order, approver_type, approver_user_id, approver_position, approver_dept_code, approver_label, company_code)
               VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
              [id, step.step_order, step.approver_type || "user", step.approver_user_id || null,
               step.approver_position || null, step.approver_dept_code || null, step.approver_label || null, companyCode]
            );
          }
        }
      });

      return res.json({ success: true, data: result, message: "결재선 템플릿이 수정되었습니다." });
    } catch (error) {
      console.error("결재선 템플릿 수정 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재선 템플릿 수정 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 템플릿 삭제
  static async deleteTemplate(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const existing = await queryOne<any>(
        "SELECT template_id FROM approval_line_templates WHERE template_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!existing) {
        return res.status(404).json({ success: false, message: "결재선 템플릿을 찾을 수 없습니다." });
      }

      await query<any>(
        "DELETE FROM approval_line_templates WHERE template_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      return res.json({ success: true, message: "결재선 템플릿이 삭제되었습니다." });
    } catch (error) {
      console.error("결재선 템플릿 삭제 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재선 템플릿 삭제 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }
}

// ============================================================
// 결재 요청 (Approval Requests) CRUD
// ============================================================

export class ApprovalRequestController {
  // 결재 요청 목록 조회
  static async getRequests(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      const userId = req.user?.userId;
      if (!companyCode || !userId) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { status, target_table, target_record_id, requester_id, my_approvals, page = "1", limit = "20" } = req.query;

      const conditions: string[] = ["r.company_code = $1"];
      const params: any[] = [companyCode];
      let idx = 2;

      if (status) {
        conditions.push(`r.status = $${idx++}`);
        params.push(status);
      }
      if (target_table) {
        conditions.push(`r.target_table = $${idx++}`);
        params.push(target_table);
      }
      if (target_record_id) {
        conditions.push(`r.target_record_id = $${idx++}`);
        params.push(target_record_id);
      }
      if (requester_id) {
        conditions.push(`r.requester_id = $${idx++}`);
        params.push(requester_id);
      }

      // 내 결재 대기 목록: 현재 사용자가 결재자인 라인만 조회
      if (my_approvals === "true") {
        conditions.push(
          `EXISTS (SELECT 1 FROM approval_lines l WHERE l.request_id = r.request_id AND l.approver_id = $${idx++} AND l.status = 'pending' AND l.company_code = r.company_code)`
        );
        params.push(userId);
      }

      const offset = (parseInt(page as string) - 1) * parseInt(limit as string);
      params.push(parseInt(limit as string), offset);

      const rows = await query<any>(
        `SELECT r.*, d.definition_name
         FROM approval_requests r
         LEFT JOIN approval_definitions d ON r.definition_id = d.definition_id AND r.company_code = d.company_code
         WHERE ${conditions.join(" AND ")}
         ORDER BY r.created_at DESC
         LIMIT $${idx++} OFFSET $${idx++}`,
        params
      );

      // 전체 건수 조회
      const countParams = params.slice(0, params.length - 2);
      const [countRow] = await query<any>(
        `SELECT COUNT(*) as total FROM approval_requests r
         WHERE ${conditions.join(" AND ")}`,
        countParams
      );

      return res.json({
        success: true,
        data: rows,
        total: parseInt(countRow?.total || "0"),
        page: parseInt(page as string),
        limit: parseInt(limit as string),
      });
    } catch (error) {
      console.error("결재 요청 목록 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 요청 목록 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 요청 상세 조회 (라인 포함)
  static async getRequest(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const request = await queryOne<any>(
        `SELECT r.*, d.definition_name
         FROM approval_requests r
         LEFT JOIN approval_definitions d ON r.definition_id = d.definition_id AND r.company_code = d.company_code
         WHERE r.request_id = $1 AND r.company_code = $2`,
        [id, companyCode]
      );

      if (!request) {
        return res.status(404).json({ success: false, message: "결재 요청을 찾을 수 없습니다." });
      }

      const lines = await query<any>(
        "SELECT * FROM approval_lines WHERE request_id = $1 AND company_code = $2 ORDER BY step_order ASC",
        [id, companyCode]
      );

      return res.json({ success: true, data: { ...request, lines } });
    } catch (error) {
      console.error("결재 요청 상세 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 요청 상세 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 요청 생성 (결재 라인 자동 생성)
  static async createRequest(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      if (!companyCode) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const {
        title, description, definition_id, target_table, target_record_id,
        target_record_data, screen_id, button_component_id,
        approvers, // [{ approver_id, approver_name, approver_position, approver_dept, approver_label }]
        approval_mode, // "sequential" | "parallel"
      } = req.body;

      if (!title || !target_table) {
        return res.status(400).json({ success: false, message: "제목과 대상 테이블은 필수입니다." });
      }

      if (!Array.isArray(approvers) || approvers.length === 0) {
        return res.status(400).json({ success: false, message: "결재자를 1명 이상 지정해야 합니다." });
      }

      const userId = req.user?.userId || "system";
      const userName = req.user?.userName || "";
      const deptName = req.user?.deptName || "";

      const isParallel = approval_mode === "parallel";
      const totalSteps = approvers.length;

      // approval_mode를 target_record_data에 병합 저장
      const mergedRecordData = {
        ...(target_record_data || {}),
        approval_mode: approval_mode || "sequential",
      };

      let result: any;
      await transaction(async (client) => {
        // 결재 요청 생성
        const { rows: reqRows } = await client.query(
          `INSERT INTO approval_requests (
            title, description, definition_id, target_table, target_record_id,
            target_record_data, status, current_step, total_steps,
            requester_id, requester_name, requester_dept,
            screen_id, button_component_id, company_code
          ) VALUES ($1, $2, $3, $4, $5, $6, 'requested', 1, $7, $8, $9, $10, $11, $12, $13)
          RETURNING *`,
          [
            title, description, definition_id, target_table, target_record_id || null,
            JSON.stringify(mergedRecordData),
            totalSteps,
            userId, userName, deptName,
            screen_id, button_component_id, companyCode,
          ]
        );
        result = reqRows[0];

        // 결재 라인 생성
        // 동시결재: 모든 결재자 pending (step_order는 고유값) / 다단결재: 첫 번째만 pending
        for (let i = 0; i < approvers.length; i++) {
          const approver = approvers[i];
          const lineStatus = isParallel ? "pending" : (i === 0 ? "pending" : "waiting");

          await client.query(
            `INSERT INTO approval_lines (
              request_id, step_order, approver_id, approver_name, approver_position,
              approver_dept, approver_label, status, company_code
            ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
            [
              result.request_id,
              i + 1,
              approver.approver_id,
              approver.approver_name || null,
              approver.approver_position || null,
              approver.approver_dept || null,
              approver.approver_label || (isParallel ? "동시 결재" : `${i + 1}차 결재`),
              lineStatus,
              companyCode,
            ]
          );
        }

        // 상태를 in_progress로 업데이트
        await client.query(
          "UPDATE approval_requests SET status = 'in_progress' WHERE request_id = $1",
          [result.request_id]
        );
        result.status = "in_progress";
      });

      return res.status(201).json({ success: true, data: result, message: "결재 요청이 생성되었습니다." });
    } catch (error) {
      console.error("결재 요청 생성 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 요청 생성 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 결재 요청 회수 (cancel)
  static async cancelRequest(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      const userId = req.user?.userId;
      if (!companyCode || !userId) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { id } = req.params;
      const request = await queryOne<any>(
        "SELECT * FROM approval_requests WHERE request_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      if (!request) {
        return res.status(404).json({ success: false, message: "결재 요청을 찾을 수 없습니다." });
      }

      if (request.requester_id !== userId) {
        return res.status(403).json({ success: false, message: "본인이 요청한 건만 회수할 수 있습니다." });
      }

      if (!["requested", "in_progress"].includes(request.status)) {
        return res.status(400).json({ success: false, message: "이미 처리된 결재 요청은 회수할 수 없습니다." });
      }

      await query<any>(
        "UPDATE approval_requests SET status = 'cancelled', updated_at = NOW() WHERE request_id = $1 AND company_code = $2",
        [id, companyCode]
      );

      return res.json({ success: true, message: "결재 요청이 회수되었습니다." });
    } catch (error) {
      console.error("결재 요청 회수 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 요청 회수 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }
}

// ============================================================
// 결재 라인 처리 (Approval Lines - 승인/반려)
// ============================================================

export class ApprovalLineController {
  // 결재 처리 (승인/반려)
  static async processApproval(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      const userId = req.user?.userId;
      if (!companyCode || !userId) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const { lineId } = req.params;
      const { action, comment } = req.body; // action: 'approved' | 'rejected'

      if (!["approved", "rejected"].includes(action)) {
        return res.status(400).json({ success: false, message: "액션은 approved 또는 rejected여야 합니다." });
      }

      const line = await queryOne<any>(
        "SELECT * FROM approval_lines WHERE line_id = $1 AND company_code = $2",
        [lineId, companyCode]
      );

      if (!line) {
        return res.status(404).json({ success: false, message: "결재 라인을 찾을 수 없습니다." });
      }

      if (line.approver_id !== userId) {
        return res.status(403).json({ success: false, message: "본인이 결재자로 지정된 건만 처리할 수 있습니다." });
      }

      if (line.status !== "pending") {
        return res.status(400).json({ success: false, message: "대기 중인 결재만 처리할 수 있습니다." });
      }

      await transaction(async (client) => {
        // 현재 라인 처리
        await client.query(
          `UPDATE approval_lines SET status = $1, comment = $2, processed_at = NOW()
           WHERE line_id = $3`,
          [action, comment || null, lineId]
        );

        const { rows: reqRows } = await client.query(
          "SELECT * FROM approval_requests WHERE request_id = $1 AND company_code = $2",
          [line.request_id, companyCode]
        );
        const request = reqRows[0];

        if (!request) return;

        if (action === "rejected") {
          // 반려: 전체 요청 반려 처리
          await client.query(
            `UPDATE approval_requests SET status = 'rejected', final_approver_id = $1, final_comment = $2,
             completed_at = NOW(), updated_at = NOW()
             WHERE request_id = $3`,
            [userId, comment || null, line.request_id]
          );
          // 남은 pending/waiting 라인도 skipped 처리
          await client.query(
            `UPDATE approval_lines SET status = 'skipped'
             WHERE request_id = $1 AND status IN ('pending', 'waiting') AND line_id != $2`,
            [line.request_id, lineId]
          );
        } else {
          // 승인: 동시결재 vs 다단결재 분기
          const recordData = request.target_record_data;
          const isParallelMode = recordData?.approval_mode === "parallel";

          if (isParallelMode) {
            // 동시결재: 남은 pending 라인이 있는지 확인
            const { rows: remainingLines } = await client.query(
              `SELECT COUNT(*) as cnt FROM approval_lines
               WHERE request_id = $1 AND status = 'pending' AND line_id != $2 AND company_code = $3`,
              [line.request_id, lineId, companyCode]
            );
            const remaining = parseInt(remainingLines[0]?.cnt || "0");

            if (remaining === 0) {
              // 모든 동시 결재자 승인 완료 → 최종 승인
              await client.query(
                `UPDATE approval_requests SET status = 'approved', final_approver_id = $1, final_comment = $2,
                 completed_at = NOW(), updated_at = NOW()
                 WHERE request_id = $3`,
                [userId, comment || null, line.request_id]
              );
            }
            // 아직 남은 결재자 있으면 대기 (상태 변경 없음)
          } else {
            // 다단결재: 다음 단계 활성화 또는 최종 완료
            const nextStep = line.step_order + 1;

            if (nextStep <= request.total_steps) {
              await client.query(
                `UPDATE approval_lines SET status = 'pending'
                 WHERE request_id = $1 AND step_order = $2 AND company_code = $3`,
                [line.request_id, nextStep, companyCode]
              );
              await client.query(
                `UPDATE approval_requests SET current_step = $1, updated_at = NOW() WHERE request_id = $2`,
                [nextStep, line.request_id]
              );
            } else {
              await client.query(
                `UPDATE approval_requests SET status = 'approved', final_approver_id = $1, final_comment = $2,
                 completed_at = NOW(), updated_at = NOW()
                 WHERE request_id = $3`,
                [userId, comment || null, line.request_id]
              );
            }
          }
        }
      });

      return res.json({ success: true, message: action === "approved" ? "승인 처리되었습니다." : "반려 처리되었습니다." });
    } catch (error) {
      console.error("결재 처리 오류:", error);
      return res.status(500).json({
        success: false,
        message: "결재 처리 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }

  // 내 결재 대기 목록 조회
  static async getMyPendingLines(req: AuthenticatedRequest, res: Response) {
    try {
      const companyCode = req.user?.companyCode;
      const userId = req.user?.userId;
      if (!companyCode || !userId) {
        return res.status(401).json({ success: false, message: "인증 정보가 없습니다." });
      }

      const rows = await query<any>(
        `SELECT l.*, r.title, r.target_table, r.target_record_id, r.requester_name, r.requester_dept, r.created_at as request_created_at
         FROM approval_lines l
         JOIN approval_requests r ON l.request_id = r.request_id AND l.company_code = r.company_code
         WHERE l.approver_id = $1 AND l.status = 'pending' AND l.company_code = $2
         ORDER BY r.created_at ASC`,
        [userId, companyCode]
      );

      return res.json({ success: true, data: rows });
    } catch (error) {
      console.error("내 결재 대기 목록 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "내 결재 대기 목록 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "알 수 없는 오류",
      });
    }
  }
}
