import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { query } from "../database/db";
import { logger } from "../utils/logger";

// ============================================
// 금형 마스터 CRUD
// ============================================

export async function getMoldList(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { mold_code, mold_name, mold_type, operation_status } = req.query;

    const conditions: string[] = [];
    const params: any[] = [];
    let paramIndex = 1;

    if (companyCode === "*") {
      // 최고 관리자: 전체 조회
    } else {
      conditions.push(`company_code = $${paramIndex}`);
      params.push(companyCode);
      paramIndex++;
    }

    if (mold_code) {
      conditions.push(`mold_code ILIKE $${paramIndex}`);
      params.push(`%${mold_code}%`);
      paramIndex++;
    }
    if (mold_name) {
      conditions.push(`mold_name ILIKE $${paramIndex}`);
      params.push(`%${mold_name}%`);
      paramIndex++;
    }
    if (mold_type) {
      conditions.push(`mold_type = $${paramIndex}`);
      params.push(mold_type);
      paramIndex++;
    }
    if (operation_status) {
      conditions.push(`operation_status = $${paramIndex}`);
      params.push(operation_status);
      paramIndex++;
    }

    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
    const sql = `SELECT * FROM mold_mng ${whereClause} ORDER BY created_date DESC`;
    const result = await query(sql, params);

    logger.info("금형 목록 조회", { companyCode, count: result.length });
    res.json({ success: true, data: result });
  } catch (error: any) {
    logger.error("금형 목록 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function getMoldDetail(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    let sql: string;
    let params: any[];

    if (companyCode === "*") {
      sql = `SELECT * FROM mold_mng WHERE mold_code = $1 LIMIT 1`;
      params = [moldCode];
    } else {
      sql = `SELECT * FROM mold_mng WHERE mold_code = $1 AND company_code = $2 LIMIT 1`;
      params = [moldCode, companyCode];
    }

    const result = await query(sql, params);
    if (result.length === 0) {
      res.status(404).json({ success: false, message: "금형을 찾을 수 없습니다." });
      return;
    }

    res.json({ success: true, data: result[0] });
  } catch (error: any) {
    logger.error("금형 상세 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createMold(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const {
      mold_code, mold_name, mold_type, category, manufacturer,
      manufacturing_number, manufacturing_date, cavity_count,
      shot_count, mold_quantity, base_input_qty, operation_status,
      remarks, image_path, memo,
    } = req.body;

    if (!mold_code || !mold_name) {
      res.status(400).json({ success: false, message: "금형코드와 금형명은 필수입니다." });
      return;
    }

    const sql = `
      INSERT INTO mold_mng (
        company_code, mold_code, mold_name, mold_type, category,
        manufacturer, manufacturing_number, manufacturing_date,
        cavity_count, shot_count, mold_quantity, base_input_qty,
        operation_status, remarks, image_path, memo, writer
      ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)
      RETURNING *
    `;
    const params = [
      companyCode, mold_code, mold_name, mold_type || null, category || null,
      manufacturer || null, manufacturing_number || null, manufacturing_date || null,
      cavity_count || 0, shot_count || 0, mold_quantity || 1, base_input_qty || 0,
      operation_status || "ACTIVE", remarks || null, image_path || null, memo || null, userId,
    ];

    const result = await query(sql, params);
    logger.info("금형 생성", { companyCode, moldCode: mold_code });
    res.json({ success: true, data: result[0], message: "금형이 등록되었습니다." });
  } catch (error: any) {
    if (error.code === "23505") {
      res.status(409).json({ success: false, message: "이미 존재하는 금형코드입니다." });
      return;
    }
    logger.error("금형 생성 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function updateMold(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;
    const {
      mold_name, mold_type, category, manufacturer,
      manufacturing_number, manufacturing_date, cavity_count,
      shot_count, mold_quantity, base_input_qty, operation_status,
      remarks, image_path, memo,
    } = req.body;

    const sql = `
      UPDATE mold_mng SET
        mold_name = COALESCE($1, mold_name),
        mold_type = $2, category = $3, manufacturer = $4,
        manufacturing_number = $5, manufacturing_date = $6,
        cavity_count = COALESCE($7, cavity_count),
        shot_count = COALESCE($8, shot_count),
        mold_quantity = COALESCE($9, mold_quantity),
        base_input_qty = COALESCE($10, base_input_qty),
        operation_status = COALESCE($11, operation_status),
        remarks = $12, image_path = $13, memo = $14,
        updated_date = NOW()
      WHERE mold_code = $15 AND company_code = $16
      RETURNING *
    `;
    const params = [
      mold_name, mold_type, category, manufacturer,
      manufacturing_number, manufacturing_date,
      cavity_count, shot_count, mold_quantity, base_input_qty,
      operation_status, remarks, image_path, memo,
      moldCode, companyCode,
    ];

    const result = await query(sql, params);
    if (result.length === 0) {
      res.status(404).json({ success: false, message: "금형을 찾을 수 없습니다." });
      return;
    }

    logger.info("금형 수정", { companyCode, moldCode });
    res.json({ success: true, data: result[0], message: "금형이 수정되었습니다." });
  } catch (error: any) {
    logger.error("금형 수정 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deleteMold(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    // 관련 데이터 먼저 삭제
    await query(`DELETE FROM mold_serial WHERE mold_code = $1 AND company_code = $2`, [moldCode, companyCode]);
    await query(`DELETE FROM mold_inspection_item WHERE mold_code = $1 AND company_code = $2`, [moldCode, companyCode]);
    await query(`DELETE FROM mold_part WHERE mold_code = $1 AND company_code = $2`, [moldCode, companyCode]);

    const result = await query(
      `DELETE FROM mold_mng WHERE mold_code = $1 AND company_code = $2 RETURNING id`,
      [moldCode, companyCode]
    );

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

    logger.info("금형 삭제", { companyCode, moldCode });
    res.json({ success: true, message: "금형이 삭제되었습니다." });
  } catch (error: any) {
    logger.error("금형 삭제 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

// ============================================
// 일련번호 CRUD
// ============================================

export async function getMoldSerials(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    const sql = `SELECT * FROM mold_serial WHERE mold_code = $1 AND company_code = $2 ORDER BY serial_number`;
    const result = await query(sql, [moldCode, companyCode]);

    res.json({ success: true, data: result });
  } catch (error: any) {
    logger.error("일련번호 목록 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createMoldSerial(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const { moldCode } = req.params;
    const { serial_number, status, progress, work_description, manager, completion_date, remarks } = req.body;

    let finalSerialNumber = serial_number;

    // 일련번호가 비어있으면 채번 규칙으로 자동 생성
    if (!finalSerialNumber) {
      try {
        const { numberingRuleService } = await import("../services/numberingRuleService");
        const rule = await numberingRuleService.getNumberingRuleByColumn(
          companyCode,
          "mold_serial",
          "serial_number"
        );

        if (rule) {
          // formData에 mold_code를 포함 (reference 파트에서 참조)
          const formData = { mold_code: moldCode, ...req.body };
          finalSerialNumber = await numberingRuleService.allocateCode(
            rule.ruleId,
            companyCode,
            formData
          );
          logger.info("일련번호 자동 채번 완료", { serialNumber: finalSerialNumber, ruleId: rule.ruleId });
        }
      } catch (numError: any) {
        logger.error("일련번호 자동 채번 실패", { error: numError.message });
      }
    }

    if (!finalSerialNumber) {
      res.status(400).json({ success: false, message: "일련번호를 생성할 수 없습니다. 채번 규칙을 확인해주세요." });
      return;
    }

    const sql = `
      INSERT INTO mold_serial (company_code, mold_code, serial_number, status, progress, work_description, manager, completion_date, remarks, writer)
      VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
      RETURNING *
    `;
    const params = [
      companyCode, moldCode, finalSerialNumber, status || "STORED",
      progress || 0, work_description || null, manager || null,
      completion_date || null, remarks || null, userId,
    ];

    const result = await query(sql, params);
    res.json({ success: true, data: result[0], message: "일련번호가 등록되었습니다." });
  } catch (error: any) {
    if (error.code === "23505") {
      res.status(409).json({ success: false, message: "이미 존재하는 일련번호입니다." });
      return;
    }
    logger.error("일련번호 생성 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deleteMoldSerial(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;

    const result = await query(
      `DELETE FROM mold_serial WHERE id = $1 AND company_code = $2 RETURNING id`,
      [id, companyCode]
    );

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

    res.json({ success: true, message: "일련번호가 삭제되었습니다." });
  } catch (error: any) {
    logger.error("일련번호 삭제 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

// ============================================
// 점검항목 CRUD
// ============================================

export async function getMoldInspections(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    const sql = `SELECT * FROM mold_inspection_item WHERE mold_code = $1 AND company_code = $2 ORDER BY created_date`;
    const result = await query(sql, [moldCode, companyCode]);

    res.json({ success: true, data: result });
  } catch (error: any) {
    logger.error("점검항목 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createMoldInspection(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const { moldCode } = req.params;
    const {
      inspection_item, inspection_cycle, inspection_method,
      inspection_content, lower_limit, upper_limit, unit,
      is_active, checklist, remarks,
    } = req.body;

    if (!inspection_item) {
      res.status(400).json({ success: false, message: "점검항목명은 필수입니다." });
      return;
    }

    const sql = `
      INSERT INTO mold_inspection_item (
        company_code, mold_code, inspection_item, inspection_cycle,
        inspection_method, inspection_content, lower_limit, upper_limit,
        unit, is_active, checklist, remarks, writer
      ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
      RETURNING *
    `;
    const params = [
      companyCode, moldCode, inspection_item, inspection_cycle || null,
      inspection_method || null, inspection_content || null,
      lower_limit || null, upper_limit || null, unit || null,
      is_active || "Y", checklist || null, remarks || null, userId,
    ];

    const result = await query(sql, params);
    res.json({ success: true, data: result[0], message: "점검항목이 등록되었습니다." });
  } catch (error: any) {
    logger.error("점검항목 생성 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deleteMoldInspection(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;

    const result = await query(
      `DELETE FROM mold_inspection_item WHERE id = $1 AND company_code = $2 RETURNING id`,
      [id, companyCode]
    );

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

    res.json({ success: true, message: "점검항목이 삭제되었습니다." });
  } catch (error: any) {
    logger.error("점검항목 삭제 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

// ============================================
// 부품 CRUD
// ============================================

export async function getMoldParts(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    const sql = `SELECT * FROM mold_part WHERE mold_code = $1 AND company_code = $2 ORDER BY created_date`;
    const result = await query(sql, [moldCode, companyCode]);

    res.json({ success: true, data: result });
  } catch (error: any) {
    logger.error("부품 목록 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createMoldPart(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const { moldCode } = req.params;
    const {
      part_name, replacement_cycle, unit, specification,
      manufacturer, manufacturer_code, image_path, remarks,
    } = req.body;

    if (!part_name) {
      res.status(400).json({ success: false, message: "부품명은 필수입니다." });
      return;
    }

    const sql = `
      INSERT INTO mold_part (
        company_code, mold_code, part_name, replacement_cycle,
        unit, specification, manufacturer, manufacturer_code,
        image_path, remarks, writer
      ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
      RETURNING *
    `;
    const params = [
      companyCode, moldCode, part_name, replacement_cycle || null,
      unit || null, specification || null, manufacturer || null,
      manufacturer_code || null, image_path || null, remarks || null, userId,
    ];

    const result = await query(sql, params);
    res.json({ success: true, data: result[0], message: "부품이 등록되었습니다." });
  } catch (error: any) {
    logger.error("부품 생성 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deleteMoldPart(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;

    const result = await query(
      `DELETE FROM mold_part WHERE id = $1 AND company_code = $2 RETURNING id`,
      [id, companyCode]
    );

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

    res.json({ success: true, message: "부품이 삭제되었습니다." });
  } catch (error: any) {
    logger.error("부품 삭제 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}

// ============================================
// 일련번호 현황 집계
// ============================================

export async function getMoldSerialSummary(req: AuthenticatedRequest, res: Response): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { moldCode } = req.params;

    const sql = `
      SELECT
        COUNT(*) as total,
        COUNT(*) FILTER (WHERE status = 'IN_USE') as in_use,
        COUNT(*) FILTER (WHERE status = 'REPAIR') as repair,
        COUNT(*) FILTER (WHERE status = 'STORED') as stored,
        COUNT(*) FILTER (WHERE status = 'DISPOSED') as disposed
      FROM mold_serial
      WHERE mold_code = $1 AND company_code = $2
    `;
    const result = await query(sql, [moldCode, companyCode]);

    res.json({ success: true, data: result[0] });
  } catch (error: any) {
    logger.error("일련번호 현황 조회 오류", error);
    res.status(500).json({ success: false, message: error.message });
  }
}
