/**
 * 입고 관리 서버 액션
 *
 * API Endpoints:
 * - GET /api/v1/receivings - 목록 조회
 * - GET /api/v1/receivings/stats - 통계 조회
 * - GET /api/v1/receivings/{id} - 상세 조회
 * - POST /api/v1/receivings - 등록
 * - PUT /api/v1/receivings/{id} - 수정
 * - DELETE /api/v1/receivings/{id} - 삭제
 * - POST /api/v1/receivings/{id}/process - 입고처리
 */

'use server';

// ===== 목데이터 모드 플래그 =====
const USE_MOCK_DATA = false;


import { serverFetch } from '@/lib/api/fetch-wrapper';
import { buildApiUrl } from '@/lib/api/query-params';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { executeServerAction } from '@/lib/api/execute-server-action';
import { executePaginatedAction } from '@/lib/api/execute-paginated-action';
import { getTodayString, formatDate } from '@/lib/utils/date';

import type {
  ReceivingItem,
  ReceivingDetail,
  ReceivingStats,
  ReceivingStatus,
  ReceivingProcessFormData,
} from './types';

// ===== 목데이터 =====
const MOCK_RECEIVING_LIST: ReceivingItem[] = [
  {
    id: '1',
    materialNo: 'MAT-001',
    lotNo: 'LOT-2026-001',
    itemId: 101,
    inspectionStatus: '적',
    inspectionResult: '합격',
    inspectionDate: '2026-01-25',
    supplier: '(주)대한철강',
    manufacturer: '포스코',
    itemCode: 'STEEL-001',
    itemType: '원자재',
    itemName: 'SUS304 스테인리스 판재',
    specification: '1000x2000x3T',
    unit: 'EA',
    receivingQty: 100,
    receivingDate: '2026-01-26',
    createdBy: '김철수',
    status: 'completed',
  },
  {
    id: '2',
    materialNo: 'MAT-002',
    lotNo: 'LOT-2026-002',
    itemId: 102,
    inspectionStatus: '적',
    inspectionResult: '합격',
    inspectionDate: '2026-01-26',
    supplier: '삼성전자부품',
    manufacturer: '삼성전자',
    itemCode: 'ELEC-002',
    itemType: '부품',
    itemName: 'MCU 컨트롤러 IC',
    specification: 'STM32F103C8T6',
    unit: 'EA',
    receivingQty: 500,
    receivingDate: '2026-01-27',
    createdBy: '이영희',
    status: 'completed',
  },
  {
    id: '3',
    materialNo: 'MAT-003',
    lotNo: 'LOT-2026-003',
    itemId: 103,
    inspectionStatus: '-',
    inspectionResult: undefined,
    inspectionDate: undefined,
    supplier: '한국플라스틱',
    manufacturer: '한국플라스틱',
    itemCode: 'PLAS-003',
    itemType: '부자재',
    itemName: 'ABS 사출 케이스',
    specification: '150x100x50',
    unit: 'SET',
    receivingQty: undefined,
    receivingDate: undefined,
    createdBy: '박민수',
    status: 'receiving_pending',
  },
  {
    id: '4',
    materialNo: 'MAT-004',
    lotNo: 'LOT-2026-004',
    itemId: 104,
    inspectionStatus: '부적',
    inspectionResult: '불합격',
    inspectionDate: '2026-01-27',
    supplier: '(주)대한철강',
    manufacturer: '포스코',
    itemCode: 'STEEL-002',
    itemType: '원자재',
    itemName: '알루미늄 프로파일',
    specification: '40x40x2000L',
    unit: 'EA',
    receivingQty: 50,
    receivingDate: '2026-01-28',
    createdBy: '김철수',
    status: 'inspection_pending',
  },
  {
    id: '5',
    materialNo: 'MAT-005',
    lotNo: 'LOT-2026-005',
    itemId: 105,
    inspectionStatus: '-',
    inspectionResult: undefined,
    inspectionDate: undefined,
    supplier: '글로벌전자',
    manufacturer: '글로벌전자',
    itemCode: 'ELEC-005',
    itemType: '부품',
    itemName: 'DC 모터 24V',
    specification: '24V 100RPM',
    unit: 'EA',
    receivingQty: undefined,
    receivingDate: undefined,
    createdBy: '최지훈',
    status: 'receiving_pending',
  },
  {
    id: '6',
    materialNo: 'MAT-006',
    lotNo: 'LOT-2026-006',
    itemId: undefined, // 품목 미연결 → 수입검사 대상 아님
    inspectionStatus: '-',
    inspectionResult: undefined,
    inspectionDate: undefined,
    supplier: '동양화학',
    manufacturer: '동양화학',
    itemCode: 'CHEM-001',
    itemType: '부자재',
    itemName: '에폭시 접착제',
    specification: '500ml',
    unit: 'EA',
    receivingQty: 200,
    receivingDate: '2026-01-25',
    createdBy: '이영희',
    status: 'completed',
  },
  {
    id: '7',
    materialNo: 'MAT-007',
    lotNo: 'LOT-2026-007',
    itemId: 107,
    inspectionStatus: '적',
    inspectionResult: '합격',
    inspectionDate: '2026-01-28',
    supplier: '삼성전자부품',
    manufacturer: '삼성전자',
    itemCode: 'ELEC-007',
    itemType: '부품',
    itemName: '커패시터 100uF',
    specification: '100uF 50V',
    unit: 'EA',
    receivingQty: 1000,
    receivingDate: '2026-01-28',
    createdBy: '박민수',
    status: 'completed',
  },
  {
    id: '8',
    materialNo: 'MAT-008',
    lotNo: 'LOT-2026-008',
    itemId: undefined, // 품목 미연결 → 수입검사 대상 아님
    inspectionStatus: '-',
    inspectionResult: undefined,
    inspectionDate: undefined,
    supplier: '한국볼트',
    manufacturer: '한국볼트',
    itemCode: 'BOLT-001',
    itemType: '부품',
    itemName: 'SUS 볼트 M8x30',
    specification: 'M8x30 SUS304',
    unit: 'EA',
    receivingQty: undefined,
    receivingDate: undefined,
    createdBy: '김철수',
    status: 'receiving_pending',
  },
];

const MOCK_RECEIVING_STATS: ReceivingStats = {
  receivingPendingCount: 3,
  receivingCompletedCount: 4,
  inspectionPendingCount: 1,
  inspectionCompletedCount: 5,
};

