'use client';

import { createContext, useContext, useState, useEffect, useMemo, ReactNode } from 'react';
import { useAuth } from './AuthContext';
import { TenantAwareCache } from '@/lib/cache';
import { itemMasterApi } from '@/lib/api/item-master';
import { getErrorMessage, ApiError } from '@/lib/api/error-handler';
import {
  transformPageResponse,
  transformSectionResponse,
  transformFieldResponse,
  transformBomItemResponse,
} from '@/lib/api/transformers';
import type {
  ItemPageRequest,
  IndependentSectionRequest,
  IndependentFieldRequest,
  IndependentBomItemRequest,
  LinkSectionRequest,
  LinkFieldRequest,
  SectionUsageResponse,
  FieldUsageResponse,
} from '@/types/item-master-api';

// 타입 정의는 별도 파일에서 import
export type {
  BendingDetail,
  BOMLine,
  SpecificationMaster,
  MaterialItemName,
  ItemRevision,
  ItemMaster,
  ItemCategory,
  ItemUnit,
  ItemMaterial,
  SurfaceTreatment,
  PartTypeOption,
  PartUsageOption,
  GuideRailOption,
  ItemFieldProperty,
  ItemMasterField,
  FieldDisplayCondition,
  ItemField,
  BOMItem,
  ItemSection,
  ItemPage,
  TemplateField,
  SectionTemplate,
} from '@/types/item-master.types';

import type {
  BendingDetail,
  BOMLine,
  SpecificationMaster,
  MaterialItemName,
  ItemRevision,
  ItemMaster,
  ItemCategory,
  ItemUnit,
  ItemMaterial,
  SurfaceTreatment,
  PartTypeOption,
  PartUsageOption,
  GuideRailOption,
  ItemFieldProperty,
  ItemMasterField,
  FieldDisplayCondition,
  ItemField,
  BOMItem,
  ItemSection,
  ItemPage,
  TemplateField,
  SectionTemplate,
} from '@/types/item-master.types';

// ===== Context Type =====
interface ItemMasterContextType {
  // 품목 마스터 데이터
  itemMasters: ItemMaster[];
  addItemMaster: (item: ItemMaster) => void;
  updateItemMaster: (id: string, updates: Partial<ItemMaster>) => void;
  deleteItemMaster: (id: string) => void;

  // 규격 마스터 데이터 (원자재/부자재)
  specificationMasters: SpecificationMaster[];
  addSpecificationMaster: (spec: SpecificationMaster) => void;
  updateSpecificationMaster: (id: string, updates: Partial<SpecificationMaster>) => void;
  deleteSpecificationMaster: (id: string) => void;

  // 원자재/부자재 품목명 마스터 데이터
  materialItemNames: MaterialItemName[];
  addMaterialItemName: (item: MaterialItemName) => void;
  updateMaterialItemName: (id: string, updates: Partial<MaterialItemName>) => void;
  deleteMaterialItemName: (id: string) => void;

