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

// ──────────────────────────────────────────────
// 포장단위 (pkg_unit) CRUD
// ──────────────────────────────────────────────

export async function getPkgUnits(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();

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

    if (companyCode === "*") {
      sql = `SELECT * FROM pkg_unit ORDER BY company_code, created_date DESC`;
      params = [];
    } else {
      sql = `SELECT * FROM pkg_unit WHERE company_code = $1 ORDER BY created_date DESC`;
      params = [companyCode];
    }

    const result = await pool.query(sql, params);
    logger.info("포장단위 목록 조회", { companyCode, count: result.rowCount });
    res.json({ success: true, data: result.rows });
  } catch (error: any) {
    logger.error("포장단위 목록 조회 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createPkgUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();
    const {
      pkg_code, pkg_name, pkg_type, status,
      width_mm, length_mm, height_mm,
      self_weight_kg, max_load_kg, volume_l, remarks,
    } = req.body;

    if (!pkg_code || !pkg_name) {
      res.status(400).json({ success: false, message: "포장코드와 포장명은 필수입니다." });
      return;
    }

    const dup = await pool.query(
      `SELECT id FROM pkg_unit WHERE pkg_code = $1 AND company_code = $2`,
      [pkg_code, companyCode]
    );
    if (dup.rowCount && dup.rowCount > 0) {
      res.status(409).json({ success: false, message: "이미 존재하는 포장코드입니다." });
      return;
    }

    const result = await pool.query(
      `INSERT INTO pkg_unit
        (company_code, pkg_code, pkg_name, pkg_type, status,
         width_mm, length_mm, height_mm, self_weight_kg, max_load_kg, volume_l, remarks, writer)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
       RETURNING *`,
      [companyCode, pkg_code, pkg_name, pkg_type, status || "ACTIVE",
       width_mm, length_mm, height_mm, self_weight_kg, max_load_kg, volume_l, remarks,
       req.user!.userId]
    );

    logger.info("포장단위 등록", { companyCode, pkg_code });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("포장단위 등록 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function updatePkgUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;
    const pool = getPool();
    const {
      pkg_name, pkg_type, status,
      width_mm, length_mm, height_mm,
      self_weight_kg, max_load_kg, volume_l, remarks,
    } = req.body;

    const result = await pool.query(
      `UPDATE pkg_unit SET
        pkg_name=$1, pkg_type=$2, status=$3,
        width_mm=$4, length_mm=$5, height_mm=$6,
        self_weight_kg=$7, max_load_kg=$8, volume_l=$9, remarks=$10,
        updated_date=NOW(), writer=$11
       WHERE id=$12 AND company_code=$13
       RETURNING *`,
      [pkg_name, pkg_type, status,
       width_mm, length_mm, height_mm,
       self_weight_kg, max_load_kg, volume_l, remarks,
       req.user!.userId, id, companyCode]
    );

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

    logger.info("포장단위 수정", { companyCode, id });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("포장단위 수정 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deletePkgUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  const pool = getPool();
  const client = await pool.connect();
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;

    await client.query("BEGIN");
    await client.query(
      `DELETE FROM pkg_unit_item WHERE pkg_code = (SELECT pkg_code FROM pkg_unit WHERE id=$1 AND company_code=$2) AND company_code=$2`,
      [id, companyCode]
    );
    const result = await client.query(
      `DELETE FROM pkg_unit WHERE id=$1 AND company_code=$2 RETURNING id`,
      [id, companyCode]
    );
    await client.query("COMMIT");

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

    logger.info("포장단위 삭제", { companyCode, id });
    res.json({ success: true });
  } catch (error: any) {
    await client.query("ROLLBACK");
    logger.error("포장단위 삭제 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  } finally {
    client.release();
  }
}

// ──────────────────────────────────────────────
// 포장단위 매칭품목 (pkg_unit_item) CRUD
// ──────────────────────────────────────────────

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

    const result = await pool.query(
      `SELECT * FROM pkg_unit_item WHERE pkg_code=$1 AND company_code=$2 ORDER BY created_date DESC`,
      [pkgCode, companyCode]
    );

    res.json({ success: true, data: result.rows });
  } catch (error: any) {
    logger.error("매칭품목 조회 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createPkgUnitItem(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();
    const { pkg_code, item_number, pkg_qty } = req.body;

    if (!pkg_code || !item_number) {
      res.status(400).json({ success: false, message: "포장코드와 품번은 필수입니다." });
      return;
    }

    const result = await pool.query(
      `INSERT INTO pkg_unit_item (company_code, pkg_code, item_number, pkg_qty, writer)
       VALUES ($1,$2,$3,$4,$5)
       RETURNING *`,
      [companyCode, pkg_code, item_number, pkg_qty, req.user!.userId]
    );

    logger.info("매칭품목 추가", { companyCode, pkg_code, item_number });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("매칭품목 추가 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

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

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

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

    logger.info("매칭품목 삭제", { companyCode, id });
    res.json({ success: true });
  } catch (error: any) {
    logger.error("매칭품목 삭제 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

// ──────────────────────────────────────────────
// 적재함 (loading_unit) CRUD
// ──────────────────────────────────────────────

export async function getLoadingUnits(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();

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

    if (companyCode === "*") {
      sql = `SELECT * FROM loading_unit ORDER BY company_code, created_date DESC`;
      params = [];
    } else {
      sql = `SELECT * FROM loading_unit WHERE company_code = $1 ORDER BY created_date DESC`;
      params = [companyCode];
    }

    const result = await pool.query(sql, params);
    logger.info("적재함 목록 조회", { companyCode, count: result.rowCount });
    res.json({ success: true, data: result.rows });
  } catch (error: any) {
    logger.error("적재함 목록 조회 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createLoadingUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();
    const {
      loading_code, loading_name, loading_type, status,
      width_mm, length_mm, height_mm,
      self_weight_kg, max_load_kg, max_stack, remarks,
    } = req.body;

    if (!loading_code || !loading_name) {
      res.status(400).json({ success: false, message: "적재함코드와 적재함명은 필수입니다." });
      return;
    }

    const dup = await pool.query(
      `SELECT id FROM loading_unit WHERE loading_code=$1 AND company_code=$2`,
      [loading_code, companyCode]
    );
    if (dup.rowCount && dup.rowCount > 0) {
      res.status(409).json({ success: false, message: "이미 존재하는 적재함코드입니다." });
      return;
    }

    const result = await pool.query(
      `INSERT INTO loading_unit
        (company_code, loading_code, loading_name, loading_type, status,
         width_mm, length_mm, height_mm, self_weight_kg, max_load_kg, max_stack, remarks, writer)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
       RETURNING *`,
      [companyCode, loading_code, loading_name, loading_type, status || "ACTIVE",
       width_mm, length_mm, height_mm, self_weight_kg, max_load_kg, max_stack, remarks,
       req.user!.userId]
    );

    logger.info("적재함 등록", { companyCode, loading_code });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("적재함 등록 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function updateLoadingUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;
    const pool = getPool();
    const {
      loading_name, loading_type, status,
      width_mm, length_mm, height_mm,
      self_weight_kg, max_load_kg, max_stack, remarks,
    } = req.body;

    const result = await pool.query(
      `UPDATE loading_unit SET
        loading_name=$1, loading_type=$2, status=$3,
        width_mm=$4, length_mm=$5, height_mm=$6,
        self_weight_kg=$7, max_load_kg=$8, max_stack=$9, remarks=$10,
        updated_date=NOW(), writer=$11
       WHERE id=$12 AND company_code=$13
       RETURNING *`,
      [loading_name, loading_type, status,
       width_mm, length_mm, height_mm,
       self_weight_kg, max_load_kg, max_stack, remarks,
       req.user!.userId, id, companyCode]
    );

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

    logger.info("적재함 수정", { companyCode, id });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("적재함 수정 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function deleteLoadingUnit(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  const pool = getPool();
  const client = await pool.connect();
  try {
    const companyCode = req.user!.companyCode;
    const { id } = req.params;

    await client.query("BEGIN");
    await client.query(
      `DELETE FROM loading_unit_pkg WHERE loading_code = (SELECT loading_code FROM loading_unit WHERE id=$1 AND company_code=$2) AND company_code=$2`,
      [id, companyCode]
    );
    const result = await client.query(
      `DELETE FROM loading_unit WHERE id=$1 AND company_code=$2 RETURNING id`,
      [id, companyCode]
    );
    await client.query("COMMIT");

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

    logger.info("적재함 삭제", { companyCode, id });
    res.json({ success: true });
  } catch (error: any) {
    await client.query("ROLLBACK");
    logger.error("적재함 삭제 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  } finally {
    client.release();
  }
}

// ──────────────────────────────────────────────
// 적재함 포장구성 (loading_unit_pkg) CRUD
// ──────────────────────────────────────────────

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

    const result = await pool.query(
      `SELECT * FROM loading_unit_pkg WHERE loading_code=$1 AND company_code=$2 ORDER BY created_date DESC`,
      [loadingCode, companyCode]
    );

    res.json({ success: true, data: result.rows });
  } catch (error: any) {
    logger.error("적재구성 조회 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

export async function createLoadingUnitPkg(
  req: AuthenticatedRequest,
  res: Response
): Promise<void> {
  try {
    const companyCode = req.user!.companyCode;
    const pool = getPool();
    const { loading_code, pkg_code, max_load_qty, load_method } = req.body;

    if (!loading_code || !pkg_code) {
      res.status(400).json({ success: false, message: "적재함코드와 포장코드는 필수입니다." });
      return;
    }

    const result = await pool.query(
      `INSERT INTO loading_unit_pkg (company_code, loading_code, pkg_code, max_load_qty, load_method, writer)
       VALUES ($1,$2,$3,$4,$5,$6)
       RETURNING *`,
      [companyCode, loading_code, pkg_code, max_load_qty, load_method, req.user!.userId]
    );

    logger.info("적재구성 추가", { companyCode, loading_code, pkg_code });
    res.json({ success: true, data: result.rows[0] });
  } catch (error: any) {
    logger.error("적재구성 추가 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}

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

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

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

    logger.info("적재구성 삭제", { companyCode, id });
    res.json({ success: true });
  } catch (error: any) {
    logger.error("적재구성 삭제 실패", { error: error.message });
    res.status(500).json({ success: false, message: error.message });
  }
}