// 기획서 2026-02-03 기준 상세 목데이터
const MOCK_RECEIVING_DETAIL: Record<string, ReceivingDetail> = {
  '1': {
    id: '1',
    materialNo: 'MAT-001',
    lotNo: 'LOT-2026-001',
    itemCode: 'STEEL-001',
    itemName: 'SUS304 스테인리스 판재',
    specification: '1000x2000x3T',
    unit: 'EA',
    supplier: '(주)대한철강',
    manufacturer: '포스코',
    receivingQty: 100,
    receivingDate: '2026-01-26',
    createdBy: '김철수',
    status: 'completed',
    remark: '',
    inspectionDate: '2026-01-25',
    inspectionResult: '합격',
    certificateFile: undefined,
    inventoryAdjustments: [
      { id: 'adj-1', adjustmentDate: '2026-01-05', quantity: 10, inspector: '홍길동' },
      { id: 'adj-2', adjustmentDate: '2026-01-05', quantity: 5, inspector: '홍길동' },
      { id: 'adj-3', adjustmentDate: '2026-01-05', quantity: -15, inspector: '홍길동' },
      { id: 'adj-4', adjustmentDate: '2026-01-05', quantity: 5, inspector: '홍길동' },
    ],
    orderNo: 'PO-2026-001',
    orderUnit: 'EA',
  },
  '2': {
    id: '2',
    materialNo: 'MAT-002',
    lotNo: 'LOT-2026-002',
    itemCode: 'ELEC-002',
    itemName: 'MCU 컨트롤러 IC',
    specification: 'STM32F103C8T6',
    unit: 'EA',
    supplier: '삼성전자부품',
    manufacturer: '삼성전자',
    receivingQty: 500,
    receivingDate: '2026-01-27',
    createdBy: '이영희',
    status: 'completed',
    remark: '긴급 입고',
    inspectionDate: '2026-01-26',
    inspectionResult: '합격',
    inventoryAdjustments: [],
    orderNo: 'PO-2026-002',
    orderUnit: 'EA',
  },
  '3': {
    id: '3',
    materialNo: 'MAT-003',
    lotNo: 'LOT-2026-003',
    itemCode: 'PLAS-003',
    itemName: 'ABS 사출 케이스',
    specification: '150x100x50',
    unit: 'SET',
    supplier: '한국플라스틱',
    manufacturer: '한국플라스틱',
    receivingQty: undefined,
    receivingDate: undefined,
    createdBy: '박민수',
    status: 'receiving_pending',
    remark: '',
    inspectionDate: undefined,
    inspectionResult: undefined,
    inventoryAdjustments: [],
    orderNo: 'PO-2026-003',
    orderUnit: 'SET',
  },
  '4': {
    id: '4',
    materialNo: 'MAT-004',
    lotNo: 'LOT-2026-004',
    itemCode: 'STEEL-002',
    itemName: '알루미늄 프로파일',
    specification: '40x40x2000L',
    unit: 'EA',
    supplier: '(주)대한철강',
    manufacturer: '포스코',
    receivingQty: 50,
    receivingDate: '2026-01-28',
    createdBy: '김철수',
    status: 'inspection_pending',
    remark: '검사 진행 중',
    inspectionDate: '2026-01-27',
    inspectionResult: '불합격',
    inventoryAdjustments: [],
    orderNo: 'PO-2026-004',
    orderUnit: 'EA',
  },
  '5': {
    id: '5',
    materialNo: 'MAT-005',
    lotNo: 'LOT-2026-005',
    itemCode: 'ELEC-005',
    itemName: 'DC 모터 24V',
    specification: '24V 100RPM',
    unit: 'EA',
    supplier: '글로벌전자',
    manufacturer: '글로벌전자',
    receivingQty: undefined,
    receivingDate: undefined,
    createdBy: '최지훈',
    status: 'receiving_pending',
    remark: '',
    inspectionDate: undefined,
    inspectionResult: undefined,
    inventoryAdjustments: [],
    orderNo: 'PO-2026-005',
    orderUnit: 'EA',
  },
};

// ===== API 데이터 타입 =====
interface ReceivingApiData {
  id: number;
  receiving_number: string;
  order_no?: string;
  order_date?: string;
  item_id?: number;
  item_code: string;
  item_name: string;
  specification?: string;
  supplier: string;
  order_qty: string | number;
  order_unit: string;
  due_date?: string;
  receiving_qty?: string | number;
  receiving_date?: string;
  lot_no?: string;
  supplier_lot?: string;
  receiving_location?: string;
  receiving_manager?: string;
  status: ReceivingStatus;
  remark?: string;
  options?: Record<string, unknown>;
  creator?: { id: number; name: string };
  created_at?: string;
  updated_at?: string;
  // 품목 관계 (item relation이 로드된 경우)
  item?: {
    id: number;
    item_type?: string;
    code?: string;
    name?: string;
  };
  // options에서 추출된 접근자 (API appends)
  manufacturer?: string;
  material_no?: string;
  inspection_status?: string;
  inspection_date?: string;
  inspection_result?: string;
  // 수입검사 템플릿 연결 여부 (서버에서 계산)
  has_inspection_template?: boolean;
  // 성적서 파일
  certificate_file_id?: number;
  certificate_file?: { id: number; display_name?: string; file_path?: string };
}

interface ReceivingApiStatsResponse {
  receiving_pending_count: number;
  shipping_count: number;
  inspection_pending_count: number;
  inspection_completed_count: number;
  today_receiving_count: number;
}

// ===== 품목유형 코드 → 라벨 변환 =====
const ITEM_TYPE_LABELS: Record<string, string> = {
  FG: '완제품',
  PT: '부품',
  SM: '부자재',
  RM: '원자재',
  CS: '소모품',
};

// ===== API → Frontend 변환 (목록용) =====
function transformApiToListItem(data: ReceivingApiData): ReceivingItem {
  return {
    id: String(data.id),
    // 입고번호: receiving_number 매핑
    materialNo: data.receiving_number,
    // 거래처 자재번호: options.material_no
    supplierMaterialNo: data.material_no,
    // 원자재로트
    lotNo: data.lot_no,
    // 품목 ID
    itemId: data.item_id,
    // 수입검사 템플릿 연결 여부
    hasInspectionTemplate: data.has_inspection_template ?? false,
    // 수입검사: options.inspection_status (적/부적/-)
    inspectionStatus: data.inspection_status,
    // 검사결과: options.inspection_result (합격/불합격)
    inspectionResult: data.inspection_result,
    // 검사일: options.inspection_date
    inspectionDate: data.inspection_date,
    // 발주처
    supplier: data.supplier,
    // 제조사: options.manufacturer
    manufacturer: data.manufacturer,
    // 품목코드
    itemCode: data.item_code,
    // 품목유형: item relation에서 가져옴
    itemType: data.item?.item_type ? ITEM_TYPE_LABELS[data.item.item_type] || data.item.item_type : undefined,
    // 품목명
    itemName: data.item_name,
    // 규격
    specification: data.specification,
    // 단위
    unit: data.order_unit || 'EA',
    // 수량 (입고수량)
    receivingQty: data.receiving_qty ? parseFloat(String(data.receiving_qty)) : undefined,
    // 입고변경일: updated_at 매핑
    receivingDate: data.updated_at ? formatDate(data.updated_at) : data.receiving_date,
    // 작성자
    createdBy: data.creator?.name,
    // 상태
    status: data.status,
    // 기존 필드 (하위 호환)
    orderNo: data.order_no || data.receiving_number,
    orderQty: parseFloat(String(data.order_qty)) || 0,
    orderUnit: data.order_unit || 'EA',
  };
}

// ===== API → Frontend 변환 (상세용) =====
function transformApiToDetail(data: ReceivingApiData): ReceivingDetail {
  return {
    id: String(data.id),
    materialNo: data.receiving_number,
    supplierMaterialNo: data.material_no,
    lotNo: data.lot_no,
    orderNo: data.order_no || data.receiving_number,
    orderDate: data.order_date,
    supplier: data.supplier,
    manufacturer: data.manufacturer,
    itemId: data.item_id,
    itemCode: data.item_code,
    itemName: data.item_name,
    specification: data.specification,
    orderQty: parseFloat(String(data.order_qty)) || 0,
    orderUnit: data.order_unit || 'EA',
    dueDate: data.due_date,
    status: data.status,
    remark: data.remark,
    receivingDate: data.receiving_date,
    receivingQty: data.receiving_qty ? parseFloat(String(data.receiving_qty)) : undefined,
    receivingLot: data.lot_no,
    supplierLot: data.supplier_lot,
    receivingLocation: data.receiving_location,
    receivingManager: data.receiving_manager,
    unit: data.order_unit || 'EA',
    createdBy: data.creator?.name,
    inspectionDate: data.inspection_date,
    inspectionResult: data.inspection_result,
    certificateFileId: data.certificate_file_id,
    certificateFileName: data.certificate_file?.display_name,
  };
}

// ===== API → Frontend 변환 (통계용) =====
function transformApiToStats(data: ReceivingApiStatsResponse): ReceivingStats {
  return {
    receivingPendingCount: data.receiving_pending_count,
    receivingCompletedCount: data.shipping_count,
    inspectionPendingCount: data.inspection_pending_count,
    inspectionCompletedCount: data.inspection_completed_count,
    shippingCount: data.shipping_count,
    todayReceivingCount: data.today_receiving_count,
  };
}

