/**
 * ERP 마스터 동기화 컨트롤러
 *
 *  POST /api/erp-sync/employees      { coCd, companyCode? }
 *  POST /api/erp-sync/departments    { coCd, companyCode?, searchText? }
 *  POST /api/erp-sync/warehouses     { coCd, companyCode?, baselocFg? }
 *  POST /api/erp-sync/customers      { coCd, companyCode? }
 *  POST /api/erp-sync/account-codes  { coCd, companyCode? }
 *  POST /api/erp-sync/all            { coCd, companyCode? }   ← 전체 일괄
 *
 *  외부 시스템(타시스템)이 호출하면 외부 ERP에서 데이터를 가져와 내부 DB에 INSERT/UPDATE 합니다.
 *  자동화 관리 > 배치 관리 화면의 "ERP 동기화" 버튼이 동일 엔드포인트를 호출합니다.
 */
import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { logger } from "../utils/logger";
import {
  syncEmployees,
  syncDepartments,
  syncWarehouses,
  syncCustomers,
  syncAccountCodes,
  syncAll,
  SyncResult,
} from "../services/erpSyncService";
import { auditLogService, getClientIp } from "../services/auditLogService";

function resolveCompanyCode(req: AuthenticatedRequest): string {
  const fromBody = (req.body?.companyCode || req.body?.company_code || "").toString().trim();
  if (fromBody) return fromBody;
  const fromUser = req.user?.companyCode;
  if (fromUser && fromUser !== "*") return fromUser;
  // 단독 운영 회사 기본값
  return process.env.DEFAULT_COMPANY_CODE || "COMPANY_16";
}

function audit(req: AuthenticatedRequest, resource: string, summary: string, result: SyncResult | SyncResult[]) {
  try {
    auditLogService.log({
      companyCode: req.user?.companyCode || "",
      userId: req.user?.userId || "system",
      userName: req.user?.userName || "system",
      action: "BATCH_UPDATE",
      resourceType: "DATA",
      resourceId: resource,
      resourceName: resource,
      tableName: resource,
      summary,
      changes: { after: result } as any,
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });
  } catch (e) {
    // 감사 로그 실패는 동기화 결과에 영향 없음
  }
}

export async function syncEmployeesHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] employees 시작", { coCd, companyCode });
  const result = await syncEmployees(coCd, companyCode, executedBy);
  audit(req, "user_info", `사원 동기화: ${result.inserted}건 신규, ${result.updated}건 갱신`, result);
  res.json({ success: result.errors.length === 0, data: result });
}

export async function syncDepartmentsHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const searchText = (req.body?.searchText || "").toString().trim() || undefined;
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] departments 시작", { coCd, companyCode });
  const result = await syncDepartments(coCd, companyCode, searchText, executedBy);
  audit(req, "dept_info", `부서 동기화: ${result.inserted}건 신규, ${result.updated}건 갱신`, result);
  res.json({ success: result.errors.length === 0, data: result });
}

export async function syncWarehousesHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const baselocFg = (req.body?.baselocFg || "").toString().trim() || undefined;
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] warehouses 시작", { coCd, companyCode });
  const result = await syncWarehouses(coCd, companyCode, baselocFg, executedBy);
  audit(req, "warehouse_info", `창고 동기화: ${result.inserted}건 신규, ${result.updated}건 갱신`, result);
  res.json({ success: result.errors.length === 0, data: result });
}

export async function syncCustomersHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] customers 시작", { coCd, companyCode });
  const result = await syncCustomers(coCd, companyCode, executedBy);
  audit(req, "customer_mng", `거래처 동기화: ${result.inserted}건 신규, ${result.updated}건 갱신`, result);
  res.json({ success: result.errors.length === 0, data: result });
}

export async function syncAccountCodesHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] accountCodes 시작", { coCd, companyCode });
  const result = await syncAccountCodes(coCd, companyCode, executedBy);
  audit(req, "account_code_info", `계정과목 동기화: ${result.inserted}건 신규, ${result.updated}건 갱신`, result);
  res.json({ success: result.errors.length === 0, data: result });
}

export async function syncAllHandler(req: AuthenticatedRequest, res: Response): Promise<void> {
  const coCd = (req.body?.coCd || req.body?.co_cd || "").toString().trim();
  if (!coCd) {
    res.status(400).json({ success: false, message: "회사코드(coCd)는 필수입니다." });
    return;
  }
  const companyCode = resolveCompanyCode(req);
  const executedBy = req.user?.userId || "system";
  logger.info("[erpSync] ALL 시작", { coCd, companyCode });
  const results = await syncAll(coCd, companyCode, executedBy);
  const totals = results.reduce(
    (acc, r) => {
      acc.fetched += r.fetched;
      acc.inserted += r.inserted;
      acc.updated += r.updated;
      acc.skipped += r.skipped;
      acc.errorsCount += r.errors.length;
      return acc;
    },
    { fetched: 0, inserted: 0, updated: 0, skipped: 0, errorsCount: 0 }
  );
  audit(req, "ALL", `전체 동기화: 신규 ${totals.inserted}건 / 갱신 ${totals.updated}건`, results);
  const success = results.every((r) => r.errors.length === 0);
  res.json({ success, totals, data: results });
}