  // 품목기준관리 - 마스터 항목
  itemMasterFields: ItemMasterField[];
  loadItemMasterFields: (fields: ItemMasterField[]) => void; // 초기 데이터 로딩용 (API 호출 없음)
  addItemMasterField: (field: Omit<ItemMasterField, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
  updateItemMasterField: (id: number, updates: Partial<ItemMasterField>) => Promise<void>;
  deleteItemMasterField: (id: number) => Promise<void>;

  // 품목기준관리 - 섹션 템플릿
  sectionTemplates: SectionTemplate[];
  loadSectionTemplates: (templates: SectionTemplate[]) => void; // 초기 데이터 로딩용 (API 호출 없음)
  addSectionTemplate: (template: Omit<SectionTemplate, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
  updateSectionTemplate: (id: number, updates: Partial<SectionTemplate>) => Promise<void>;
  deleteSectionTemplate: (id: number) => Promise<void>;

  // 품목기준관리 계층구조
  itemPages: ItemPage[];
  loadItemPages: (pages: ItemPage[]) => void; // 초기 데이터 로딩용 (API 호출 없음)
  addItemPage: (page: Omit<ItemPage, 'id' | 'created_at' | 'updated_at'>) => Promise<ItemPage>;
  updateItemPage: (id: number, updates: Partial<ItemPage>) => Promise<void>;
  deleteItemPage: (id: number) => Promise<void>;
  reorderPages: (newOrder: Array<{ id: number; order_no: number }>) => Promise<void>;
  addSectionToPage: (pageId: number, sectionData: Omit<ItemSection, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
  updateSection: (sectionId: number, updates: Partial<ItemSection>) => Promise<void>;
  deleteSection: (sectionId: number) => Promise<void>;
  reorderSections: (pageId: number, sectionIds: number[]) => Promise<void>;
  addFieldToSection: (sectionId: number, fieldData: Omit<ItemField, 'id' | 'created_at' | 'updated_at'>) => Promise<void>;
  updateField: (fieldId: number, updates: Partial<ItemField>) => Promise<void>;
  deleteField: (fieldId: number) => Promise<void>;
  reorderFields: (sectionId: number, fieldIds: number[]) => Promise<void>;

  // BOM 관리
  addBOMItem: (sectionId: number, bomData: Omit<BOMItem, 'id' | 'created_at' | 'updated_at' | 'tenant_id' | 'section_id'>) => Promise<void>;
  updateBOMItem: (bomId: number, updates: Partial<BOMItem>) => Promise<void>;
  deleteBOMItem: (bomId: number) => Promise<void>;

  // 독립 엔티티 관리 (2025-11-26 추가)
  independentSections: ItemSection[]; // 독립 섹션 목록 (page_id=null)
  independentFields: ItemField[]; // 독립 필드 목록 (section_id=null)
  independentBomItems: BOMItem[]; // 독립 BOM 목록 (section_id=null)
  loadIndependentSections: (sections: ItemSection[]) => void;
  loadIndependentFields: (fields: ItemField[]) => void;
  loadIndependentBomItems: (bomItems: BOMItem[]) => void;
  refreshIndependentSections: (isTemplate?: boolean) => Promise<void>;
  refreshIndependentFields: () => Promise<void>;
  refreshIndependentBomItems: () => Promise<void>;
  createIndependentSection: (data: Omit<IndependentSectionRequest, 'group_id'>) => Promise<ItemSection>;
  createIndependentField: (data: Omit<IndependentFieldRequest, 'group_id'>) => Promise<ItemField>;
  createIndependentBomItem: (data: Omit<IndependentBomItemRequest, 'group_id'>) => Promise<BOMItem>;

  // 링크/언링크 관리 (2025-11-26 추가)
  linkSectionToPage: (pageId: number, sectionId: number, orderNo?: number) => Promise<void>;
  unlinkSectionFromPage: (pageId: number, sectionId: number) => Promise<void>;
  linkFieldToSection: (sectionId: number, fieldId: number, orderNo?: number, fieldData?: ItemField) => Promise<void>;
  unlinkFieldFromSection: (sectionId: number, fieldId: number) => Promise<void>;

  // 사용처 조회 (2025-11-26 추가)
  getSectionUsage: (sectionId: number) => Promise<SectionUsageResponse>;
  getFieldUsage: (fieldId: number) => Promise<FieldUsageResponse>;

  // 복제 (2025-11-26 추가)
  cloneSection: (sectionId: number) => Promise<ItemSection>;
  cloneField: (fieldId: number) => Promise<ItemField>;

  // 품목 기준정보 관리
  itemCategories: ItemCategory[];
  itemUnits: ItemUnit[];
  itemMaterials: ItemMaterial[];
  surfaceTreatments: SurfaceTreatment[];
  partTypeOptions: PartTypeOption[];
  partUsageOptions: PartUsageOption[];
  guideRailOptions: GuideRailOption[];

  addItemCategory: (category: ItemCategory) => void;
  updateItemCategory: (id: string, updates: Partial<ItemCategory>) => void;
  deleteItemCategory: (id: string) => void;

  addItemUnit: (unit: ItemUnit) => void;
  updateItemUnit: (id: string, updates: Partial<ItemUnit>) => void;
  deleteItemUnit: (id: string) => void;

  addItemMaterial: (material: ItemMaterial) => void;
  updateItemMaterial: (id: string, updates: Partial<ItemMaterial>) => void;
  deleteItemMaterial: (id: string) => void;

  addSurfaceTreatment: (treatment: SurfaceTreatment) => void;
  updateSurfaceTreatment: (id: string, updates: Partial<SurfaceTreatment>) => void;
  deleteSurfaceTreatment: (id: string) => void;

  addPartTypeOption: (option: PartTypeOption) => void;
  updatePartTypeOption: (id: string, updates: Partial<PartTypeOption>) => void;
  deletePartTypeOption: (id: string) => void;

  addPartUsageOption: (option: PartUsageOption) => void;
  updatePartUsageOption: (id: string, updates: Partial<PartUsageOption>) => void;
  deletePartUsageOption: (id: string) => void;

  addGuideRailOption: (option: GuideRailOption) => void;
  updateGuideRailOption: (id: string, updates: Partial<GuideRailOption>) => void;
  deleteGuideRailOption: (id: string) => void;

  // 캐시 및 데이터 초기화
  clearCache: () => void; // TenantAwareCache 정리
  resetAllData: () => void; // 모든 state 초기화

  // 테넌트 정보
  tenantId: number | undefined; // 현재 로그인한 사용자의 테넌트 ID
}

// Create context
const ItemMasterContext = createContext<ItemMasterContextType | undefined>(undefined);

// Provider component
export function ItemMasterProvider({ children }: { children: ReactNode }) {
  // ===== Initial Data =====
  // ✅ Mock 데이터 주석 처리 - API에서 가져올 예정
  const initialItemMasters: ItemMaster[] = [];

  // ✅ 빈 배열로 초기화 - API에서 데이터 로드 예정
  const initialSpecificationMasters: SpecificationMaster[] = [];
  const initialMaterialItemNames: MaterialItemName[] = [];
  const initialItemCategories: ItemCategory[] = [];
  const initialItemUnits: ItemUnit[] = [];
  const initialItemMaterials: ItemMaterial[] = [];
  const initialSurfaceTreatments: SurfaceTreatment[] = [];
  const initialPartTypeOptions: PartTypeOption[] = [];
  const initialPartUsageOptions: PartUsageOption[] = [];
  const initialGuideRailOptions: GuideRailOption[] = [];
  const initialItemMasterFields: ItemMasterField[] = [];
  const initialItemPages: ItemPage[] = [];

  // ===== Auth & Cache Setup =====
  const { currentUser } = useAuth();
  const tenantId = currentUser?.tenant?.id;

  // ✅ TenantAwareCache 인스턴스 생성 (tenant.id 기반, SSR-safe)
  const cache = useMemo(() => {
    // 서버 환경에서는 null 반환 (sessionStorage 없음)
    if (typeof window === 'undefined') return null;

    // 클라이언트 환경에서만 캐시 생성
    return tenantId ? new TenantAwareCache(tenantId, sessionStorage, 3600000) : null;
  }, [tenantId]);

  // ===== State Management (SSR-safe) =====
  const [itemMasters, setItemMasters] = useState<ItemMaster[]>(initialItemMasters);
  const [specificationMasters, setSpecificationMasters] = useState<SpecificationMaster[]>(initialSpecificationMasters);
  const [materialItemNames, setMaterialItemNames] = useState<MaterialItemName[]>(initialMaterialItemNames);
  const [itemCategories, setItemCategories] = useState<ItemCategory[]>(initialItemCategories);
  const [itemUnits, setItemUnits] = useState<ItemUnit[]>(initialItemUnits);
  const [itemMaterials, setItemMaterials] = useState<ItemMaterial[]>(initialItemMaterials);
  const [surfaceTreatments, setSurfaceTreatments] = useState<SurfaceTreatment[]>(initialSurfaceTreatments);
  const [partTypeOptions, setPartTypeOptions] = useState<PartTypeOption[]>(initialPartTypeOptions);
  const [partUsageOptions, setPartUsageOptions] = useState<PartUsageOption[]>(initialPartUsageOptions);
  const [guideRailOptions, setGuideRailOptions] = useState<GuideRailOption[]>(initialGuideRailOptions);
  const [sectionTemplates, setSectionTemplates] = useState<SectionTemplate[]>([]);
  const [itemMasterFields, setItemMasterFields] = useState<ItemMasterField[]>(initialItemMasterFields);
  const [itemPages, setItemPages] = useState<ItemPage[]>(initialItemPages);

  // 2025-11-26 추가: 독립 엔티티 상태
  const [independentSections, setIndependentSections] = useState<ItemSection[]>([]);
  const [independentFields, setIndependentFields] = useState<ItemField[]>([]);
  const [independentBomItems, setIndependentBomItems] = useState<BOMItem[]>([]);

  // ✅ TenantAwareCache에서 초기 데이터 로드
  useEffect(() => {
    if (!cache) return; // tenant.id 없으면 초기 데이터 유지

    // ItemMasters
    const cachedItemMasters = cache.get<ItemMaster[]>('itemMasters');
    if (cachedItemMasters) setItemMasters(cachedItemMasters);

    // SpecificationMasters (버전 체크)
    if (cache.isVersionMatch('specificationMasters', '1.0')) {
      const cachedSpecs = cache.get<SpecificationMaster[]>('specificationMasters');
      if (cachedSpecs) setSpecificationMasters(cachedSpecs);
    }

    // MaterialItemNames (버전 체크)
    if (cache.isVersionMatch('materialItemNames', '1.1')) {
      const cachedMaterials = cache.get<MaterialItemName[]>('materialItemNames');
      if (cachedMaterials) setMaterialItemNames(cachedMaterials);
    }

    // ItemCategories
    const cachedCategories = cache.get<ItemCategory[]>('itemCategories');
    if (cachedCategories) setItemCategories(cachedCategories);

    // ItemUnits
    const cachedUnits = cache.get<ItemUnit[]>('itemUnits');
    if (cachedUnits) setItemUnits(cachedUnits);

    // ItemMaterials
    const cachedMaterials = cache.get<ItemMaterial[]>('itemMaterials');
    if (cachedMaterials) setItemMaterials(cachedMaterials);

    // SurfaceTreatments
    const cachedTreatments = cache.get<SurfaceTreatment[]>('surfaceTreatments');
    if (cachedTreatments) setSurfaceTreatments(cachedTreatments);

    // PartTypeOptions
    const cachedPartTypes = cache.get<PartTypeOption[]>('partTypeOptions');
    if (cachedPartTypes) setPartTypeOptions(cachedPartTypes);

    // PartUsageOptions
    const cachedPartUsages = cache.get<PartUsageOption[]>('partUsageOptions');
    if (cachedPartUsages) setPartUsageOptions(cachedPartUsages);

    // GuideRailOptions
    const cachedGuideRails = cache.get<GuideRailOption[]>('guideRailOptions');
    if (cachedGuideRails) setGuideRailOptions(cachedGuideRails);

    // SectionTemplates
    const cachedTemplates = cache.get<SectionTemplate[]>('sectionTemplates');
    if (cachedTemplates) setSectionTemplates(cachedTemplates);

    // ItemMasterFields
    const cachedFields = cache.get<ItemMasterField[]>('itemMasterFields');
    if (cachedFields) setItemMasterFields(cachedFields);

    // ItemPages
    const cachedPages = cache.get<ItemPage[]>('itemPages');
    if (cachedPages) setItemPages(cachedPages);
  }, [cache]);

  // ✅ TenantAwareCache 동기화 (상태 변경 시 자동 저장)
  useEffect(() => {
    if (cache && itemMasters !== initialItemMasters) {
      cache.set('itemMasters', itemMasters);
    }
  }, [cache, itemMasters]);

  useEffect(() => {
    if (cache && specificationMasters !== initialSpecificationMasters) {
      cache.set('specificationMasters', specificationMasters, '1.0');
    }
  }, [cache, specificationMasters]);

  useEffect(() => {
    if (cache && materialItemNames !== initialMaterialItemNames) {
      cache.set('materialItemNames', materialItemNames, '1.1');
    }
  }, [cache, materialItemNames]);

  useEffect(() => {
    if (cache && itemCategories !== initialItemCategories) {
      cache.set('itemCategories', itemCategories);
    }
  }, [cache, itemCategories]);

  useEffect(() => {
    if (cache && itemUnits !== initialItemUnits) {
      cache.set('itemUnits', itemUnits);
    }
  }, [cache, itemUnits]);

  useEffect(() => {
    if (cache && itemMaterials !== initialItemMaterials) {
      cache.set('itemMaterials', itemMaterials);
    }
  }, [cache, itemMaterials]);

  useEffect(() => {
    if (cache && surfaceTreatments !== initialSurfaceTreatments) {
      cache.set('surfaceTreatments', surfaceTreatments);
    }
  }, [cache, surfaceTreatments]);

  useEffect(() => {
    if (cache && partTypeOptions !== initialPartTypeOptions) {
      cache.set('partTypeOptions', partTypeOptions);
    }
  }, [cache, partTypeOptions]);

  useEffect(() => {
    if (cache && partUsageOptions !== initialPartUsageOptions) {
      cache.set('partUsageOptions', partUsageOptions);
    }
  }, [cache, partUsageOptions]);

  useEffect(() => {
    if (cache && guideRailOptions !== initialGuideRailOptions) {
      cache.set('guideRailOptions', guideRailOptions);
    }
  }, [cache, guideRailOptions]);

  useEffect(() => {
    if (cache) {
      cache.set('sectionTemplates', sectionTemplates);
    }
  }, [cache, sectionTemplates]);

  useEffect(() => {
    if (cache && itemMasterFields !== initialItemMasterFields) {
      cache.set('itemMasterFields', itemMasterFields);
    }
  }, [cache, itemMasterFields]);

  useEffect(() => {
    if (cache && itemPages !== initialItemPages) {
      cache.set('itemPages', itemPages);
    }
  }, [cache, itemPages]);

  // ===== CRUD Functions =====

  // ItemMaster CRUD
  const addItemMaster = (item: ItemMaster) => {
    setItemMasters(prev => [...prev, item]);
  };

  const updateItemMaster = (id: string, updates: Partial<ItemMaster>) => {
    setItemMasters(prev => prev.map(item => item.id === id ? { ...item, ...updates } : item));
  };

  const deleteItemMaster = (id: string) => {
    setItemMasters(prev => prev.filter(item => item.id !== id));
  };

  // SpecificationMaster CRUD
  const addSpecificationMaster = (spec: SpecificationMaster) => {
    setSpecificationMasters(prev => [...prev, spec]);
  };

  const updateSpecificationMaster = (id: string, updates: Partial<SpecificationMaster>) => {
    setSpecificationMasters(prev => prev.map(spec => spec.id === id ? { ...spec, ...updates } : spec));
  };

  const deleteSpecificationMaster = (id: string) => {
    setSpecificationMasters(prev => prev.filter(spec => spec.id !== id));
  };

  // MaterialItemName CRUD
  const addMaterialItemName = (item: MaterialItemName) => {
    setMaterialItemNames(prev => [...prev, item]);
  };

  const updateMaterialItemName = (id: string, updates: Partial<MaterialItemName>) => {
    setMaterialItemNames(prev => prev.map(item => item.id === id ? { ...item, ...updates } : item));
  };

  const deleteMaterialItemName = (id: string) => {
    setMaterialItemNames(prev => prev.filter(item => item.id !== id));
  };

  // ItemCategory CRUD
  const addItemCategory = (category: ItemCategory) => {
    setItemCategories(prev => [...prev, category]);
  };

  const updateItemCategory = (id: string, updates: Partial<ItemCategory>) => {
    setItemCategories(prev => prev.map(cat => cat.id === id ? { ...cat, ...updates } : cat));
  };

  const deleteItemCategory = (id: string) => {
    setItemCategories(prev => prev.filter(cat => cat.id !== id));
  };

  // ItemUnit CRUD
  const addItemUnit = (unit: ItemUnit) => {
    setItemUnits(prev => [...prev, unit]);
  };

  const updateItemUnit = (id: string, updates: Partial<ItemUnit>) => {
    setItemUnits(prev => prev.map(unit => unit.id === id ? { ...unit, ...updates } : unit));
  };

  const deleteItemUnit = (id: string) => {
    setItemUnits(prev => prev.filter(unit => unit.id !== id));
  };

  // ItemMaterial CRUD
  const addItemMaterial = (material: ItemMaterial) => {
    setItemMaterials(prev => [...prev, material]);
  };

  const updateItemMaterial = (id: string, updates: Partial<ItemMaterial>) => {
    setItemMaterials(prev => prev.map(mat => mat.id === id ? { ...mat, ...updates } : mat));
  };

  const deleteItemMaterial = (id: string) => {
    setItemMaterials(prev => prev.filter(mat => mat.id !== id));
  };

  // SurfaceTreatment CRUD
  const addSurfaceTreatment = (treatment: SurfaceTreatment) => {
    setSurfaceTreatments(prev => [...prev, treatment]);
  };

  const updateSurfaceTreatment = (id: string, updates: Partial<SurfaceTreatment>) => {
    setSurfaceTreatments(prev => prev.map(treat => treat.id === id ? { ...treat, ...updates } : treat));
  };

  const deleteSurfaceTreatment = (id: string) => {
    setSurfaceTreatments(prev => prev.filter(treat => treat.id !== id));
  };

  // PartTypeOption CRUD
  const addPartTypeOption = (option: PartTypeOption) => {
    setPartTypeOptions(prev => [...prev, option]);
  };

  const updatePartTypeOption = (id: string, updates: Partial<PartTypeOption>) => {
    setPartTypeOptions(prev => prev.map(opt => opt.id === id ? { ...opt, ...updates } : opt));
  };

  const deletePartTypeOption = (id: string) => {
    setPartTypeOptions(prev => prev.filter(opt => opt.id !== id));
  };

  // PartUsageOption CRUD
  const addPartUsageOption = (option: PartUsageOption) => {
    setPartUsageOptions(prev => [...prev, option]);
  };

  const updatePartUsageOption = (id: string, updates: Partial<PartUsageOption>) => {
    setPartUsageOptions(prev => prev.map(opt => opt.id === id ? { ...opt, ...updates } : opt));
  };

  const deletePartUsageOption = (id: string) => {
    setPartUsageOptions(prev => prev.filter(opt => opt.id !== id));
  };

  // GuideRailOption CRUD
  const addGuideRailOption = (option: GuideRailOption) => {
    setGuideRailOptions(prev => [...prev, option]);
  };

  const updateGuideRailOption = (id: string, updates: Partial<GuideRailOption>) => {
    setGuideRailOptions(prev => prev.map(opt => opt.id === id ? { ...opt, ...updates } : opt));
  };

  const deleteGuideRailOption = (id: string) => {
    setGuideRailOptions(prev => prev.filter(opt => opt.id !== id));
  };

  // ItemMasterField CRUD (임시: 로컬 state)
  /**
   * 초기 데이터 로딩용: API 호출 없이 마스터 필드를 state에 로드 (덮어쓰기)
   */
  /**
   * @deprecated 2025-11-27: item_fields로 통합됨.
   * independentFields 및 loadIndependentFields 사용 권장
   */
  const loadItemMasterFields = (fields: ItemMasterField[]) => {
    setItemMasterFields(fields);
    console.log('[ItemMasterContext] 마스터 필드 로드 완료:', fields.length);
  };

  /**
   * @deprecated 2025-11-27: item_fields로 통합됨.
   * independentFields 및 createIndependentField 사용 권장
   */
  const addItemMasterField = async (field: Omit<ItemMasterField, 'id' | 'created_at' | 'updated_at'>) => {
    try {
      // API 호출 - 2025-11-27: fields.createIndependent() 사용 (masterFields.create() deprecated)
      // Note: API가 ItemFieldResponse를 직접 반환 (wrapper 없음)
      // 2025-11-28: field_key 추가
      const response = await itemMasterApi.fields.createIndependent({
        field_name: field.field_name,
        field_key: field.field_key ?? undefined, // 2025-11-28: field_key 추가
        field_type: field.field_type,
        category: field.category ?? undefined,
        description: field.description ?? undefined,
        is_common: field.is_common,
        default_value: field.default_value ?? undefined,
        options: field.options ?? undefined,
        validation_rules: field.validation_rules ?? undefined,
        properties: field.properties ?? undefined,
      });

      // 응답 데이터 변환 및 state 업데이트
      // 2025-11-27: API가 ItemFieldResponse를 직접 반환하므로 response를 직접 사용
      // 2025-11-28: field_key 추가
      const newField: ItemMasterField = {
        id: response.id,
        tenant_id: response.tenant_id,
        field_name: response.field_name,
        field_key: response.field_key, // 2025-11-28: field_key 추가
        field_type: response.field_type,
        category: response.category,
        description: response.description,
        is_common: response.is_common,
        default_value: response.default_value,
        options: response.options,
        validation_rules: response.validation_rules,
        properties: response.properties,
        created_by: response.created_by,
        updated_by: response.updated_by,
        created_at: response.created_at,
        updated_at: response.updated_at,
      };

      setItemMasterFields(prev => [...prev, newField]);
      console.log('[ItemMasterContext] 마스터 필드 생성 성공:', newField.id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 마스터 필드 생성 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * @deprecated 2025-11-27: item_fields로 통합됨.
   * independentFields 및 updateIndependentField 사용 권장
   */
  const updateItemMasterField = async (id: number, updates: Partial<ItemMasterField>) => {
    try {
      // API 호출 - 2025-11-27: fields.update() 사용 (masterFields.update() deprecated)
      const requestData: any = {};
      if (updates.field_name !== undefined) requestData.field_name = updates.field_name;
      if (updates.field_key !== undefined) requestData.field_key = updates.field_key; // 2025-11-28: field_key 추가
      if (updates.field_type !== undefined) requestData.field_type = updates.field_type;
      if (updates.category !== undefined) requestData.category = updates.category;
      if (updates.description !== undefined) requestData.description = updates.description;
      if (updates.is_common !== undefined) requestData.is_common = updates.is_common;
      if (updates.default_value !== undefined) requestData.default_value = updates.default_value;
      if (updates.options !== undefined) requestData.options = updates.options;
      if (updates.validation_rules !== undefined) requestData.validation_rules = updates.validation_rules;
      if (updates.properties !== undefined) requestData.properties = updates.properties;

      const response = await itemMasterApi.fields.update(id, requestData);

      if (!response.success || !response.data) {
        throw new Error(response.message || '마스터 필드 수정 실패');
      }

      // state 업데이트 - 2025-11-28: field_key 추가
      setItemMasterFields(prev => prev.map(field =>
        field.id === id ? {
          ...field,
          field_name: response.data!.field_name,
          field_key: response.data!.field_key, // 2025-11-28: field_key 추가
          field_type: response.data!.field_type,
          category: response.data!.category,
          description: response.data!.description,
          is_common: response.data!.is_common,
          default_value: response.data!.default_value,
          options: response.data!.options,
          validation_rules: response.data!.validation_rules,
          properties: response.data!.properties,
          updated_at: response.data!.updated_at,
        } : field
      ));

      // 2025-11-27: 섹션탭/계층구조 실시간 반영
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      // 2025-11-28: field_key 추가
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        fields: (section.fields || []).map(field =>
          field.id === id ? {
            ...field,
            field_name: response.data!.field_name,
            field_key: response.data!.field_key, // 2025-11-28: field_key 추가
            field_type: response.data!.field_type,
            is_required: response.data!.is_required,
            default_value: response.data!.default_value,
            options: response.data!.options,
            validation_rules: response.data!.validation_rules,
            properties: response.data!.properties,
            updated_at: response.data!.updated_at,
          } : field
        )
      })));

      // 2025-11-28: field_key 추가
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          fields: (section.fields || []).map(field =>
            field.id === id ? {
              ...field,
              field_name: response.data!.field_name,
              field_key: response.data!.field_key, // 2025-11-28: field_key 추가
              field_type: response.data!.field_type,
              is_required: response.data!.is_required,
              default_value: response.data!.default_value,
              options: response.data!.options,
              validation_rules: response.data!.validation_rules,
              properties: response.data!.properties,
              updated_at: response.data!.updated_at,
            } : field
          )
        }))
      })));

      console.log('[ItemMasterContext] 마스터 필드 수정 성공:', id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 마스터 필드 수정 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * @deprecated 2025-11-27: item_fields로 통합됨.
   * independentFields 및 deleteIndependentField 사용 권장
   */
  const deleteItemMasterField = async (id: number) => {
    try {
      // API 호출 - 2025-11-27: fields.delete() 사용 (masterFields.delete() deprecated)
      const response = await itemMasterApi.fields.delete(id);

      if (!response.success) {
        throw new Error(response.message || '마스터 필드 삭제 실패');
      }

      // state 업데이트
      setItemMasterFields(prev => prev.filter(field => field.id !== id));

      // 2025-11-27: 섹션탭/계층구조 실시간 반영
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        fields: (section.fields || []).filter(field => field.id !== id)
      })));

      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          fields: (section.fields || []).filter(field => field.id !== id)
        }))
      })));

      console.log('[ItemMasterContext] 마스터 필드 삭제 성공:', id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 마스터 필드 삭제 실패:', errorMessage);
      throw error;
    }
  };

  // SectionTemplate CRUD with API
  /**
   * 초기 데이터 로딩용: API 호출 없이 섹션 템플릿을 state에 로드 (덮어쓰기)
   */
  const loadSectionTemplates = (templates: SectionTemplate[]) => {
    setSectionTemplates(templates);
    console.log('[ItemMasterContext] 섹션 템플릿 로드 완료:', templates.length);
  };

  const addSectionTemplate = async (template: Omit<SectionTemplate, 'id' | 'created_at' | 'updated_at'>) => {
    try {
      // 프론트엔드 형식 → API 형식 변환
      // template_name → title, section_type → type
      const apiType = template.section_type === 'BOM' ? 'bom' : 'fields';

      const response = await itemMasterApi.templates.create({
        title: template.template_name,
        type: apiType,
        description: template.description ?? undefined,
        is_default: false, // 기본값
      });

      if (!response.success || !response.data) {
        throw new Error(response.message || '섹션 템플릿 생성 실패');
      }

      // API 응답 → 프론트엔드 형식 변환
      // title → template_name, type → section_type
      const SECTION_TYPE_MAP: Record<string, 'BASIC' | 'BOM' | 'CUSTOM'> = {
        fields: 'BASIC',
        bom: 'BOM',
      };

      const newTemplate: SectionTemplate = {
        id: response.data.id,
        tenant_id: response.data.tenant_id,
        template_name: response.data.title,
        section_type: SECTION_TYPE_MAP[response.data.type] || 'BASIC',
        description: response.data.description,
        default_fields: null,
        category: template.category,
        fields: template.fields,
        bomItems: template.bomItems,
        created_by: response.data.created_by,
        updated_by: response.data.updated_by,
        created_at: response.data.created_at,
        updated_at: response.data.updated_at,
      };

      setSectionTemplates(prev => [...prev, newTemplate]);
      console.log('[ItemMasterContext] 섹션 템플릿 생성 성공:', newTemplate.id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 템플릿 생성 실패:', errorMessage);
      throw error;
    }
  };

  const updateSectionTemplate = async (id: number, updates: Partial<SectionTemplate>) => {
    try {
      // default_fields, fields, category, bomItems는 로컬에서만 관리 (API 미지원)
      const localOnlyUpdates = ['default_fields', 'fields', 'category', 'bomItems'];
      const hasApiUpdates = Object.keys(updates).some(key => !localOnlyUpdates.includes(key));
      const hasLocalUpdates = Object.keys(updates).some(key => localOnlyUpdates.includes(key));

      // API 호출이 필요한 경우에만 API 요청
      if (hasApiUpdates) {
        // API 요청 형식으로 변환 (frontend → API)
        // frontend: template_name, section_type
        // API: title, type
        const requestData: any = {};
        if (updates.template_name !== undefined) requestData.title = updates.template_name;
        if (updates.section_type !== undefined) {
          // section_type 변환: 'BASIC' | 'CUSTOM' → 'fields', 'BOM' → 'bom'
          requestData.type = updates.section_type === 'BOM' ? 'bom' : 'fields';
        }
        if (updates.description !== undefined) requestData.description = updates.description;

        const response = await itemMasterApi.templates.update(id, requestData);

        if (!response.success || !response.data) {
          throw new Error(response.message || '섹션 템플릿 수정 실패');
        }

        // state 업데이트 (API 응답 → frontend 형식으로 변환)
        // API 응답: title, type ('fields' | 'bom')
        // Frontend 형식: template_name, section_type ('BASIC' | 'BOM' | 'CUSTOM')
        const SECTION_TYPE_MAP: Record<string, 'BASIC' | 'BOM' | 'CUSTOM'> = {
          fields: 'BASIC',
          bom: 'BOM',
        };

        // 1. sectionTemplates 업데이트 (섹션 탭)
        setSectionTemplates(prev => prev.map(template =>
          template.id === id ? {
            ...template,
            template_name: response.data!.title,
            section_type: SECTION_TYPE_MAP[response.data!.type] || 'BASIC',
            description: response.data!.description,
            updated_at: response.data!.updated_at,
          } : template
        ));

        // 2. itemPages 업데이트 (계층구조 탭) - 같은 ID의 섹션도 동기화
        setItemPages(prev => prev.map(page => ({
          ...page,
          sections: page.sections.map(section =>
            section.id === id
              ? { ...section, title: response.data!.title }
              : section
          )
        })));

        console.log('[ItemMasterContext] 섹션 템플릿 수정 성공 (양방향 동기화):', id);
      }

      // 로컬 전용 필드 업데이트 (default_fields, fields, category, bomItems)
      if (hasLocalUpdates) {
        setSectionTemplates(prev => prev.map(template => {
          if (template.id !== id) return template;

          const updatedTemplate = { ...template };

          // default_fields 업데이트 시 fields도 같이 업데이트
          if (updates.default_fields !== undefined) {
            updatedTemplate.default_fields = updates.default_fields;
            updatedTemplate.fields = updates.default_fields as TemplateField[];
          }
          if (updates.fields !== undefined) {
            updatedTemplate.fields = updates.fields;
            updatedTemplate.default_fields = updates.fields;
          }
          if (updates.category !== undefined) {
            updatedTemplate.category = updates.category;
          }
          if (updates.bomItems !== undefined) {
            updatedTemplate.bomItems = updates.bomItems;
          }

          return updatedTemplate;
        }));

        console.log('[ItemMasterContext] 섹션 템플릿 수정 성공 (로컬):', id, Object.keys(updates).filter(k => localOnlyUpdates.includes(k)));
      }
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 템플릿 수정 실패:', errorMessage);
      throw error;
    }
  };

  const deleteSectionTemplate = async (id: number) => {
    try {
      // API 호출
      const response = await itemMasterApi.templates.delete(id);

      if (!response.success) {
        throw new Error(response.message || '섹션 템플릿 삭제 실패');
      }

      // 1. sectionTemplates 업데이트 (섹션 탭)
      setSectionTemplates(prev => prev.filter(template => template.id !== id));

      // 2. itemPages 업데이트 (계층구조 탭) - 같은 ID의 섹션도 삭제
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.filter(section => section.id !== id)
      })));

      console.log('[ItemMasterContext] 섹션 템플릿 삭제 성공 (양방향 동기화):', id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 템플릿 삭제 실패:', errorMessage);
      throw error;
    }
  };

  // ItemPage CRUD with API

  /**
   * 초기 데이터 로딩용: API 호출 없이 페이지 데이터를 state에 로드 (덮어쓰기)
   * (이미 백엔드에서 받아온 데이터를 로드할 때 사용)
   */
  const loadItemPages = (pages: ItemPage[]) => {
    setItemPages(pages);  // 덮어쓰기 (append가 아님!)
    console.log('[ItemMasterContext] 페이지 데이터 로드 완료:', pages.length);
  };

  /**
   * 새 페이지 생성: API 호출 + state 업데이트
   * (사용자가 새 페이지를 만들 때 사용)
   * @returns 생성된 페이지 반환
   */
  const addItemPage = async (pageData: Omit<ItemPage, 'id' | 'created_at' | 'updated_at'>): Promise<ItemPage> => {
    try {
      // API 요청 데이터 변환
      const requestData: ItemPageRequest = {
        page_name: pageData.page_name,
        item_type: pageData.item_type,
        absolute_path: pageData.absolute_path || '',
      };

      // API 호출
      const response = await itemMasterApi.pages.create(requestData);

      // 응답 데이터 변환 및 state 업데이트
      const newPage = transformPageResponse(response);
      setItemPages(prev => [...prev, newPage]);

      console.log('[ItemMasterContext] 페이지 생성 성공:', newPage);
      return newPage;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 페이지 생성 실패:', errorMessage);
      throw error;
    }
  };

  const updateItemPage = async (id: number, updates: Partial<ItemPage>) => {
    try {
      // API 요청 데이터 변환
      const requestData: Partial<ItemPageRequest> = {};
      if (updates.page_name) requestData.page_name = updates.page_name;
      if (updates.absolute_path !== undefined) requestData.absolute_path = updates.absolute_path;

      // API 호출
      const response = await itemMasterApi.pages.update(id, requestData);

      if (!response.success || !response.data) {
        throw new Error(response.message || '페이지 수정 실패');
      }

      // ⚠️ 2026-01-06: 변경 요청한 필드만 업데이트
      // API 응답(response.data)에 sections가 빈 배열로 오기 때문에
      // 응답 전체를 덮어쓰면 기존 섹션이 사라지는 버그 발생
      // → 변경한 필드(page_name, absolute_path)만 업데이트하고 나머지는 기존 값 유지
      setItemPages(prev => prev.map(page => {
        if (page.id === id) {
          return {
            ...page,
            page_name: updates.page_name ?? page.page_name,
            absolute_path: updates.absolute_path ?? page.absolute_path,
          };
        }
        return page;
      }));

      console.log('[ItemMasterContext] 페이지 수정 성공:', { id, updates });
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 페이지 수정 실패:', errorMessage);
      throw error;
    }
  };

  const deleteItemPage = async (id: number) => {
    try {
      // 2025-12-01: 페이지 삭제 전에 해당 페이지의 섹션들(필드 포함)을 저장
      // refreshIndependentSections()는 백엔드에서 섹션만 가져오고 필드 데이터는 포함하지 않음
      // 따라서 직접 섹션 데이터를 보존하여 필드 연결을 유지해야 함
      const pageToDelete = itemPages.find(page => page.id === id);
      const sectionsToPreserve = pageToDelete?.sections || [];

      // API 호출
      const response = await itemMasterApi.pages.delete(id);

      if (!response.success) {
        throw new Error(response.message || '페이지 삭제 실패');
      }

      // state 업데이트
      setItemPages(prev => prev.filter(page => page.id !== id));

      // 2025-12-01: 페이지의 섹션들을 독립 섹션으로 이동 (필드 데이터 유지)
      // refreshIndependentSections() 대신 직접 섹션 추가하여 필드 연결 보존
      if (sectionsToPreserve.length > 0) {
        setIndependentSections(prev => {
          // 기존 독립 섹션 ID 목록
          const existingIds = new Set(prev.map(s => s.id));
          // 중복되지 않는 섹션만 추가 (필드 포함된 원본 데이터)
          const newSections = sectionsToPreserve.filter(s => !existingIds.has(s.id));
          console.log('[ItemMasterContext] 페이지 삭제 - 섹션을 독립 섹션으로 이동:', {
            preserved: newSections.length,
            withFields: newSections.map(s => ({
              id: s.id,
              title: s.title,
              fieldCount: s.fields?.length || 0
            }))
          });
          return [...prev, ...newSections];
        });
      }

      console.log('[ItemMasterContext] 페이지 삭제 성공:', id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 페이지 삭제 실패:', errorMessage);
      throw error;
    }
  };

  const reorderPages = async (newOrder: Array<{ id: number; order_no: number }>) => {
    try {
      // Optimistic UI 업데이트 (즉시 반영)
      setItemPages(prev => {
        const updated = [...prev];
        updated.sort((a, b) => {
          const orderA = newOrder.find(o => o.id === a.id)?.order_no ?? 0;
          const orderB = newOrder.find(o => o.id === b.id)?.order_no ?? 0;
          return orderA - orderB;
        });
        return updated.map(page => {
          const newOrderNo = newOrder.find(o => o.id === page.id)?.order_no;
          return newOrderNo !== undefined ? { ...page, order_no: newOrderNo } : page;
        });
      });

      // API 호출
      const response = await itemMasterApi.pages.reorder({ page_orders: newOrder });

      if (!response.success || !response.data) {
        throw new Error(response.message || '페이지 순서 변경 실패');
      }

      // API 응답으로 최종 업데이트
      const reorderedPages = response.data.map(transformPageResponse);
      setItemPages(reorderedPages);

      console.log('[ItemMasterContext] 페이지 순서 변경 성공');
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 페이지 순서 변경 실패:', errorMessage);

      // 실패 시 이전 상태로 롤백
      // 여기서는 페이지 전체를 다시 로드하는 것이 더 안전할 수 있음
      throw error;
    }
  };

  // Section CRUD with API
  const addSectionToPage = async (pageId: number, sectionData: Omit<ItemSection, 'id' | 'created_at' | 'updated_at'>) => {
    try {
      // API 호출
      const response = await itemMasterApi.sections.create(pageId, {
        title: sectionData.title,
        type: sectionData.section_type === 'BOM' ? 'bom' : 'fields',
      });

      if (!response.success || !response.data) {
        throw new Error(response.message || '섹션 생성 실패');
      }

      // 응답 데이터 변환 및 state 업데이트
      const newSection = transformSectionResponse(response.data);
      setItemPages(prev => prev.map(page =>
        page.id === pageId
          ? { ...page, sections: [...page.sections, newSection] }
          : page
      ));

      console.log('[ItemMasterContext] 섹션 생성 성공:', newSection);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 생성 실패:', errorMessage);
      throw error;
    }
  };

  const updateSection = async (sectionId: number, updates: Partial<ItemSection>) => {
    try {
      // API 요청 데이터 변환
      const requestData: any = {};
      if (updates.title) requestData.title = updates.title;
      // page_id 변경 지원 (연결 해제 시 null)
      if ('page_id' in updates) requestData.page_id = updates.page_id;

      // API 호출
      const response = await itemMasterApi.sections.update(sectionId, requestData);

      if (!response.success || !response.data) {
        throw new Error(response.message || '섹션 수정 실패');
      }

      // 응답 데이터 변환
      const updatedSection = transformSectionResponse(response.data);

      // page_id가 null로 변경되면 (연결 해제) 페이지에서 섹션 제거 + 독립 섹션에 추가
      if (updates.page_id === null) {
        // 1. itemPages에서 해당 섹션 찾아서 제거
        let unlinkedSection: ItemSection | null = null;
        setItemPages(prev => prev.map(page => {
          const foundSection = page.sections.find(s => s.id === sectionId);
          if (foundSection) {
            unlinkedSection = { ...foundSection, page_id: null };
          }
          return {
            ...page,
            sections: page.sections.filter(section => section.id !== sectionId)
          };
        }));

        // 2. 독립 섹션에 추가 (섹션 탭에서 보이도록)
        if (unlinkedSection) {
          setIndependentSections(prev => [...prev, unlinkedSection!]);
        }

        console.log('[ItemMasterContext] 섹션 연결 해제 (계층구조→독립):', sectionId);
      } else {
        // 일반 수정: 섹션 데이터 업데이트
        setItemPages(prev => prev.map(page => ({
          ...page,
          sections: page.sections.map(section =>
            section.id === sectionId ? updatedSection : section
          )
        })));
      }

      // 2. sectionTemplates 업데이트 (섹션 탭) - 같은 ID의 템플릿도 동기화
      setSectionTemplates(prev => prev.map(template =>
        template.id === sectionId
          ? { ...template, template_name: updatedSection.title }
          : template
      ));

      // 3. independentSections 업데이트 (독립 섹션) - sectionsAsTemplates useMemo 재계산 트리거
      setIndependentSections(prev => prev.map(section =>
        section.id === sectionId
          ? { ...section, ...updatedSection }
          : section
      ));

      console.log('[ItemMasterContext] 섹션 수정 성공 (3방향 동기화):', updatedSection);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 수정 실패:', errorMessage);
      throw error;
    }
  };

  const deleteSection = async (sectionId: number) => {
    try {
      // API 호출
      const response = await itemMasterApi.sections.delete(sectionId);

      if (!response.success) {
        throw new Error(response.message || '섹션 삭제 실패');
      }

      // 1. itemPages 업데이트 (계층구조 탭)
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.filter(section => section.id !== sectionId)
      })));

      // 2. sectionTemplates 업데이트 (섹션 탭) - 같은 ID의 템플릿도 삭제
      setSectionTemplates(prev => prev.filter(template => template.id !== sectionId));

      // 3. independentSections 업데이트 (독립 섹션) - sectionsAsTemplates useMemo 재계산 트리거
      setIndependentSections(prev => prev.filter(section => section.id !== sectionId));

      console.log('[ItemMasterContext] 섹션 삭제 성공 (3방향 동기화):', sectionId);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 삭제 실패:', errorMessage);
      throw error;
    }
  };

  const reorderSections = async (pageId: number, sectionIds: number[]) => {
    try {
      // 요청 데이터 구성 (백엔드는 'items' 필드를 기대함)
      const requestData = {
        items: sectionIds.map((id, index) => ({ id, order_no: index + 1 }))  // order_no는 1부터 시작
      };
      console.log('[ItemMasterContext] 섹션 순서 변경 요청:', {
        pageId,
        sectionIds,
        requestData
      });

      // API 호출
      const response = await itemMasterApi.sections.reorder(pageId, requestData);
      console.log('[ItemMasterContext] 섹션 순서 변경 응답:', response);

      if (!response.success) {
        throw new Error(response.message || '섹션 순서 변경 실패');
      }

      // 응답 데이터 처리 - 배열 또는 객체 형태 모두 지원
      // 백엔드 응답 형식에 따라 처리
      if (response.data && Array.isArray(response.data)) {
        // 배열 형태: 변경된 섹션 목록 반환
        const reorderedSections = response.data.map(transformSectionResponse);
        setItemPages(prev => prev.map(page =>
          page.id === pageId
            ? { ...page, sections: reorderedSections }
            : page
        ));
      } else {
        // 배열이 아닌 경우: 로컬 state에서 순서만 업데이트
        setItemPages(prev => prev.map(page => {
          if (page.id !== pageId) return page;

          // sectionIds 순서대로 섹션 재정렬
          const sectionMap = new Map(page.sections.map(s => [s.id, s]));
          const reorderedSections = sectionIds
            .map((id, index) => {
              const section = sectionMap.get(id);
              return section ? { ...section, order_no: index + 1 } : null;
            })
            .filter((s): s is ItemSection => s !== null);

          return { ...page, sections: reorderedSections };
        }));
      }

      console.log('[ItemMasterContext] 섹션 순서 변경 성공');
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 순서 변경 실패:', errorMessage);
      throw error;
    }
  };

  // Field CRUD with API
  const addFieldToSection = async (sectionId: number, fieldData: Omit<ItemField, 'id' | 'created_at' | 'updated_at'>) => {
    try {
      // API 호출 (null → undefined 변환)
      // 2025-11-28: field_key 추가
      const response = await itemMasterApi.fields.create(sectionId, {
        field_name: fieldData.field_name,
        field_key: fieldData.field_key ?? undefined, // 2025-11-28: field_key 추가
        field_type: fieldData.field_type,
        is_required: fieldData.is_required,
        default_value: fieldData.default_value ?? undefined,
        placeholder: fieldData.placeholder ?? undefined,
        display_condition: fieldData.display_condition ?? undefined,
        validation_rules: fieldData.validation_rules ?? undefined,
        options: fieldData.options ?? undefined,
        properties: fieldData.properties ?? undefined,
      });

      if (!response.success || !response.data) {
        throw new Error(response.message || '필드 생성 실패');
      }

      // 응답 데이터 변환 및 state 업데이트
      // 2025-11-28: field_key 추가
      const newField: ItemField = {
        id: response.data.id,
        tenant_id: response.data.tenant_id,
        section_id: response.data.section_id,
        master_field_id: response.data.master_field_id,
        field_name: response.data.field_name,
        field_key: response.data.field_key, // 2025-11-28: field_key 추가
        field_type: response.data.field_type,
        order_no: response.data.order_no,
        is_required: response.data.is_required,
        default_value: response.data.default_value,
        placeholder: response.data.placeholder,
        display_condition: response.data.display_condition,
        validation_rules: response.data.validation_rules,
        options: response.data.options,
        properties: response.data.properties,
        created_at: response.data.created_at,
        updated_at: response.data.updated_at,
      };

      console.log('[addFieldToSection] Before setItemPages, sectionId:', sectionId, 'newField:', newField.field_name);

      // 2025-11-27: itemPages 업데이트 (페이지에 연결된 섹션)
      setItemPages(prev => {
        const updated = prev.map(page => ({
          ...page,
          sections: page.sections.map(section =>
            section.id === sectionId
              ? { ...section, fields: [...(section.fields || []), newField] }
              : section
          )
        }));
        console.log('[addFieldToSection] After setItemPages, updated pages:', updated.map(p => ({
          id: p.id,
          sections: p.sections.map(s => ({
            id: s.id,
            title: s.title,
            fieldsCount: s.fields?.length || 0
          }))
        })));
        return updated;
      });

      // 2025-11-27: independentSections도 업데이트 (독립 섹션에 필드 추가된 경우)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존하므로
      // 두 상태 모두 업데이트해야 모든 탭에서 실시간 동기화됨
      setIndependentSections(prev => {
        const updated = prev.map(section =>
          section.id === sectionId
            ? { ...section, fields: [...(section.fields || []), newField] }
            : section
        );
        console.log('[addFieldToSection] After setIndependentSections, updated sections:', updated.map(s => ({
          id: s.id,
          title: s.title,
          fieldsCount: s.fields?.length || 0
        })));
        return updated;
      });

      // 2025-11-27: 항목탭/속성탭 실시간 동기화
      // ItemField → ItemMasterField 변환하여 추가
      // 2025-11-28: field_key 추가
      const newMasterField: ItemMasterField = {
        id: newField.id,
        tenant_id: newField.tenant_id ?? 0,
        field_name: newField.field_name,
        field_key: newField.field_key, // 2025-11-28: field_key 추가
        field_type: newField.field_type,
        description: newField.placeholder ?? null,
        category: null,
        is_common: false,
        is_required: newField.is_required,
        default_value: newField.default_value ?? null,
        options: newField.options ?? null,
        validation_rules: newField.validation_rules ?? null,
        properties: newField.properties ?? null,
        created_by: null,
        updated_by: null,
        created_at: newField.created_at,
        updated_at: newField.updated_at,
      };
      setItemMasterFields(prev => [...prev, newMasterField]);

      console.log('[ItemMasterContext] 필드 생성 성공:', newField.id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 생성 실패:', errorMessage);
      throw error;
    }
  };

  const updateField = async (fieldId: number, updates: Partial<ItemField>) => {
    try {
      // API 호출 (null → undefined 변환)
      const requestData: any = {};
      if (updates.field_name !== undefined) requestData.field_name = updates.field_name;
      // 2025-11-28: field_key 추가
      if (updates.field_key !== undefined) requestData.field_key = updates.field_key ?? undefined;
      if (updates.field_type !== undefined) requestData.field_type = updates.field_type;
      if (updates.is_required !== undefined) requestData.is_required = updates.is_required;
      if (updates.default_value !== undefined) requestData.default_value = updates.default_value ?? undefined;
      if (updates.placeholder !== undefined) requestData.placeholder = updates.placeholder ?? undefined;
      // 2025-11-27: display_condition도 API로 전송 (JSON 타입으로 저장)
      if (updates.display_condition !== undefined) requestData.display_condition = updates.display_condition ?? undefined;
      if (updates.validation_rules !== undefined) requestData.validation_rules = updates.validation_rules ?? undefined;
      if (updates.options !== undefined) requestData.options = updates.options ?? undefined;
      if (updates.properties !== undefined) requestData.properties = updates.properties ?? undefined;

      const response = await itemMasterApi.fields.update(fieldId, requestData);

      if (!response.success || !response.data) {
        throw new Error(response.message || '필드 수정 실패');
      }

      // state 업데이트
      // 2025-11-28: field_key 추가
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          fields: (section.fields || []).map(field =>
            field.id === fieldId ? {
              ...field,
              field_name: response.data!.field_name,
              field_key: response.data!.field_key, // 2025-11-28: field_key 추가
              field_type: response.data!.field_type,
              is_required: response.data!.is_required,
              default_value: response.data!.default_value,
              placeholder: response.data!.placeholder,
              display_condition: response.data!.display_condition,
              validation_rules: response.data!.validation_rules,
              options: response.data!.options,
              properties: response.data!.properties,
              updated_at: response.data!.updated_at,
            } : field
          )
        }))
      })));

      // 2025-11-27: itemMasterFields 동기화 (항목탭 실시간 반영)
      // ItemField → ItemMasterField 타입 매핑
      // 2025-11-28: field_key 추가
      setItemMasterFields(prev => prev.map(mf =>
        mf.id === fieldId ? {
          ...mf,
          field_name: response.data!.field_name,
          field_key: response.data!.field_key, // 2025-11-28: field_key 추가
          field_type: response.data!.field_type,
          is_required: response.data!.is_required,
          default_value: response.data!.default_value ?? null,
          description: response.data!.placeholder ?? null, // placeholder → description
          validation_rules: response.data!.validation_rules ?? null,
          options: response.data!.options ?? null,
          properties: response.data!.properties ?? null,
          updated_at: response.data!.updated_at,
        } : mf
      ));

      // 2025-11-27: independentFields 동기화 (섹션에 연결되지 않은 필드)
      // 2025-11-28: field_key 추가
      setIndependentFields(prev => prev.map(field =>
        field.id === fieldId ? {
          ...field,
          field_name: response.data!.field_name,
          field_key: response.data!.field_key, // 2025-11-28: field_key 추가
          field_type: response.data!.field_type,
          is_required: response.data!.is_required,
          default_value: response.data!.default_value,
          placeholder: response.data!.placeholder,
          display_condition: response.data!.display_condition,
          validation_rules: response.data!.validation_rules,
          options: response.data!.options,
          properties: response.data!.properties,
          updated_at: response.data!.updated_at,
        } : field
      ));

      // 2025-11-27: independentSections 동기화 (섹션탭 실시간 반영)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      // 2025-11-28: field_key 추가
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        fields: (section.fields || []).map(field =>
          field.id === fieldId ? {
            ...field,
            field_name: response.data!.field_name,
            field_key: response.data!.field_key, // 2025-11-28: field_key 추가
            field_type: response.data!.field_type,
            is_required: response.data!.is_required,
            default_value: response.data!.default_value,
            placeholder: response.data!.placeholder,
            display_condition: response.data!.display_condition,
            validation_rules: response.data!.validation_rules,
            options: response.data!.options,
            properties: response.data!.properties,
            updated_at: response.data!.updated_at,
          } : field
        )
      })));

      console.log('[ItemMasterContext] 필드 수정 성공:', fieldId);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 수정 실패:', errorMessage);
      throw error;
    }
  };

  const deleteField = async (fieldId: number) => {
    try {
      // API 호출
      const response = await itemMasterApi.fields.delete(fieldId);

      if (!response.success) {
        throw new Error(response.message || '필드 삭제 실패');
      }

      // state 업데이트
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          fields: (section.fields || []).filter(field => field.id !== fieldId)
        }))
      })));

      // 2025-11-27: itemMasterFields 동기화 (항목탭 실시간 반영)
      setItemMasterFields(prev => prev.filter(mf => mf.id !== fieldId));

      // 2025-11-27: independentFields 동기화
      setIndependentFields(prev => prev.filter(f => f.id !== fieldId));

      // 2025-11-27: independentSections 동기화 (섹션탭/계층구조 실시간 반영)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        fields: (section.fields || []).filter(field => field.id !== fieldId)
      })));

      console.log('[ItemMasterContext] 필드 삭제 성공:', fieldId);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 삭제 실패:', errorMessage);
      throw error;
    }
  };

  const reorderFields = async (sectionId: number, fieldIds: number[]) => {
    try {
      // 2025-12-03: 검증 추가 - 빈 배열이면 스킵
      if (!fieldIds || fieldIds.length === 0) {
        console.warn('[ItemMasterContext] reorderFields 스킵: 필드 ID 배열이 비어있음');
        return;
      }

      // 2025-12-03: 검증 추가 - 유효하지 않은 ID 필터링 (null, undefined, NaN 제거)
      const validFieldIds = fieldIds.filter(id => id !== null && id !== undefined && !isNaN(id));
      if (validFieldIds.length !== fieldIds.length) {
        console.warn('[ItemMasterContext] reorderFields: 유효하지 않은 필드 ID 제거됨', {
          original: fieldIds,
          valid: validFieldIds
        });
      }

      if (validFieldIds.length === 0) {
        console.warn('[ItemMasterContext] reorderFields 스킵: 유효한 필드 ID가 없음');
        return;
      }

      // 요청 데이터 구성 (2025-12-03: field_orders → items로 변경, 백엔드와 동일하게)
      const requestData = {
        items: validFieldIds.map((id, index) => ({ id, order_no: index + 1 }))  // order_no는 1부터 시작
      };

      // API 호출
      const response = await itemMasterApi.fields.reorder(sectionId, requestData);

      if (!response.success) {
        throw new Error(response.message || '필드 순서 변경 실패');
      }

      // 2025-12-03: 백엔드가 'success' 문자열만 반환하므로 로컬 state에서 순서 업데이트
      // validFieldIds 순서대로 필드 재정렬
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => {
          if (section.id !== sectionId) return section;

          // fieldIds 순서대로 필드 재정렬
          const fieldMap = new Map((section.fields || []).map(f => [f.id, f]));
          const reorderedFields = validFieldIds
            .map((id, index) => {
              const field = fieldMap.get(id);
              return field ? { ...field, order_no: index + 1 } : null;
            })
            .filter((f): f is ItemField => f !== null);

          return { ...section, fields: reorderedFields };
        })
      })));

      // 2025-12-03: 섹션탭 실시간 반영 추가
      setIndependentSections(prev => prev.map(section => {
        if (section.id !== sectionId) return section;

        const fieldMap = new Map((section.fields || []).map(f => [f.id, f]));
        const reorderedFields = validFieldIds
          .map((id, index) => {
            const field = fieldMap.get(id);
            return field ? { ...field, order_no: index + 1 } : null;
          })
          .filter((f): f is ItemField => f !== null);

        return { ...section, fields: reorderedFields };
      }));
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 순서 변경 실패:', errorMessage);
      // 2025-12-03: ApiError인 경우 상세 정보 출력
      if (error instanceof ApiError && error.errors) {
        console.error('[ItemMasterContext] 상세 검증 에러:', error.errors);
      }
      throw error;
    }
  };

  // BOM CRUD with API
  const addBOMItem = async (sectionId: number, bomData: Omit<BOMItem, 'id' | 'created_at' | 'updated_at' | 'tenant_id' | 'section_id'>) => {
    try {
      // API 호출 (null → undefined 변환)
      const response = await itemMasterApi.bomItems.create(sectionId, {
        item_code: bomData.item_code ?? undefined,
        item_name: bomData.item_name,
        quantity: bomData.quantity,
        unit: bomData.unit ?? undefined,
        unit_price: bomData.unit_price ?? undefined,
        total_price: bomData.total_price ?? undefined,
        spec: bomData.spec ?? undefined,
        note: bomData.note ?? undefined,
      });

      if (!response.success || !response.data) {
        throw new Error(response.message || 'BOM 항목 생성 실패');
      }

      // 응답 데이터 변환 및 state 업데이트
      const newBOM: BOMItem = {
        id: response.data.id,
        tenant_id: response.data.tenant_id,
        section_id: response.data.section_id,
        item_code: response.data.item_code,
        item_name: response.data.item_name,
        quantity: response.data.quantity,
        unit: response.data.unit,
        unit_price: response.data.unit_price,
        total_price: response.data.total_price,
        spec: response.data.spec,
        note: response.data.note,
        created_at: response.data.created_at,
        updated_at: response.data.updated_at,
      };

      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section =>
          section.id === sectionId
            ? { ...section, bom_items: [...(section.bom_items || []), newBOM] }
            : section
        )
      })));

      // 2025-11-27: independentSections 동기화 (섹션탭 실시간 반영)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section =>
        section.id === sectionId
          ? { ...section, bom_items: [...(section.bom_items || []), newBOM] }
          : section
      ));

      console.log('[ItemMasterContext] BOM 항목 생성 성공 (양방향 동기화):', newBOM.id);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] BOM 항목 생성 실패:', errorMessage);
      throw error;
    }
  };

  const updateBOMItem = async (bomId: number, updates: Partial<BOMItem>) => {
    try {
      // API 호출 (null → undefined 변환)
      const requestData: any = {};
      if (updates.item_code !== undefined) requestData.item_code = updates.item_code ?? undefined;
      if (updates.item_name !== undefined) requestData.item_name = updates.item_name;
      if (updates.quantity !== undefined) requestData.quantity = updates.quantity;
      if (updates.unit !== undefined) requestData.unit = updates.unit ?? undefined;
      if (updates.unit_price !== undefined) requestData.unit_price = updates.unit_price ?? undefined;
      if (updates.total_price !== undefined) requestData.total_price = updates.total_price ?? undefined;
      if (updates.spec !== undefined) requestData.spec = updates.spec ?? undefined;
      if (updates.note !== undefined) requestData.note = updates.note ?? undefined;

      const response = await itemMasterApi.bomItems.update(bomId, requestData);

      if (!response.success || !response.data) {
        throw new Error(response.message || 'BOM 항목 수정 실패');
      }

      // 업데이트된 BOM 데이터
      const updatedBOMData = {
        item_code: response.data!.item_code,
        item_name: response.data!.item_name,
        quantity: response.data!.quantity,
        unit: response.data!.unit,
        unit_price: response.data!.unit_price,
        total_price: response.data!.total_price,
        spec: response.data!.spec,
        note: response.data!.note,
        updated_at: response.data!.updated_at,
      };

      // state 업데이트
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          bom_items: (section.bom_items || []).map((bom: BOMItem) =>
            bom.id === bomId ? { ...bom, ...updatedBOMData } : bom
          )
        }))
      })));

      // 2025-11-27: independentSections 동기화 (섹션탭 실시간 반영)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        bom_items: (section.bom_items || []).map((bom: BOMItem) =>
          bom.id === bomId ? { ...bom, ...updatedBOMData } : bom
        )
      })));

      console.log('[ItemMasterContext] BOM 항목 수정 성공 (양방향 동기화):', bomId);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] BOM 항목 수정 실패:', errorMessage);
      throw error;
    }
  };

  const deleteBOMItem = async (bomId: number) => {
    try {
      // API 호출
      const response = await itemMasterApi.bomItems.delete(bomId);

      if (!response.success) {
        throw new Error(response.message || 'BOM 항목 삭제 실패');
      }

      // state 업데이트
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section => ({
          ...section,
          bom_items: (section.bom_items || []).filter((bom: BOMItem) => bom.id !== bomId)
        }))
      })));

      // 2025-11-27: independentSections 동기화 (섹션탭 실시간 반영)
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section => ({
        ...section,
        bom_items: (section.bom_items || []).filter((bom: BOMItem) => bom.id !== bomId)
      })));

      console.log('[ItemMasterContext] BOM 항목 삭제 성공 (양방향 동기화):', bomId);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] BOM 항목 삭제 실패:', errorMessage);
      throw error;
    }
  };

  // ============================================
  // 2025-11-26 추가: 독립 엔티티 관리
  // ============================================

  /**
   * 독립 섹션 로드 (API 호출 없이 state 설정)
   */
  const loadIndependentSections = (sections: ItemSection[]) => {
    setIndependentSections(sections);
    console.log('[ItemMasterContext] 독립 섹션 로드 완료:', sections.length);
  };

  /**
   * 독립 필드 로드 (API 호출 없이 state 설정)
   */
  const loadIndependentFields = (fields: ItemField[]) => {
    setIndependentFields(fields);
    console.log('[ItemMasterContext] 독립 필드 로드 완료:', fields.length);
  };

  /**
   * 독립 BOM 로드 (API 호출 없이 state 설정)
   */
  const loadIndependentBomItems = (bomItems: BOMItem[]) => {
    setIndependentBomItems(bomItems);
    console.log('[ItemMasterContext] 독립 BOM 로드 완료:', bomItems.length);
  };

  /**
   * 독립 섹션 새로고침 (API 호출)
   * @param isTemplate - true면 템플릿만, false면 일반 독립 섹션만, undefined면 전체
   */
  const refreshIndependentSections = async (isTemplate?: boolean) => {
    try {
      // 2025-11-26: sections.list()는 ItemSectionResponse[]를 직접 반환
      const sectionsData = await itemMasterApi.sections.list({ is_template: isTemplate });

      // API가 배열을 직접 반환하므로 바로 변환
      const sections = sectionsData.map(transformSectionResponse);
      setIndependentSections(sections);
      console.log('[ItemMasterContext] 독립 섹션 새로고침 완료:', sections.length);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 섹션 새로고침 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 독립 필드 새로고침 (API 호출)
   */
  const refreshIndependentFields = async () => {
    try {
      // 2025-11-26: fields.list()는 ItemFieldResponse[]를 직접 반환
      const fieldsData = await itemMasterApi.fields.list();

      // API가 배열을 직접 반환하므로 바로 변환
      const fields = fieldsData.map(transformFieldResponse);
      setIndependentFields(fields);
      console.log('[ItemMasterContext] 독립 필드 새로고침 완료:', fields.length);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 필드 새로고침 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 독립 BOM 새로고침 (API 호출)
   */
  const refreshIndependentBomItems = async () => {
    try {
      // 2025-11-26: bomItems.list()는 BomItemResponse[]를 직접 반환
      const bomItemsData = await itemMasterApi.bomItems.list();

      // API가 배열을 직접 반환하므로 바로 변환
      const bomItems = bomItemsData.map(transformBomItemResponse);
      setIndependentBomItems(bomItems);
      console.log('[ItemMasterContext] 독립 BOM 새로고침 완료:', bomItems.length);
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 BOM 새로고침 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 독립 섹션 생성 (API 호출)
   * 2025-11-26: sections.createIndependent()는 ItemSectionResponse를 직접 반환
   */
  const createIndependentSection = async (data: Omit<IndependentSectionRequest, 'group_id'>): Promise<ItemSection> => {
    try {
      // API가 ItemSectionResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const sectionData = await itemMasterApi.sections.createIndependent(data);

      const newSection = transformSectionResponse(sectionData);
      setIndependentSections(prev => [...prev, newSection]);
      console.log('[ItemMasterContext] 독립 섹션 생성 성공:', newSection.id);
      return newSection;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 섹션 생성 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 독립 필드 생성 (API 호출)
   * 2025-11-26: fields.createIndependent()는 ItemFieldResponse를 직접 반환
   */
  const createIndependentField = async (data: Omit<IndependentFieldRequest, 'group_id'>): Promise<ItemField> => {
    try {
      // API가 ItemFieldResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const fieldData = await itemMasterApi.fields.createIndependent(data);

      const newField = transformFieldResponse(fieldData);
      setIndependentFields(prev => [...prev, newField]);
      console.log('[ItemMasterContext] 독립 필드 생성 성공:', newField.id);
      return newField;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 필드 생성 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 독립 BOM 생성 (API 호출)
   * 2025-11-26: bomItems.createIndependent()는 BomItemResponse를 직접 반환
   */
  const createIndependentBomItem = async (data: Omit<IndependentBomItemRequest, 'group_id'>): Promise<BOMItem> => {
    try {
      // API가 BomItemResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const bomItemData = await itemMasterApi.bomItems.createIndependent(data);

      const newBomItem = transformBomItemResponse(bomItemData);
      setIndependentBomItems(prev => [...prev, newBomItem]);
      console.log('[ItemMasterContext] 독립 BOM 생성 성공:', newBomItem.id);
      return newBomItem;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 독립 BOM 생성 실패:', errorMessage);
      throw error;
    }
  };

  // ============================================
  // 2025-11-26 추가: 링크/언링크 관리
  // ============================================

  /**
   * 섹션을 페이지에 연결
   */
  const linkSectionToPage = async (pageId: number, sectionId: number, orderNo?: number) => {
    try {
      const response = await itemMasterApi.pages.linkSection(pageId, {
        child_id: sectionId,
        order_no: orderNo,
      });

      if (!response.success) {
        throw new Error(response.message || '섹션 연결 실패');
      }

      // 페이지 구조 새로고침
      // 2025-11-26: API가 PageStructureResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const structureData = await itemMasterApi.pages.getStructure(pageId);
      console.log('[linkSectionToPage] getStructure 응답:', structureData);
      console.log('[linkSectionToPage] sections 배열:', structureData?.sections);
      if (structureData?.sections?.[0]) {
        console.log('[linkSectionToPage] 첫번째 섹션 원본:', structureData.sections[0]);
        console.log('[linkSectionToPage] 첫번째 섹션 키:', Object.keys(structureData.sections[0]));
      }

      if (structureData && structureData.page) {
        const updatedPage = transformPageResponse(structureData.page);

        // getStructure API 응답 형식: { section: {...}, order_no, fields: [], bom_items: [] }
        // section wrapper를 해제하고 fields/bom_items를 병합
        updatedPage.sections = structureData.sections?.map((sectionData: any) => {
          // sectionData가 wrapper 형태인지 확인
          const rawSection = sectionData.section || sectionData;
          const transformed = transformSectionResponse(rawSection);

          // fields와 bom_items는 wrapper에서 직접 가져옴 (있다면)
          if (sectionData.fields && Array.isArray(sectionData.fields)) {
            transformed.fields = sectionData.fields.map((f: any) =>
              f.field ? transformFieldResponse(f.field) : transformFieldResponse(f)
            );
          }
          if (sectionData.bom_items && Array.isArray(sectionData.bom_items)) {
            transformed.bom_items = sectionData.bom_items.map((b: any) =>
              b.bom_item ? transformBomItemResponse(b.bom_item) : transformBomItemResponse(b)
            );
          }

          return transformed;
        }) || [];

        console.log('[linkSectionToPage] 변환된 페이지:', updatedPage);
        console.log('[linkSectionToPage] 변환된 sections:', updatedPage.sections);
        setItemPages(prev => prev.map(page => page.id === pageId ? updatedPage : page));
      } else {
        console.warn('[linkSectionToPage] structureData.page가 없음, 페이지 데이터를 다시 로드해주세요');
        // TODO: 전체 init 데이터 새로고침 기능 구현 필요
        // 현재는 페이지를 새로고침하거나 init API를 다시 호출해야 함
      }

      // 독립 섹션 목록에서 제거 (연결되면 더 이상 독립이 아님)
      setIndependentSections(prev => prev.filter(s => s.id !== sectionId));

      console.log('[ItemMasterContext] 섹션 연결 성공:', { pageId, sectionId });
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 연결 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 섹션을 페이지에서 연결 해제
   */
  const unlinkSectionFromPage = async (pageId: number, sectionId: number) => {
    try {
      const response = await itemMasterApi.pages.unlinkSection(pageId, sectionId);

      if (!response.success) {
        throw new Error(response.message || '섹션 연결 해제 실패');
      }

      // 페이지에서 섹션 제거
      setItemPages(prev => prev.map(page =>
        page.id === pageId
          ? { ...page, sections: page.sections.filter(s => s.id !== sectionId) }
          : page
      ));

      // 독립 섹션 목록 새로고침 (연결 해제된 섹션이 추가됨)
      // 2025-11-26: refresh 실패는 치명적이지 않으므로 에러 로그만 남기고 진행
      try {
        await refreshIndependentSections();
      } catch (refreshError) {
        console.warn('[ItemMasterContext] 독립 섹션 새로고침 실패 (무시됨):', getErrorMessage(refreshError));
      }

      console.log('[ItemMasterContext] 섹션 연결 해제 성공:', { pageId, sectionId });
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 연결 해제 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 필드를 섹션에 연결
   * 2025-12-01: fieldData 파라미터 추가 (createIndependentField 직후 호출 시 상태 동기화 이슈 해결)
   */
  const linkFieldToSection = async (sectionId: number, fieldId: number, orderNo?: number, fieldData?: ItemField) => {
    try {
      const response = await itemMasterApi.sections.linkField(sectionId, {
        child_id: fieldId,
        order_no: orderNo,
      });

      if (!response.success) {
        throw new Error(response.message || '필드 연결 실패');
      }

      // 2025-12-01: fieldData가 직접 전달되면 사용, 아니면 independentFields에서 찾기
      // (createIndependentField 직후 호출 시 상태가 아직 업데이트되지 않아 find가 실패할 수 있음)
      const linkedField = fieldData || independentFields.find(f => f.id === fieldId);
      if (linkedField) {
        setItemPages(prev => prev.map(page => ({
          ...page,
          sections: page.sections.map(section =>
            section.id === sectionId
              ? {
                  ...section,
                  fields: [
                    ...(section.fields || []),
                    {
                      ...linkedField,
                      section_id: sectionId,
                      // 2025-12-02: 섹션별 순서 종속 - 새 order_no 할당
                      order_no: orderNo ?? section.fields?.length ?? 0
                    }
                  ]
                }
              : section
          )
        })));

        // 2025-11-27: 섹션탭 실시간 반영
        // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
        setIndependentSections(prev => prev.map(section =>
          section.id === sectionId
            ? {
                ...section,
                fields: [
                  ...(section.fields || []),
                  {
                    ...linkedField,
                    section_id: sectionId,
                    // 2025-12-02: 섹션별 순서 종속 - 새 order_no 할당
                    order_no: orderNo ?? section.fields?.length ?? 0
                  }
                ]
              }
            : section
        ));
      }

      // 독립 필드 목록에서 제거 (fieldData가 전달된 경우에도 실행)
      setIndependentFields(prev => prev.filter(f => f.id !== fieldId));

      console.log('[ItemMasterContext] 필드 연결 성공:', { sectionId, fieldId });
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 연결 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 필드를 섹션에서 연결 해제
   */
  const unlinkFieldFromSection = async (sectionId: number, fieldId: number) => {
    try {
      const response = await itemMasterApi.sections.unlinkField(sectionId, fieldId);

      if (!response.success) {
        throw new Error(response.message || '필드 연결 해제 실패');
      }

      // 섹션에서 필드 제거
      setItemPages(prev => prev.map(page => ({
        ...page,
        sections: page.sections.map(section =>
          section.id === sectionId
            ? { ...section, fields: (section.fields || []).filter(f => f.id !== fieldId) }
            : section
        )
      })));

      // 2025-11-27: 섹션탭 실시간 반영
      // sectionsAsTemplates useMemo가 [itemPages, independentSections] 둘 다 의존
      setIndependentSections(prev => prev.map(section =>
        section.id === sectionId
          ? { ...section, fields: (section.fields || []).filter(f => f.id !== fieldId) }
          : section
      ));

      // 독립 필드 목록 새로고침
      await refreshIndependentFields();

      console.log('[ItemMasterContext] 필드 연결 해제 성공:', { sectionId, fieldId });
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 연결 해제 실패:', errorMessage);
      throw error;
    }
  };

  // ============================================
  // 2025-11-26 추가: 사용처 조회
  // ============================================

  /**
   * 섹션 사용처 조회
   */
  const getSectionUsage = async (sectionId: number): Promise<SectionUsageResponse> => {
    try {
      // 2025-11-26: API가 SectionUsageResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const usageData = await itemMasterApi.sections.getUsage(sectionId);

      console.log('[ItemMasterContext] 섹션 사용처 조회 성공:', sectionId);
      return usageData;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 사용처 조회 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 필드 사용처 조회
   */
  const getFieldUsage = async (fieldId: number): Promise<FieldUsageResponse> => {
    try {
      // 2025-11-26: API가 FieldUsageResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const usageData = await itemMasterApi.fields.getUsage(fieldId);

      console.log('[ItemMasterContext] 필드 사용처 조회 성공:', fieldId);
      return usageData;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 사용처 조회 실패:', errorMessage);
      throw error;
    }
  };

  // ============================================
  // 2025-11-26 추가: 복제 기능
  // ============================================

  /**
   * 섹션 복제
   */
  const cloneSection = async (sectionId: number): Promise<ItemSection> => {
    try {
      // 2025-11-26: API가 ItemSectionResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const sectionData = await itemMasterApi.sections.clone(sectionId);
      console.log('[cloneSection] API 응답 원본:', sectionData);

      const clonedSection = transformSectionResponse(sectionData);
      console.log('[cloneSection] 변환 후 섹션:', {
        id: clonedSection.id,
        title: clonedSection.title,
        page_id: clonedSection.page_id,
        section_type: clonedSection.section_type,
        fieldsCount: clonedSection.fields?.length || 0,
        fields: clonedSection.fields,
      });

      // 2025-11-27: 복제된 섹션을 적절한 상태에 추가 (즉시 UI 업데이트)
      // page_id가 null 또는 undefined면 독립 섹션 (API가 null 대신 undefined를 반환할 수 있음)
      if (clonedSection.page_id == null) {
        // 독립 섹션(일반 섹션)인 경우 independentSections에 추가
        console.log('[cloneSection] 독립 섹션 추가 (independentSections)');
        setIndependentSections(prev => {
          const newSections = [...prev, clonedSection];
          console.log('[cloneSection] independentSections 업데이트:', newSections.length);
          return newSections;
        });
      } else {
        // 모듈 섹션인 경우 해당 페이지의 sections에 추가
        console.log('[cloneSection] 모듈 섹션 추가 (itemPages), page_id:', clonedSection.page_id);
        setItemPages(prev => {
          const newPages = prev.map(page => {
            if (page.id === clonedSection.page_id) {
              console.log('[cloneSection] 페이지 찾음:', page.id, '기존 섹션 수:', page.sections.length);
              return {
                ...page,
                sections: [...page.sections, clonedSection]
              };
            }
            return page;
          });
          return newPages;
        });
      }

      console.log('[ItemMasterContext] 섹션 복제 성공:', clonedSection.id);
      return clonedSection;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 섹션 복제 실패:', errorMessage);
      throw error;
    }
  };

  /**
   * 필드 복제
   */
  const cloneField = async (fieldId: number): Promise<ItemField> => {
    try {
      // 2025-11-26: API가 ItemFieldResponse를 직접 반환 (ApiResponse 래퍼 없음)
      const fieldData = await itemMasterApi.fields.clone(fieldId);

      const clonedField = transformFieldResponse(fieldData);

      // 복제된 필드가 독립 필드면 독립 필드 목록에 추가
      if (clonedField.section_id === null) {
        setIndependentFields(prev => [...prev, clonedField]);
      }

      console.log('[ItemMasterContext] 필드 복제 성공:', clonedField.id);
      return clonedField;
    } catch (error) {
      const errorMessage = getErrorMessage(error);
      console.error('[ItemMasterContext] 필드 복제 실패:', errorMessage);
      throw error;
    }
  };

  // 캐시 및 데이터 초기화 함수
  const clearCache = () => {
    if (cache) {
      cache.clear();
      console.log('[ItemMasterContext] TenantAwareCache cleared');
    }
  };

  const resetAllData = () => {
    // 모든 state를 초기값으로 reset
    setItemMasters(initialItemMasters);
    setSpecificationMasters(initialSpecificationMasters);
    setMaterialItemNames(initialMaterialItemNames);
    setItemCategories(initialItemCategories);
    setItemUnits(initialItemUnits);
    setItemMaterials(initialItemMaterials);
    setSurfaceTreatments(initialSurfaceTreatments);
    setPartTypeOptions(initialPartTypeOptions);
    setPartUsageOptions(initialPartUsageOptions);
    setGuideRailOptions(initialGuideRailOptions);
    setSectionTemplates([]);
    setItemMasterFields(initialItemMasterFields);
    setItemPages(initialItemPages);

    // TenantAwareCache도 정리
    clearCache();

    console.log('[ItemMasterContext] All data reset to initial state');
  };

  // Context value
  const value: ItemMasterContextType = {
    itemMasters,
    addItemMaster,
    updateItemMaster,
    deleteItemMaster,

    specificationMasters,
    addSpecificationMaster,
    updateSpecificationMaster,
    deleteSpecificationMaster,

    materialItemNames,
    addMaterialItemName,
    updateMaterialItemName,
    deleteMaterialItemName,

    itemMasterFields,
    loadItemMasterFields,
    addItemMasterField,
    updateItemMasterField,
    deleteItemMasterField,

    sectionTemplates,
    loadSectionTemplates,
    addSectionTemplate,
    updateSectionTemplate,
    deleteSectionTemplate,

    itemPages,
    loadItemPages,
    addItemPage,
    updateItemPage,
    deleteItemPage,
    reorderPages,
    addSectionToPage,
    updateSection,
    deleteSection,
    reorderSections,
    addFieldToSection,
    updateField,
    deleteField,
    reorderFields,

    addBOMItem,
    updateBOMItem,
    deleteBOMItem,

    // 2025-11-26 추가: 독립 엔티티 관리
    independentSections,
    independentFields,
    independentBomItems,
    loadIndependentSections,
    loadIndependentFields,
    loadIndependentBomItems,
    refreshIndependentSections,
    refreshIndependentFields,
    refreshIndependentBomItems,
    createIndependentSection,
    createIndependentField,
    createIndependentBomItem,

    // 링크/언링크 관리
    linkSectionToPage,
    unlinkSectionFromPage,
    linkFieldToSection,
    unlinkFieldFromSection,

    // 사용처 조회
    getSectionUsage,
    getFieldUsage,

    // 복제
    cloneSection,
    cloneField,

    itemCategories,
    itemUnits,
    itemMaterials,
    surfaceTreatments,
    partTypeOptions,
    partUsageOptions,
    guideRailOptions,

    addItemCategory,
    updateItemCategory,
    deleteItemCategory,

    addItemUnit,
    updateItemUnit,
    deleteItemUnit,

    addItemMaterial,
    updateItemMaterial,
    deleteItemMaterial,

    addSurfaceTreatment,
    updateSurfaceTreatment,
    deleteSurfaceTreatment,

    addPartTypeOption,
    updatePartTypeOption,
    deletePartTypeOption,

    addPartUsageOption,
    updatePartUsageOption,
    deletePartUsageOption,

    addGuideRailOption,
    updateGuideRailOption,
    deleteGuideRailOption,

    clearCache,
    resetAllData,

    tenantId,
  };

  return (
    <ItemMasterContext.Provider value={value}>
      {children}
    </ItemMasterContext.Provider>
  );
}

// Custom hook
export function useItemMaster() {
  const context = useContext(ItemMasterContext);
  if (context === undefined) {
    throw new Error('useItemMaster must be used within an ItemMasterProvider');
  }
  return context;
}