// ===== Frontend → API 변환 (등록/수정용) =====
function transformFrontendToApi(
  data: Partial<ReceivingDetail>
): Record<string, unknown> {
  const result: Record<string, unknown> = {};

  if (data.orderNo !== undefined) result.order_no = data.orderNo;
  if (data.orderDate !== undefined) result.order_date = data.orderDate;
  if (data.itemCode !== undefined) result.item_code = data.itemCode;
  if (data.itemName !== undefined) result.item_name = data.itemName;
  if (data.specification !== undefined) result.specification = data.specification;
  if (data.supplier !== undefined) result.supplier = data.supplier;
  // 발주수량: orderQty가 없으면 receivingQty를 사용
  const orderQty = data.orderQty ?? data.receivingQty;
  if (orderQty !== undefined) result.order_qty = orderQty;
  const unit = data.orderUnit ?? data.unit;
  if (unit !== undefined) result.order_unit = unit;
  if (data.dueDate !== undefined) result.due_date = data.dueDate;
  if (data.status !== undefined) result.status = data.status;
  if (data.remark !== undefined) result.remark = data.remark;
  if (data.receivingQty !== undefined) result.receiving_qty = data.receivingQty;
  if (data.receivingDate !== undefined) result.receiving_date = data.receivingDate;
  // lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
  if (data.supplierMaterialNo !== undefined) result.material_no = data.supplierMaterialNo;
  if (data.manufacturer !== undefined) result.manufacturer = data.manufacturer;
  if (data.certificateFileId !== undefined) result.certificate_file_id = data.certificateFileId;

  return result;
}

// ===== Frontend → API 변환 (입고처리용) =====
function transformProcessDataToApi(
  data: ReceivingProcessFormData
): Record<string, unknown> {
  return {
    receiving_qty: data.receivingQty,
    // lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
    supplier_lot: data.supplierLot,
    receiving_location: data.receivingLocation,
    remark: data.remark,
  };
}

// ===== 입고 목록 조회 =====
export async function getReceivings(params?: {
  page?: number;
  perPage?: number;
  startDate?: string;
  endDate?: string;
  status?: string;
  search?: string;
}) {
  // ===== 목데이터 모드 =====
  if (USE_MOCK_DATA) {
    let filteredData = [...MOCK_RECEIVING_LIST];

    // 상태 필터
    if (params?.status && params.status !== 'all') {
      filteredData = filteredData.filter(item => item.status === params.status);
    }

    // 검색 필터
    if (params?.search) {
      const search = params.search.toLowerCase();
      filteredData = filteredData.filter(
        item =>
          item.lotNo?.toLowerCase().includes(search) ||
          item.itemCode.toLowerCase().includes(search) ||
          item.itemName.toLowerCase().includes(search) ||
          item.supplier.toLowerCase().includes(search)
      );
    }

    const page = params?.page || 1;
    const perPage = params?.perPage || 20;
    const total = filteredData.length;
    const lastPage = Math.ceil(total / perPage);
    const startIndex = (page - 1) * perPage;
    const paginatedData = filteredData.slice(startIndex, startIndex + perPage);

    return {
      success: true as const,
      data: paginatedData,
      pagination: {
        currentPage: page,
        lastPage,
        perPage,
        total,
      },
    };
  }

  return executePaginatedAction<ReceivingApiData, ReceivingItem>({
    url: buildApiUrl('/api/v1/receivings', {
      page: params?.page,
      per_page: params?.perPage,
      start_date: params?.startDate,
      end_date: params?.endDate,
      status: params?.status && params.status !== 'all' ? params.status : undefined,
      search: params?.search,
    }),
    transform: transformApiToListItem,
    errorMessage: '입고 목록 조회에 실패했습니다.',
  });
}

// ===== 입고 통계 조회 =====
export async function getReceivingStats(): Promise<{
  success: boolean;
  data?: ReceivingStats;
  error?: string;
  __authError?: boolean;
}> {
  if (USE_MOCK_DATA) return { success: true, data: MOCK_RECEIVING_STATS };

  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/receivings/stats'),
    transform: (data: ReceivingApiStatsResponse) => transformApiToStats(data),
    errorMessage: '입고 통계 조회에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, data: result.data, error: result.error };
}

// ===== 입고 상세 조회 =====
export async function getReceivingById(id: string): Promise<{
  success: boolean;
  data?: ReceivingDetail;
  error?: string;
  __authError?: boolean;
}> {
  if (USE_MOCK_DATA) {
    const detail = MOCK_RECEIVING_DETAIL[id];
    return detail ? { success: true, data: detail } : { success: false, error: '입고 정보를 찾을 수 없습니다.' };
  }

  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/receivings/${id}`),
    transform: (data: ReceivingApiData) => transformApiToDetail(data),
    errorMessage: '입고 조회에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, data: result.data, error: result.error };
}

// ===== 입고 등록 =====
export async function createReceiving(
  data: Partial<ReceivingDetail>
): Promise<{ success: boolean; data?: ReceivingDetail; error?: string; __authError?: boolean }> {
  const apiData = transformFrontendToApi(data);
  const result = await executeServerAction({
    url: buildApiUrl('/api/v1/receivings'),
    method: 'POST',
    body: apiData,
    transform: (d: ReceivingApiData) => transformApiToDetail(d),
    errorMessage: '입고 등록에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, data: result.data, error: result.error };
}

// ===== 입고 수정 =====
export async function updateReceiving(
  id: string,
  data: Partial<ReceivingDetail>
): Promise<{ success: boolean; data?: ReceivingDetail; error?: string; __authError?: boolean }> {
  const apiData = transformFrontendToApi(data);
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/receivings/${id}`),
    method: 'PUT',
    body: apiData,
    transform: (d: ReceivingApiData) => transformApiToDetail(d),
    errorMessage: '입고 수정에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, data: result.data, error: result.error };
}

// ===== 입고 삭제 =====
export async function deleteReceiving(
  id: string
): Promise<{ success: boolean; error?: string; __authError?: boolean }> {
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/receivings/${id}`),
    method: 'DELETE',
    errorMessage: '입고 삭제에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, error: result.error };
}

// ===== 입고처리 =====
export async function processReceiving(
  id: string,
  data: ReceivingProcessFormData
): Promise<{ success: boolean; data?: ReceivingDetail; error?: string; __authError?: boolean }> {
  const apiData = transformProcessDataToApi(data);
  const result = await executeServerAction({
    url: buildApiUrl(`/api/v1/receivings/${id}/process`),
    method: 'POST',
    body: apiData,
    transform: (d: ReceivingApiData) => transformApiToDetail(d),
    errorMessage: '입고처리에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  return { success: result.success, data: result.data, error: result.error };
}

// ===== 발주처 검색 (입고 등록용) =====
export interface SupplierOption {
  value: string;
  label: string;
}

const MOCK_SUPPLIERS: SupplierOption[] = [
  { value: '(주)대한철강', label: '(주)대한철강' },
  { value: '삼성전자부품', label: '삼성전자부품' },
  { value: '한국플라스틱', label: '한국플라스틱' },
  { value: '글로벌전자', label: '글로벌전자' },
  { value: '동양화학', label: '동양화학' },
  { value: '한국볼트', label: '한국볼트' },
  { value: '지오TNS (KG스틸)', label: '지오TNS (KG스틸)' },
];

export async function searchSuppliers(query?: string): Promise<{
  success: boolean;
  data: SupplierOption[];
}> {
  if (USE_MOCK_DATA) {
    if (!query) return { success: true, data: MOCK_SUPPLIERS };
    const q = query.toLowerCase();
    const filtered = MOCK_SUPPLIERS.filter((s) => s.label.toLowerCase().includes(q));
    return { success: true, data: filtered };
  }

  interface SupplierApiData { data: Array<Record<string, string>> }
  const result = await executeServerAction<SupplierApiData, SupplierOption[]>({
    url: buildApiUrl('/api/v1/suppliers', { search: query, per_page: 50 }),
    transform: (d) => (d.data || []).map((s) => ({
      value: s.name,
      label: s.name,
    })),
    errorMessage: '발주처 검색에 실패했습니다.',
  });
  return { success: result.success, data: result.data || [] };
}

// ===== 수입검사 템플릿 타입 (ImportInspectionDocument와 동일) =====
export interface InspectionTemplateResponse {
  templateId: string;
  templateName: string;
  headerInfo: {
    productName: string;
    specification: string;
    materialNo: string;
    lotSize: number;
    supplier: string;
    lotNo: string;
    inspectionDate: string;
    inspector: string;
    reportDate: string;
    approvers: {
      writer?: string;
      reviewer?: string;
      approver?: string;
    };
    // 결재선 원본 데이터 (동적 UI 표시용)
    approvalLines?: Array<{
      id: number;
      name: string;
      dept: string;
      role: string;
      sortOrder: number;
    }>;
  };
  inspectionItems: Array<{
    id: string;
    no: number;
    name: string;
    subName?: string;
    parentId?: string;
    standard: {
      description?: string;
      value?: string | number;
      tolerance?: string;  // 허용치 문자열 (MNG와 동일)
      options?: Array<{
        id: string;
        label: string;
        tolerance: string;
        isSelected: boolean;
      }>;
    };
    inspectionMethod: string;
    inspectionCycle: string;
    measurementType: 'okng' | 'numeric' | 'both' | 'single_value' | 'substitute';
    measurementCount: number;
    // 1차 그룹 (category) rowspan - NO, 카테고리명 컬럼용
    categoryRowSpan?: number;
    isFirstInCategory?: boolean;
    // 2차 그룹 (item) rowspan - 검사항목(세부), 검사방식, 검사주기, 측정치, 판정 컬럼용
    itemRowSpan?: number;
    isFirstInItem?: boolean;
    // 기존 호환용 (deprecated)
    rowSpan?: number;
    isSubRow?: boolean;
  }>;
  notes?: string[];
}

// ===== 수입검사 템플릿 Resolve API 응답 타입 =====
export interface DocumentResolveResponse {
  is_new: boolean;
  template: {
    id: number;
    name: string;
    category: string;
    title: string;
    company_name?: string;
    company_address?: string;
    company_contact?: string;
    footer_remark_label?: string;
    footer_judgement_label?: string;
    footer_judgement_options?: string[];
    approval_lines: Array<{
      id: number;
      name?: string;
      dept?: string;
      role: string;
      user_id?: number;
      sort_order: number;
    }>;
    basic_fields: Array<{
      id: number;
      field_key: string;
      label: string;
      input_type: string;
      options?: unknown;
      default_value?: string;
      is_required: boolean;
      sort_order: number;
    }>;
    section_fields: Array<{
      id: number;
      field_key: string;
      label: string;
      field_type: string;
      options?: unknown;
      width?: string;
      is_required: boolean;
      sort_order: number;
    }>;
    sections: Array<{
      id: number;
      name: string;
      sort_order: number;
      items: Array<{
        id: number;
        /** 새로운 API 형식: field_values에 모든 필드값 포함 */
        field_values?: Record<string, unknown>;
        /** 레거시 필드 (하위 호환) */
        category?: string;
        item?: string;
        standard?: string;
        /** 범위 조건 객체: { min, min_op, max, max_op } */
        standard_criteria?: {
          min?: number | null;
          min_op?: 'gt' | 'gte' | null;
          max?: number | null;
          max_op?: 'lt' | 'lte' | null;
        } | null;
        /** 공차 객체: { type, value, plus, minus, min, max, op } */
        tolerance?: {
          type?: 'symmetric' | 'asymmetric' | 'range' | 'percentage' | 'limit';
          value?: string | number;
          plus?: string | number;
          minus?: string | number;
          min?: string | number;
          max?: string | number;
          op?: 'lte' | 'lt' | 'gte' | 'gt';  // limit 타입용
        } | string | null;
        method?: string;
        method_name?: string;  // 검사방식 한글 이름 (API에서 common_codes join)
        measurement_type?: string;
        frequency?: string;
        frequency_n?: number;
        frequency_c?: number;
        regulation?: string;
        sort_order: number;
      }>;
    }>;
    columns: Array<{
      id: number;
      label: string;
      input_type: string;
      options?: unknown;
      width?: string;
      is_required: boolean;
      sort_order: number;
    }>;
  };
  document: {
    id: number;
    document_no: string;
    title: string;
    status: 'DRAFT' | 'PENDING' | 'APPROVED' | 'REJECTED' | 'CANCELLED';
    linkable_type?: string;
    linkable_id?: number;
    submitted_at?: string;
    completed_at?: string;
    created_at?: string;
    data: Array<{
      section_id?: number | null;
      column_id?: number | null;
      row_index: number;
      field_key: string;
      field_value?: string | null;
    }>;
    attachments: Array<{
      id: number;
      file_id: number;
      attachment_type: string;
      description?: string;
      file?: {
        id: number;
        original_name: string;
        display_name?: string;
        file_path: string;
        file_size: number;
        mime_type?: string;
      };
    }>;
    approvals: Array<{
      id: number;
      user_id: number;
      user_name?: string;
      step: number;
      role: string;
      status: string;
      comment?: string;
      acted_at?: string;
    }>;
  } | null;
  item: {
    id: number;
    code: string;
    name: string;
    /** 품목 속성 (thickness, width, length 등) */
    attributes?: {
      thickness?: number;
      width?: number;
      length?: number;
      [key: string]: unknown;
    } | null;
  };
}

// ===== 수입검사 템플릿 존재 여부 확인 =====
export async function checkInspectionTemplate(itemId?: number): Promise<{
  success: boolean;
  hasTemplate: boolean;
  attachments?: Array<{
    id: number;
    file_id: number;
    attachment_type: string;
    description?: string;
    file?: {
      id: number;
      display_name?: string;
      original_name?: string;
      file_path: string;
      file_size: number;
      mime_type?: string;
    };
  }>;
  error?: string;
}> {
  if (!itemId) {
    return { success: true, hasTemplate: false };
  }

  // 목데이터 모드
  if (USE_MOCK_DATA) {
    return { success: true, hasTemplate: true };
  }

  try {
    const url = buildApiUrl('/api/v1/documents/resolve', {
      category: 'incoming_inspection',
      item_id: itemId,
    });

    const { response, error } = await serverFetch(url, { method: 'GET' });

    if (error) {
      // 404는 템플릿 없음으로 처리
      if (error.code === 'NOT_FOUND' || error.message?.includes('404')) {
        return { success: true, hasTemplate: false };
      }
      return { success: false, hasTemplate: false, error: error.message || '템플릿 조회 실패' };
    }

    if (!response) {
      return { success: false, hasTemplate: false, error: '템플릿 조회 실패' };
    }

    // 404 응답도 템플릿 없음으로 처리
    if (response.status === 404) {
      return { success: true, hasTemplate: false };
    }

    const result = await response.json();
    // template.id가 있으면 템플릿 존재
    const hasTemplate = !!(result?.data?.template?.id);
    const attachments = result?.data?.document?.attachments || [];
    return { success: true, hasTemplate, attachments };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    console.error('checkInspectionTemplate error:', error);
    return { success: false, hasTemplate: false, error: '템플릿 조회 중 오류' };
  }
}

// ===== 수입검사 템플릿 조회 (item_id 기반 - /v1/documents/resolve API 사용) =====
export async function getInspectionTemplate(params: {
  itemId?: number;
  itemName?: string;
  specification?: string;
  lotNo?: string;
  supplier?: string;
  inspector?: string;    // 검사자 (현재 로그인 사용자)
  lotSize?: number;      // 로트크기 (입고수량)
  materialNo?: string;   // 자재번호
}): Promise<{
  success: boolean;
  data?: InspectionTemplateResponse;
  resolveData?: DocumentResolveResponse;
  error?: string;
  __authError?: boolean;
}> {
  // ===== 목데이터 모드 - EGI 강판 템플릿 반환 =====
  if (USE_MOCK_DATA) {
    // 품목명/규격에 따라 다른 템플릿 반환 (추후 24종 확장)
    const inspectorName = params.inspector || '노원호';
    const mockTemplate: InspectionTemplateResponse = {
      templateId: 'EGI-001',
      templateName: '전기 아연도금 강판',
      headerInfo: {
        productName: params.itemName || '전기 아연도금 강판 (KS D 3528, SECC) "EGI 평국판"',
        specification: params.specification || '1.55 * 1218 × 480',
        materialNo: params.materialNo || 'PE02RB',
        lotSize: params.lotSize || 200,
        supplier: params.supplier || '지오TNS (KG스틸)',
        lotNo: params.lotNo || '250715-02',
        inspectionDate: new Date().toLocaleDateString('ko-KR', { month: '2-digit', day: '2-digit' }).replace('. ', '/').replace('.', ''),
        inspector: inspectorName,
        reportDate: getTodayString(),
        approvers: {
          writer: inspectorName,
          reviewer: '',
          approver: '',
        },
        // 결재선 데이터
        approvalLines: [
          { id: 1, name: '', dept: '', role: '작성', sortOrder: 1 },
          { id: 2, name: '', dept: '', role: '검토', sortOrder: 2 },
          { id: 3, name: '', dept: '', role: '승인', sortOrder: 3 },
          { id: 4, name: '', dept: '', role: '승인', sortOrder: 4 },
        ],
      },
      inspectionItems: [
        {
          id: 'appearance',
          no: 1,
          name: '겉모양',
          standard: { description: '사용상 해로운 결함이 없을 것' },
          inspectionMethod: '육안검사',
          inspectionCycle: '',
          measurementType: 'okng',
          measurementCount: 3,
        },
        {
          id: 'thickness',
          no: 2,
          name: '치수',
          subName: '두께',
          standard: {
            value: 1.55,
            options: [
              { id: 't1', label: '0.8 이상 ~ 1.0 미만', tolerance: '± 0.07', isSelected: false },
              { id: 't2', label: '1.0 이상 ~ 1.25 미만', tolerance: '± 0.08', isSelected: false },
              { id: 't3', label: '1.25 이상 ~ 1.6 미만', tolerance: '± 0.10', isSelected: true },
              { id: 't4', label: '1.6 이상 ~ 2.0 미만', tolerance: '± 0.12', isSelected: false },
            ],
          },
          inspectionMethod: 'n = 3\nc = 0',
          inspectionCycle: '체크검사',
          measurementType: 'numeric',
          measurementCount: 3,
          rowSpan: 3,
        },
        {
          id: 'width',
          no: 2,
          name: '치수',
          subName: '너비',
          parentId: 'thickness',
          standard: {
            value: 1219,
            options: [{ id: 'w1', label: '1250 미만', tolerance: '+ 7\n- 0', isSelected: true }],
          },
          inspectionMethod: '',
          inspectionCycle: '',
          measurementType: 'numeric',
          measurementCount: 3,
          isSubRow: true,
        },
        {
          id: 'length',
          no: 2,
          name: '치수',
          subName: '길이',
          parentId: 'thickness',
          standard: {
            value: 480,
            options: [{ id: 'l1', label: '2000 이상 ~ 4000 미만', tolerance: '+ 15\n- 0', isSelected: true }],
          },
          inspectionMethod: '',
          inspectionCycle: '',
          measurementType: 'numeric',
          measurementCount: 3,
          isSubRow: true,
        },
        {
          id: 'tensileStrength',
          no: 3,
          name: '인장강도 (N/㎟)',
          standard: { description: '270 이상' },
          inspectionMethod: '',
          inspectionCycle: '',
          measurementType: 'numeric',
          measurementCount: 1,
        },
        {
          id: 'elongation',
          no: 4,
          name: '연신율 %',
          standard: {
            options: [
              { id: 'e1', label: '두께 0.6 이상 ~ 1.0 미만', tolerance: '36 이상', isSelected: false },
              { id: 'e2', label: '두께 1.0 이상 ~ 1.6 미만', tolerance: '37 이상', isSelected: true },
              { id: 'e3', label: '두께 1.6 이상 ~ 2.3 미만', tolerance: '38 이상', isSelected: false },
            ],
          },
          inspectionMethod: '공급업체\n밀시트',
          inspectionCycle: '입고시',
          measurementType: 'numeric',
          measurementCount: 1,
        },
        {
          id: 'zincCoating',
          no: 5,
          name: '아연의 최소 부착량 (g/㎡)',
          standard: { description: '편면 17 이상' },
          inspectionMethod: '',
          inspectionCycle: '',
          measurementType: 'numeric',
          measurementCount: 2,
        },
      ],
      notes: [
        '※ 1.55mm의 경우 KS F 4510에 따른 MIN 1.5의 기준에 따름',
        '※ 두께의 경우 너비 1000 이상 ~ 1250 미만 기준에 따름',
      ],
    };

    return { success: true, data: mockTemplate };
  }

  // ===== 실제 API 호출 (/v1/documents/resolve) =====
  // itemId가 있으면 실제 API로 템플릿 조회
  if (!params.itemId) {
    return { success: false, error: '품목 ID가 필요합니다.' };
  }

  const result = await executeServerAction<DocumentResolveResponse>({
    url: buildApiUrl('/api/v1/documents/resolve', {
      category: 'incoming_inspection',
      item_id: params.itemId,
    }),
    errorMessage: '검사 템플릿 조회에 실패했습니다.',
  });
  if (result.__authError) return { success: false, __authError: true };
  if (!result.success || !result.data) return { success: false, error: result.error };

  const resolveData = result.data;
  const template = transformResolveToTemplate(resolveData, params);
  return { success: true, data: template, resolveData };
}

// ===== Tolerance 타입 정의 =====
interface ToleranceObject {
  type?: 'symmetric' | 'asymmetric' | 'range' | 'percentage' | 'limit';
  value?: string | number;
  plus?: string | number;
  minus?: string | number;
  min?: string | number;
  max?: string | number;
  min_op?: string;
  max_op?: string;
  op?: 'lte' | 'lt' | 'gte' | 'gt';  // limit 타입용
}

// ===== StandardCriteria 타입 정의 =====
interface StandardCriteriaObject {
  min?: number | null;
  min_op?: 'gt' | 'gte' | null;
  max?: number | null;
  max_op?: 'lt' | 'lte' | null;
}

// ===== tolerance 객체를 문자열로 변환하는 헬퍼 함수 =====
function _formatTolerance(tolerance: unknown): string {
  if (!tolerance) return '';
  if (typeof tolerance === 'string') return tolerance;
  if (typeof tolerance !== 'object') return String(tolerance);

  const t = tolerance as ToleranceObject;

  // 새로운 API 형식: type 기반 처리
  switch (t.type) {
    case 'symmetric':
      return t.value ? `± ${t.value}` : '';
    case 'asymmetric':
      return `+ ${t.plus || 0}\n- ${t.minus || 0}`;
    case 'range':
      return `${t.min || ''} ~ ${t.max || ''}`;
    case 'percentage':
      return t.value ? `± ${t.value}%` : '';
  }

  // 레거시 형식: min/max 직접 처리 (type 없는 경우)
  if (t.min !== undefined || t.max !== undefined) {
    return formatStandardCriteria(t as StandardCriteriaObject);
  }

  return '';
}

// ===== standard_criteria 객체를 문자열로 변환 =====
function formatStandardCriteria(criteria: unknown): string {
  if (!criteria) return '';
  if (typeof criteria === 'string') return criteria;
  if (typeof criteria !== 'object') return String(criteria);

  const c = criteria as StandardCriteriaObject;
  const parts: string[] = [];

  // min 조건
  if (c.min !== undefined && c.min !== null) {
    const op = c.min_op === 'gte' ? '≥' : c.min_op === 'gt' ? '>' : '≥';
    parts.push(`${op} ${c.min}`);
  }

  // max 조건
  if (c.max !== undefined && c.max !== null) {
    const op = c.max_op === 'lte' ? '≤' : c.max_op === 'lt' ? '<' : '≤';
    parts.push(`${op} ${c.max}`);
  }

  if (parts.length === 0) return '';
  if (parts.length === 1) return parts[0];

  // 두 조건 모두 있으면 "min 이상 ~ max 미만" 형태
  return parts.join(', ');
}

// ===== 범위 라벨 생성 (예: "0.8 이상 ~ 1.0 미만") =====
function formatCriteriaLabel(criteria: unknown): string {
  if (!criteria) return '';
  if (typeof criteria === 'string') return criteria;
  if (typeof criteria !== 'object') return '';

  const c = criteria as StandardCriteriaObject;
  const parts: string[] = [];

  if (c.min !== undefined && c.min !== null) {
    const op = c.min_op === 'gte' ? '이상' : c.min_op === 'gt' ? '초과' : '이상';
    parts.push(`${c.min} ${op}`);
  }

  if (c.max !== undefined && c.max !== null) {
    const op = c.max_op === 'lte' ? '이하' : c.max_op === 'lt' ? '미만' : '미만';
    parts.push(`${c.max} ${op}`);
  }

  return parts.join(' ~ ');
}

// ===== MNG와 동일한 허용치 포맷팅 =====
function formatToleranceForDisplay(tolerance: unknown): string {
  if (!tolerance) return '-';
  // 문자열인 경우 (레거시)
  if (typeof tolerance === 'string') return tolerance || '-';
  if (typeof tolerance !== 'object') return String(tolerance);

  const t = tolerance as ToleranceObject;
  // type이 없으면 레거시
  if (!t.type) return '-';

  switch (t.type) {
    case 'symmetric':
      return t.value != null ? `±${t.value}` : '-';
    case 'asymmetric':
      return (t.plus != null || t.minus != null)
        ? `+${t.plus ?? 0} / -${t.minus ?? 0}` : '-';
    case 'range':
      return (t.min != null || t.max != null)
        ? `${t.min ?? ''} ~ ${t.max ?? ''}` : '-';
    case 'limit': {
      const opSymbol: Record<string, string> = { lte: '≤', lt: '<', gte: '≥', gt: '>' };
      return t.value != null ? `${opSymbol[t.op as string] || '≤'}${t.value}` : '-';
    }
    default:
      return '-';
  }
}

// ===== MNG와 동일한 검사기준 포맷팅 =====
function formatStandardForDisplay(item: {
  standard?: string;
  standard_criteria?: unknown;
  tolerance?: unknown;
}): string {
  const c = item.standard_criteria as StandardCriteriaObject | undefined;
  if (c && (c.min != null || c.max != null)) {
    const opLabel: Record<string, string> = { gte: '이상', gt: '초과', lte: '이하', lt: '미만' };
    const parts: string[] = [];
    if (c.min != null) parts.push(`${c.min} ${opLabel[c.min_op || 'gte']}`);
    if (c.max != null) parts.push(`${c.max} ${opLabel[c.max_op || 'lte']}`);
    return parts.join(' ~ ');
  }
  let std = item.standard || '-';
  const tolStr = formatToleranceForDisplay(item.tolerance);
  if (tolStr !== '-') std += ` (${tolStr})`;
  return std;
}

// ===== MNG와 동일한 검사주기 포맷팅 =====
function formatFrequencyForDisplay(item: {
  frequency?: string;
  frequency_n?: number;
  frequency_c?: number;
}): string {
  const parts: string[] = [];
  if (item.frequency_n != null && item.frequency_n !== 0) {
    let nc = `n=${item.frequency_n}`;
    // c=0도 표시 (null이 아니면 표시)
    if (item.frequency_c != null) nc += `, c=${item.frequency_c}`;
    parts.push(nc);
  }
  if (item.frequency) parts.push(item.frequency);
  return parts.length > 0 ? parts.join(' / ') : '-';
}

// ===== DocumentResolve 응답을 InspectionTemplateResponse로 변환 =====
function transformResolveToTemplate(
  resolveData: DocumentResolveResponse,
  params: { itemName?: string; specification?: string; lotNo?: string; supplier?: string; inspector?: string; lotSize?: number; materialNo?: string }
): InspectionTemplateResponse {
  const { template, document, item } = resolveData;

  // 기존 문서 데이터를 맵으로 변환 (빠른 조회용)
  const savedDataMap = new Map<string, string>();
  if (document?.data) {
    document.data.forEach(d => {
      const key = `${d.section_id || 0}_${d.row_index}_${d.field_key}`;
      savedDataMap.set(key, d.field_value || '');
    });
  }

  // 품목 속성 추출 (자동 하이라이트용)
  const itemAttrs = item.attributes as { thickness?: number; width?: number; length?: number } | undefined;

  // 모든 섹션의 items를 하나로 합침
  let allSectionItems: Array<{
    sectionItem: typeof template.sections[0]['items'][0];
    category: string;
    itemName: string;
  }> = [];

  for (const section of template.sections) {
    for (const sectionItem of section.items) {
      const fieldValues = sectionItem.field_values || {};
      const category = safeString(sectionItem.category) || safeString(fieldValues.category);
      const itemName = safeString(sectionItem.item) || safeString(fieldValues.item);
      allSectionItems.push({ sectionItem, category, itemName });
    }
  }

  // 품목에 해당 치수 속성이 없으면 검사항목에서 제거 (코일 등 너비/길이 없는 품목)
  if (itemAttrs) {
    const dimensionAttrMap: Record<string, 'thickness' | 'width' | 'length'> = {
      '두께': 'thickness',
      '너비': 'width',
      '길이': 'length',
    };

    allSectionItems = allSectionItems.filter(({ itemName }) => {
      const attrKey = dimensionAttrMap[itemName];
      if (!attrKey) return true;
      return itemAttrs[attrKey] != null;
    });
  }

  // 그룹핑 로직:
  // - category가 있으면: category로 1차 그룹, item으로 2차 그룹
  // - category가 없으면: 같은 item 이름끼리 1차 그룹 (2차 그룹 없음)

  interface GroupInfo {
    categoryRowSpan: number;
    isFirstInCategory: boolean;
    itemRowSpan: number;
    isFirstInItem: boolean;
    hasCategory: boolean;
  }

  const groupInfoMap = new Map<number, GroupInfo>();

  for (let i = 0; i < allSectionItems.length; i++) {
    const { category, itemName } = allSectionItems[i];
    const hasCategory = !!category;

    let categoryRowSpan = 1;
    let isFirstInCategory = true;
    let itemRowSpan = 1;
    let isFirstInItem = true;

    if (hasCategory) {
      // category가 있는 경우: category로 1차 그룹, item으로 2차 그룹

      // 1차 그룹 (category) 계산
      for (let j = 0; j < i; j++) {
        if (allSectionItems[j].category === category) {
          isFirstInCategory = false;
          break;
        }
      }

      if (isFirstInCategory) {
        for (let j = i + 1; j < allSectionItems.length; j++) {
          if (allSectionItems[j].category === category) {
            categoryRowSpan++;
          } else {
            break;
          }
        }
      }

      // 2차 그룹 (item) 계산 - category 내에서 같은 item 그룹핑
      for (let j = 0; j < i; j++) {
        if (allSectionItems[j].category === category && allSectionItems[j].itemName === itemName) {
          isFirstInItem = false;
          break;
        }
      }

      if (isFirstInItem) {
        for (let j = i + 1; j < allSectionItems.length; j++) {
          if (allSectionItems[j].category === category && allSectionItems[j].itemName === itemName) {
            itemRowSpan++;
          } else if (allSectionItems[j].category !== category) {
            break;
          }
        }
      }
    } else {
      // category가 없는 경우: 같은 item 이름끼리 그룹핑

      // 같은 item 이름이 이전에 있었는지 확인
      for (let j = 0; j < i; j++) {
        if (!allSectionItems[j].category && allSectionItems[j].itemName === itemName) {
          isFirstInCategory = false;
          isFirstInItem = false;
          break;
        }
      }

      // 같은 item 이름이 몇 개 연속되는지 확인 (처음인 경우만)
      if (isFirstInCategory) {
        for (let j = i + 1; j < allSectionItems.length; j++) {
          if (!allSectionItems[j].category && allSectionItems[j].itemName === itemName) {
            categoryRowSpan++;
            itemRowSpan++;
          } else {
            break;
          }
        }
      }
    }

    groupInfoMap.set(i, {
      categoryRowSpan: isFirstInCategory ? categoryRowSpan : 0,
      isFirstInCategory,
      itemRowSpan: isFirstInItem ? itemRowSpan : 0,
      isFirstInItem,
      hasCategory,
    });
  }

  // 섹션의 items를 검사항목으로 변환
  const inspectionItems: InspectionTemplateResponse['inspectionItems'] = [];
  let noCounter = 0;
  let prevCategoryForNo = '';

  for (let i = 0; i < allSectionItems.length; i++) {
    const { sectionItem, category, itemName } = allSectionItems[i];
    const groupInfo = groupInfoMap.get(i)!;

    // NO 증가 (category가 바뀔 때만, 또는 category가 없을 때)
    if (category !== prevCategoryForNo || !category) {
      noCounter++;
      prevCategoryForNo = category;
    }

    const fieldValues = sectionItem.field_values || {};
    const standardText = safeString(sectionItem.standard) || safeString(fieldValues.standard);
    const method = safeString(sectionItem.method) || safeString(fieldValues.method);
    const measurementType = safeString(sectionItem.measurement_type) || safeString(fieldValues.measurement_type);

    // MNG와 동일한 검사기준 포맷팅
    const formattedStandard = formatStandardForDisplay({
      standard: standardText,
      standard_criteria: sectionItem.standard_criteria,
      tolerance: sectionItem.tolerance,
    });

    // MNG와 동일한 허용치 포맷팅
    const formattedTolerance = formatToleranceForDisplay(sectionItem.tolerance);

    // MNG와 동일한 검사주기 포맷팅
    const formattedFrequency = formatFrequencyForDisplay({
      frequency: sectionItem.frequency,
      frequency_n: sectionItem.frequency_n,
      frequency_c: sectionItem.frequency_c,
    });

    // 참조 속성 (연신율 등은 두께를 기준으로 검사기준 결정)
    const referenceAttribute = safeString(fieldValues.reference_attribute);

    // 자동 하이라이트 (품목 속성과 standard_criteria 매칭)
    const isHighlighted = shouldHighlightRow(
      itemName,
      sectionItem.standard_criteria,
      itemAttrs,
      referenceAttribute || undefined
    );

    // standard_criteria가 있으면 옵션으로 변환 (하이라이트용)
    let toleranceOptions: Array<{ id: string; label: string; tolerance: string; isSelected: boolean }> | undefined;
    const criteriaLabel = formatCriteriaLabel(sectionItem.standard_criteria);
    if (sectionItem.standard_criteria && criteriaLabel) {
      toleranceOptions = [{
        id: `criteria-${sectionItem.id}`,
        label: criteriaLabel,
        tolerance: formattedTolerance !== '-' ? formattedTolerance : '',
        isSelected: isHighlighted,
      }];
    }

    // 측정 횟수: frequency_n 값 사용 (기본값 1)
    const measurementCount = sectionItem.frequency_n && sectionItem.frequency_n > 0 ? sectionItem.frequency_n : 1;

    inspectionItems.push({
      id: String(sectionItem.id),
      no: noCounter,
      name: category || itemName,  // 카테고리가 있으면 카테고리, 없으면 항목명
      subName: category ? itemName : undefined,  // 카테고리가 있을 때만 항목명이 subName
      standard: {
        description: formattedStandard,  // MNG와 동일한 포맷 (검사기준 전체)
        value: undefined,
        tolerance: formattedTolerance !== '-' ? formattedTolerance : undefined,  // 허용치
        options: toleranceOptions,
      },
      inspectionMethod: formatInspectionMethod(method, sectionItem),
      inspectionCycle: formattedFrequency,  // MNG와 동일한 포맷
      measurementType: mapMeasurementType(measurementType),
      measurementCount,
      // 3단계 그룹핑 정보
      categoryRowSpan: groupInfo.categoryRowSpan,
      isFirstInCategory: groupInfo.isFirstInCategory,
      itemRowSpan: groupInfo.itemRowSpan,
      isFirstInItem: groupInfo.isFirstInItem,
      // 기존 호환용
      rowSpan: groupInfo.categoryRowSpan,
      isSubRow: !groupInfo.isFirstInCategory,
    });
  }

  // 품목 속성에서 규격 추출 (두께*너비*길이 형식)
  let specificationFromAttrs = '';
  if (itemAttrs) {
    const parts: string[] = [];
    if (itemAttrs.thickness) parts.push(String(itemAttrs.thickness));
    if (itemAttrs.width) parts.push(String(itemAttrs.width));
    if (itemAttrs.length) parts.push(String(itemAttrs.length));
    if (parts.length > 0) {
      specificationFromAttrs = parts.join(' × ');
    }
  }

  // 결재선 정보 (role → 표시명)
  const sortedApprovalLines = [...template.approval_lines].sort((a, b) => a.sort_order - b.sort_order);
  const writerLine = sortedApprovalLines.find(l => l.role === '작성');
  const reviewerLine = sortedApprovalLines.find(l => l.role === '검토');
  const approverLines = sortedApprovalLines.filter(l => l.role === '승인');

  // notes에 비고 추가
  const notes: string[] = [];
  if (template.footer_remark_label) {
    notes.push(template.footer_remark_label);
  }

  return {
    templateId: String(template.id),
    templateName: template.name,
    headerInfo: {
      productName: item.name || params.itemName || '',
      specification: params.specification || specificationFromAttrs || '',
      materialNo: params.materialNo || item.code || '',
      lotSize: params.lotSize || 0,
      supplier: params.supplier || '',
      lotNo: params.lotNo || '',
      inspectionDate: new Date().toLocaleDateString('ko-KR', { month: '2-digit', day: '2-digit' }).replace('. ', '/').replace('.', ''),
      inspector: params.inspector || '',
      reportDate: getTodayString(),
      approvers: {
        // 작성자는 현재 검사자 (로그인 사용자)로 설정
        writer: params.inspector || writerLine?.role || '',
        reviewer: reviewerLine?.role || '',
        // 승인자들 (여러 명 가능)
        approver: approverLines.map(l => l.role).join(', ') || '',
      },
      // 결재선 원본 데이터 (UI에서 동적으로 표시하기 위해)
      approvalLines: sortedApprovalLines.map(l => ({
        id: l.id,
        name: l.name || l.role || '',
        dept: l.dept || '',
        role: l.role || l.name || '',
        sortOrder: l.sort_order,
      })),
    },
    inspectionItems,
    notes,
  };
}

// ===== 안전한 문자열 변환 =====
function safeString(value: unknown): string {
  if (value === null || value === undefined) return '';
  if (typeof value === 'string') return value;
  if (typeof value === 'number') return String(value);
  if (typeof value === 'object') {
    // 객체인 경우 JSON.stringify 하지 않고 빈 문자열 반환
    return '';
  }
  return String(value);
}

// ===== 자동 하이라이트 판단 =====
function shouldHighlightRow(
  itemName: string,
  criteria: unknown,
  itemAttrs?: { thickness?: number; width?: number; length?: number },
  referenceAttribute?: string  // field_values.reference_attribute
): boolean {
  if (!criteria || !itemAttrs) return false;
  if (typeof criteria !== 'object') return false;

  const c = criteria as StandardCriteriaObject;
  const name = itemName.toLowerCase();

  let targetValue: number | undefined;

  // 1. referenceAttribute가 명시되어 있으면 해당 속성 사용 (연신율 등)
  if (referenceAttribute) {
    const attrMap: Record<string, keyof typeof itemAttrs> = {
      'thickness': 'thickness',
      'width': 'width',
      'length': 'length',
    };
    const attrKey = attrMap[referenceAttribute];
    if (attrKey && itemAttrs[attrKey] !== undefined) {
      targetValue = itemAttrs[attrKey];
    }
  }
  // 2. referenceAttribute가 없으면 항목명에서 추론 (기존 로직)
  else {
    if (name.includes('두께') && itemAttrs.thickness !== undefined) {
      targetValue = itemAttrs.thickness;
    } else if (name.includes('너비') && itemAttrs.width !== undefined) {
      targetValue = itemAttrs.width;
    } else if (name.includes('길이') && itemAttrs.length !== undefined) {
      targetValue = itemAttrs.length;
    }
  }

  if (targetValue === undefined) return false;

  // 범위 체크
  let match = true;
  if (c.min !== undefined && c.min !== null) {
    match = match && (c.min_op === 'gte' ? targetValue >= c.min : targetValue > c.min);
  }
  if (c.max !== undefined && c.max !== null) {
    match = match && (c.max_op === 'lte' ? targetValue <= c.max : targetValue < c.max);
  }

  return match;
}

// ===== 검사방식 포맷 =====
function formatInspectionMethod(
  method: string,
  sectionItem: { method_name?: string; frequency_n?: number; frequency_c?: number }
): string {
  // API에서 반환한 method_name이 있으면 우선 사용 (common_codes join 결과)
  if (sectionItem.method_name) {
    return sectionItem.method_name;
  }

  // method 코드가 있으면 fallback 매핑 사용
  if (method) {
    const methodMap: Record<string, string> = {
      'visual': '육안검사',
      'check': '체크검사',
      'measure': '계측검사',
      'mill_sheet': '공급업체 밀시트',
      'millsheet': '밀시트',
      'certified_agency': '공인시험기관',
      'substitute_cert': '공급업체 성적서 대체',
      'other': '기타',
    };
    return methodMap[method] || method;
  }

  // frequency_n, frequency_c가 있으면 "n = X, c = Y" 형식
  if (sectionItem.frequency_n !== undefined && sectionItem.frequency_n > 0) {
    const n = sectionItem.frequency_n;
    const c = sectionItem.frequency_c ?? 0;
    return `n = ${n}\nc = ${c}`;
  }

  return '';
}

// ===== 측정유형 매핑 - MNG와 동일 =====
function mapMeasurementType(type: string): 'okng' | 'numeric' | 'both' | 'single_value' | 'substitute' {
  switch (type) {
    case 'numeric':
      return 'numeric';
    case 'checkbox':
    case 'okng':
      return 'okng';
    case 'both':
      return 'both';
    case 'single_value':
      return 'single_value';
    case 'substitute':
      return 'substitute';
    default:
      return 'okng';
  }
}

// ===== 수입검사 파일 업로드 (사진 첨부용) =====
export interface UploadedInspectionFile {
  id: number;
  name: string;
  url: string;
  size?: number;
}

export async function uploadInspectionFiles(files: File[]): Promise<{
  success: boolean;
  data?: UploadedInspectionFile[];
  error?: string;
}> {
  if (files.length === 0) {
    return { success: true, data: [] };
  }

  try {
    const { cookies } = await import('next/headers');
    const cookieStore = await cookies();
    const token = cookieStore.get('access_token')?.value;

    const uploadedFiles: UploadedInspectionFile[] = [];

    for (const file of files) {
      const formData = new FormData();
      formData.append('file', file);

      const response = await fetch(
        buildApiUrl('/api/v1/files/upload'),
        {
          method: 'POST',
          headers: {
            'Authorization': token ? `Bearer ${token}` : '',
            'X-API-KEY': process.env.API_KEY || '',
          },
          body: formData,
        }
      );

      if (!response.ok) {
        console.error('[ReceivingActions] File upload error:', response.status);
        return { success: false, error: `파일 업로드 실패: ${file.name}` };
      }

      const result = await response.json();
      if (result.success && result.data) {
        uploadedFiles.push({
          id: result.data.id,
          name: result.data.display_name || file.name,
          url: `/api/proxy/files/${result.data.id}/download`,
          size: result.data.file_size,
        });
      }
    }

    return { success: true, data: uploadedFiles };
  } catch (error) {
    if (isNextRedirectError(error)) throw error;
    console.error('[ReceivingActions] uploadInspectionFiles error:', error);
    return { success: false, error: '파일 업로드 중 오류가 발생했습니다.' };
  }
}

// ===== 수입검사 데이터 저장 (documents/upsert + receivings 상태 업데이트) =====
export async function saveInspectionData(params: {
  templateId: number;
  itemId: number;
  title?: string;
  data: Array<{ section_id?: number | null; column_id?: number | null; row_index: number; field_key: string; field_value: string | null }>;
  attachments?: Array<{ file_id: number; attachment_type: string; description?: string }>;
  receivingId: string;
  inspectionResult?: 'pass' | 'fail' | null;
  rendered_html?: string;
}): Promise<{
  success: boolean;
  error?: string;
  __authError?: boolean;
}> {
  // Step 1: POST /v1/documents/upsert - 검사 데이터 저장
  const docResult = await executeServerAction({
    url: buildApiUrl('/api/v1/documents/upsert'),
    method: 'POST',
    body: {
      template_id: params.templateId,
      item_id: params.itemId,
      title: params.title || '수입검사 성적서',
      data: params.data,
      attachments: params.attachments || [],
      rendered_html: params.rendered_html,
    },
    errorMessage: '검사 데이터 저장에 실패했습니다.',
  });
  if (docResult.__authError) return { success: false, __authError: true };
  if (!docResult.success) return { success: false, error: docResult.error };

  // Step 2: PUT /v1/receivings/{id} - 검사 완료 후 상태 변경
  const today = getTodayString();
  const inspectionStatus = params.inspectionResult === 'pass' ? '적' : params.inspectionResult === 'fail' ? '부적' : '-';
  const inspectionResultLabel = params.inspectionResult === 'pass' ? '합격' : params.inspectionResult === 'fail' ? '불합격' : null;

  const recResult = await executeServerAction({
    url: buildApiUrl(`/api/v1/receivings/${params.receivingId}`),
    method: 'PUT',
    body: {
      status: 'inspection_completed',
      inspection_status: inspectionStatus,
      inspection_date: today,
      inspection_result: inspectionResultLabel,
    },
    errorMessage: '입고 상태 업데이트에 실패했습니다.',
  });
  if (!recResult.success) {
    console.error('[ReceivingActions] 입고 상태 업데이트 실패 (검사 데이터는 저장됨):', recResult.error);
  }

  return { success: true };
}