/**
 * 품목 관리 API 클라이언트
 *
 * Laravel 백엔드와 통신하는 API 함수들
 * Next.js 15 Server Components와 Client Components 모두에서 사용 가능
 */

import type {
  ItemMaster,
  CreateItemData,
  UpdateItemData,
  FetchItemsParams,
  ApiResponse,
  PaginatedResponse,
  BOMLine,
} from '@/types/item';

// ===== 환경 변수 =====

const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';

// ===== 유틸리티 함수 =====

/**
 * 인증 토큰 가져오기
 * TODO: 실제 인증 구현에 맞게 수정 필요
 */
function getAuthToken(): string | null {
  // Server Component에서는 쿠키에서 자동으로
  // Client Component에서는 localStorage 또는 쿠키에서
  if (typeof window !== 'undefined') {
    return localStorage.getItem('auth_token');
  }
  return null;
}

/**
 * Fetch 옵션 생성
 */
function createFetchOptions(options: RequestInit = {}): RequestInit {
  const token = getAuthToken();
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(options.headers as Record<string, string>),
  };

  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  return {
    ...options,
    headers,
    credentials: 'include', // 쿠키 포함
  };
}

/**
 * API 에러 처리
 */
async function handleApiResponse<T>(response: Response): Promise<T> {
  if (!response.ok) {
    const error = await response.json().catch(() => ({
      message: 'API 요청 실패',
    }));

    throw new Error(error.message || `HTTP ${response.status}: ${response.statusText}`);
  }

  const data = await response.json();
  return data;
}

// ===== 품목 CRUD =====

/**
 * 품목 목록 조회
 *
 * @example
 * // Server Component에서
 * const items = await fetchItems({ itemType: 'FG' });
 *
 * // Client Component에서
 * const [items, setItems] = useState([]);
 * useEffect(() => {
 *   fetchItems().then(setItems);
 * }, []);
 */
// API 응답 → 프론트엔드(camelCase) 변환
interface ApiItemResponse {
  id?: number | string;
  // DB 필드명 (code, name)
  code?: string;
  name?: string;
  item_type?: string;
  unit?: string;
  specification?: string;
  is_active?: boolean | number;
  // snake_case 대안 (item_code, item_name)
  item_code?: string;
  item_name?: string;
  // camelCase도 지원 (이미 변환된 경우)
  itemCode?: string;
  itemName?: string;
  itemType?: string;
  isActive?: boolean;
  // 수입검사 양식 연결 여부
  has_inspection_template?: boolean;
  hasInspectionTemplate?: boolean;
}

function transformItemFromApi(apiItem: ApiItemResponse): ItemMaster {
  return {
    id: String(apiItem.id || ''),
    // 우선순위: code > item_code > itemCode
    itemCode: apiItem.code || apiItem.item_code || apiItem.itemCode || '',
    // 우선순위: name > item_name > itemName
    itemName: apiItem.name || apiItem.item_name || apiItem.itemName || '',
    itemType: (apiItem.item_type || apiItem.itemType || 'FG') as ItemMaster['itemType'],
    unit: apiItem.unit || '',
    specification: apiItem.specification || '',
    isActive: apiItem.is_active === true || apiItem.is_active === 1 || apiItem.isActive === true,
    hasInspectionTemplate: apiItem.has_inspection_template === true || apiItem.hasInspectionTemplate === true,
    currentRevision: 0,
    isFinal: false,
    createdAt: '',
  };
}

export async function fetchItems(
  params?: FetchItemsParams
): Promise<ItemMaster[]> {
  const queryParams = new URLSearchParams();

  if (params) {
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        queryParams.append(key, String(value));
      }
    });
  }

  // 클라이언트에서 호출 시 프록시 라우트 사용 (HttpOnly 쿠키 인증 지원)
  const isClient = typeof window !== 'undefined';
  const baseUrl = isClient ? '/api/proxy' : `${API_URL}/api/v1`;
  const url = `${baseUrl}/items${queryParams.toString() ? `?${queryParams}` : ''}`;

  const response = await fetch(url, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
    credentials: 'include',
  });

  if (!response.ok) {
    throw new Error(`품목 조회 실패: ${response.status}`);
  }

  const result = await response.json();

  // 디버깅: API 응답 구조 확인

  // 데이터 추출
  let rawItems: ApiItemResponse[] = [];

  if (result.success && result.data) {
    // 페이지네이션 응답: { success: true, data: { data: [...], ... } }
    if (result.data.data && Array.isArray(result.data.data)) {
      rawItems = result.data.data;
    }
    // 단순 배열 응답: { success: true, data: [...] }
    else if (Array.isArray(result.data)) {
      rawItems = result.data;
    }
  }
  // 직접 배열 응답 (fallback)
  else if (Array.isArray(result)) {
    rawItems = result;
  }

  // snake_case → camelCase 변환
  const transformed = rawItems.map(transformItemFromApi);

  return transformed;
}

/**
 * 품목 목록 조회 (페이지네이션)
 */
export async function fetchItemsPaginated(
  params?: FetchItemsParams
): Promise<PaginatedResponse<ItemMaster>> {
  const queryParams = new URLSearchParams();

  if (params) {
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        queryParams.append(key, String(value));
      }
    });
  }

  const url = `${API_URL}/api/items/paginated${queryParams.toString() ? `?${queryParams}` : ''}`;

  const response = await fetch(url, createFetchOptions());
  const data = await handleApiResponse<ApiResponse<PaginatedResponse<ItemMaster>>>(response);

  return data.data;
}

/**
 * 품목 상세 조회
 *
 * @param itemCode - 품목 코드 (예: "KD-FG-001")
 *
 * @example
 * const item = await fetchItemByCode('KD-FG-001');
 */
export async function fetchItemByCode(itemCode: string): Promise<ItemMaster> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<ItemMaster>>(response);
  return data.data;
}

/**
 * 품목 등록
 *
 * @example
 * const newItem = await createItem({
 *   itemCode: 'KD-FG-001',
 *   itemName: '스크린 제품',
 *   itemType: 'FG',
 *   unit: 'EA',
 * });
 */
export async function createItem(
  itemData: CreateItemData
): Promise<ItemMaster> {
  const response = await fetch(
    `${API_URL}/api/items`,
    createFetchOptions({
      method: 'POST',
      body: JSON.stringify(itemData),
    })
  );

  const data = await handleApiResponse<ApiResponse<ItemMaster>>(response);
  return data.data;
}

/**
 * 품목 수정
 *
 * @param itemCode - 품목 코드
 * @param updates - 수정할 필드들
 *
 * @example
 * const updatedItem = await updateItem('KD-FG-001', {
 *   itemName: '스크린 제품 (수정)',
 *   salesPrice: 150000,
 * });
 */
export async function updateItem(
  itemCode: string,
  updates: UpdateItemData
): Promise<ItemMaster> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}`,
    createFetchOptions({
      method: 'PUT',
      body: JSON.stringify(updates),
    })
  );

  const data = await handleApiResponse<ApiResponse<ItemMaster>>(response);
  return data.data;
}

/**
 * 품목 삭제
 *
 * @param itemCode - 품목 코드
 *
 * @example
 * await deleteItem('KD-FG-001');
 */
export async function deleteItem(itemCode: string): Promise<void> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}`,
    createFetchOptions({
      method: 'DELETE',
    })
  );

  await handleApiResponse<ApiResponse<null>>(response);
}

// ===== BOM (자재명세서) 관리 =====

/**
 * BOM 목록 조회
 *
 * @param itemCode - 상위 품목 코드
 */
export async function fetchBOM(itemCode: string): Promise<BOMLine[]> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}/bom`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<BOMLine[]>>(response);
  return data.data;
}

/**
 * BOM 계층구조 조회 (트리 형태)
 *
 * @param itemCode - 상위 품목 코드
 */
export async function fetchBOMTree(itemCode: string): Promise<any> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}/bom/tree`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<any>>(response);
  return data.data;
}

/**
 * BOM 라인 추가
 *
 * @param itemCode - 상위 품목 코드
 * @param bomLine - BOM 라인 데이터
 */
export async function addBOMLine(
  itemCode: string,
  bomLine: Omit<BOMLine, 'id'>
): Promise<BOMLine> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}/bom`,
    createFetchOptions({
      method: 'POST',
      body: JSON.stringify(bomLine),
    })
  );

  const data = await handleApiResponse<ApiResponse<BOMLine>>(response);
  return data.data;
}

/**
 * BOM 라인 수정
 *
 * @param itemCode - 상위 품목 코드
 * @param lineId - BOM 라인 ID
 * @param updates - 수정할 필드들
 */
export async function updateBOMLine(
  itemCode: string,
  lineId: string,
  updates: Partial<BOMLine>
): Promise<BOMLine> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}/bom/${lineId}`,
    createFetchOptions({
      method: 'PUT',
      body: JSON.stringify(updates),
    })
  );

  const data = await handleApiResponse<ApiResponse<BOMLine>>(response);
  return data.data;
}

/**
 * BOM 라인 삭제
 *
 * @param itemCode - 상위 품목 코드
 * @param lineId - BOM 라인 ID
 */
export async function deleteBOMLine(
  itemCode: string,
  lineId: string
): Promise<void> {
  const response = await fetch(
    `${API_URL}/api/items/${encodeURIComponent(itemCode)}/bom/${lineId}`,
    createFetchOptions({
      method: 'DELETE',
    })
  );

  await handleApiResponse<ApiResponse<null>>(response);
}

// ===== 파일 업로드 =====

/** 파일 타입 */
export type ItemFileType = 'specification' | 'certification' | 'bending_diagram';

/** 파일 업로드 옵션 */
export interface UploadFileOptions {
  /** 필드 키 (백엔드에서 파일 식별용) - 예: specification_file, certification_file, bending_diagram */
  fieldKey?: string;
  /** 파일 ID (같은 field_key 내 여러 파일 구분용) - 0, 1, 2... (없으면 최초 등록, 있으면 덮어쓰기) */
  fileId?: number;
  /** 인증번호 (certification 타입일 때) */
  certificationNumber?: string;
  /** 인증 시작일 (certification 타입일 때) */
  certificationStartDate?: string;
  /** 인증 종료일 (certification 타입일 때) */
  certificationEndDate?: string;
  /** 절곡 상세 정보 (bending_diagram 타입일 때) */
  bendingDetails?: Array<{
    angle: number;
    length: number;
    type: string;
  }>;
}

/** 파일 업로드 응답 */
export interface UploadFileResponse {
  file_type: string;
  file_url: string;
  file_path: string;
  file_name: string;
  product: Record<string, unknown>;
}

/**
 * 품목 파일 업로드 (ID 기반, 프록시 사용)
 *
 * HttpOnly 쿠키 인증을 위해 Next.js API 프록시를 경유합니다.
 *
 * @param itemId - 품목 ID (숫자)
 * @param file - 업로드할 파일
 * @param fileType - 파일 유형 (specification, certification, bending_diagram)
 * @param options - 추가 옵션 (certification 관련 필드, bending_details 등)
 *
 * @example
 * // 시방서 업로드
 * await uploadItemFile(123, specFile, 'specification');
 *
 * // 인정서 업로드 (추가 정보 포함)
 * await uploadItemFile(123, certFile, 'certification', {
 *   certificationNumber: 'CERT-001',
 *   certificationStartDate: '2025-01-01',
 *   certificationEndDate: '2026-01-01',
 * });
 *
 * // 절곡/조립 전개도 업로드
 * await uploadItemFile(123, diagramFile, 'bending_diagram');
 */
export async function uploadItemFile(
  itemId: number,
  file: File,
  fileType: ItemFileType,
  options?: UploadFileOptions
): Promise<UploadFileResponse> {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('type', fileType);

  // field_key, file_id 추가 (백엔드에서 파일 식별용)
  // - field_key: 파일 종류 식별자 (예: specification_file, certification_file, bending_diagram)
  // - file_id: 같은 field_key 내 파일 순번 (없으면 최초 등록, 있으면 해당 파일 덮어쓰기)
  if (options?.fieldKey) {
    formData.append('field_key', options.fieldKey);
  }
  if (options?.fileId !== undefined) {
    formData.append('file_id', String(options.fileId));
  }

  // certification 관련 추가 필드
  if (fileType === 'certification' && options) {
    if (options.certificationNumber) {
      formData.append('certification_number', options.certificationNumber);
    }
    if (options.certificationStartDate) {
      formData.append('certification_start_date', options.certificationStartDate);
    }
    if (options.certificationEndDate) {
      formData.append('certification_end_date', options.certificationEndDate);
    }
  }

  // bending_diagram 관련 추가 필드
  // 백엔드가 배열 형태를 기대하므로 각 항목을 개별적으로 append
  if (fileType === 'bending_diagram' && options?.bendingDetails) {
    options.bendingDetails.forEach((detail, index) => {
      Object.entries(detail).forEach(([key, value]) => {
        formData.append(`bending_details[${index}][${key}]`, String(value));
      });
    });
  }

  // 프록시 경유: /api/proxy/items/{id}/files → /api/v1/items/{id}/files
  const response = await fetch(`/api/proxy/items/${itemId}/files`, {
    method: 'POST',
    body: formData,
    credentials: 'include',
    // Content-Type은 FormData 사용 시 자동 설정됨 (boundary 포함)
  });

  const data = await handleApiResponse<ApiResponse<UploadFileResponse>>(response);
  return data.data;
}

/**
 * 품목 파일 삭제 (파일 ID 기반, 프록시 사용)
 *
 * @param itemId - 품목 ID (숫자)
 * @param fileId - 파일 ID (files 테이블의 id)
 * @param itemType - 품목 유형 (FG, PT, SM 등) - 기본값 'FG'
 *
 * @example
 * await deleteItemFile(123, 456, 'FG');
 */
export async function deleteItemFile(
  itemId: number,
  fileId: number,
  itemType: string = 'FG'
): Promise<{ file_id: number; deleted: boolean }> {
  // 프록시 경유: /api/proxy/items/{id}/files/{fileId} → /api/v1/items/{id}/files/{fileId}
  const response = await fetch(`/api/proxy/items/${itemId}/files/${fileId}?item_type=${itemType}`, {
    method: 'DELETE',
    credentials: 'include',
  });

  const data = await handleApiResponse<ApiResponse<{ file_id: number; deleted: boolean }>>(response);
  return data.data;
}

// ===== 검색 및 필터 =====

/**
 * 품목 코드로 검색 (자동완성용)
 *
 * @param query - 검색어
 * @param limit - 최대 결과 개수
 */
export async function searchItemCodes(
  query: string,
  limit: number = 10
): Promise<string[]> {
  const response = await fetch(
    `${API_URL}/api/items/search/codes?q=${encodeURIComponent(query)}&limit=${limit}`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<string[]>>(response);
  return data.data;
}

/**
 * 품목명으로 검색 (자동완성용)
 *
 * @param query - 검색어
 * @param limit - 최대 결과 개수
 */
export async function searchItemNames(
  query: string,
  limit: number = 10
): Promise<Array<{ itemCode: string; itemName: string }>> {
  const response = await fetch(
    `${API_URL}/api/items/search/names?q=${encodeURIComponent(query)}&limit=${limit}`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<Array<{ itemCode: string; itemName: string }>>>(response);
  return data.data;
}

// ===== 유틸리티 =====

/**
 * 품목 코드 중복 체크
 *
 * @param itemCode - 체크할 품목 코드
 * @returns 사용 가능 여부 (true: 사용 가능, false: 중복)
 */
export async function checkItemCodeAvailability(
  itemCode: string
): Promise<boolean> {
  const response = await fetch(
    `${API_URL}/api/items/check/${encodeURIComponent(itemCode)}`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<{ available: boolean }>>(response);
  return data.data.available;
}

/** 품목 코드 중복 체크 결과 */
export interface DuplicateCheckResult {
  /** 중복 여부 */
  isDuplicate: boolean;
  /** 중복된 품목 ID (중복인 경우에만 존재) */
  duplicateId?: number;
  /** 중복된 품목 타입 (중복인 경우에만 존재) */
  duplicateItemType?: string;
}

/**
 * 품목 코드 중복 체크 (ID 반환)
 *
 * GET /api/v1/items/code/{code} API를 활용하여 중복 체크
 * - 200 OK: 중복 있음 (해당 품목의 id 반환)
 * - 404 Not Found: 중복 없음
 *
 * @param itemCode - 체크할 품목 코드
 * @param excludeId - 제외할 품목 ID (수정 시 자기 자신 제외)
 * @returns 중복 체크 결과 (중복 여부 + 중복 품목 ID)
 *
 * @example
 * // 등록 시
 * const result = await checkItemCodeDuplicate('PT-ASM-001');
 * if (result.isDuplicate) {
 *   // 중복! result.duplicateId로 수정 페이지 이동 가능
 * }
 *
 * // 수정 시 (자기 자신 제외)
 * const result = await checkItemCodeDuplicate('PT-ASM-001', currentItemId);
 */
export async function checkItemCodeDuplicate(
  itemCode: string,
  excludeId?: number
): Promise<DuplicateCheckResult> {
  try {
    // 프록시 경유: /api/proxy/items/code/{code} → /api/v1/items/code/{code}
    const response = await fetch(
      `/api/proxy/items/code/${encodeURIComponent(itemCode)}`,
      {
        method: 'GET',
        credentials: 'include',
      }
    );

    if (response.status === 404) {
      // 404: 해당 코드의 품목이 없음 → 중복 아님
      return { isDuplicate: false };
    }

    if (!response.ok) {
      // 다른 에러는 중복 아님으로 처리 (안전한 방향)
      console.warn('[checkItemCodeDuplicate] API 에러:', response.status);
      return { isDuplicate: false };
    }

    // 200 OK: 해당 코드의 품목이 존재함
    const data = await response.json();
    const duplicateItem = data.data;

    // 수정 모드에서 자기 자신인 경우 제외
    if (excludeId && duplicateItem.id === excludeId) {
      return { isDuplicate: false };
    }

    return {
      isDuplicate: true,
      duplicateId: duplicateItem.id,
      // 백엔드에서 product_type, item_type, type_code 등 다양한 필드명 사용 가능
      duplicateItemType: duplicateItem.product_type || duplicateItem.item_type || duplicateItem.type_code,
    };
  } catch (error) {
    console.error('[checkItemCodeDuplicate] 에러:', error);
    // 에러 시 중복 아님으로 처리 (등록/수정 진행 허용)
    return { isDuplicate: false };
  }
}

/**
 * 다음 품목 코드 생성 (서버에서 자동 생성)
 *
 * @param itemType - 품목 유형
 * @returns 생성된 품목 코드 (예: "KD-FG-001")
 */
export async function generateItemCode(
  itemType: string
): Promise<string> {
  const response = await fetch(
    `${API_URL}/api/items/generate-code?itemType=${itemType}`,
    createFetchOptions()
  );

  const data = await handleApiResponse<ApiResponse<{ itemCode: string }>>(response);
  return data.data.itemCode;
}

/**
 * Next.js revalidation 트리거
 * Server Component에서 데이터 변경 시 호출
 */
export async function revalidateItems(): Promise<void> {
  if (typeof window === 'undefined') {
    // Server Component에서만 실행
    const { revalidatePath } = await import('next/cache');
    revalidatePath('/items');
  }
}

// ===== 품목 단가 조회 =====

/** 품목 단가 조회 결과 */
export interface ItemPriceResult {
  item_code: string;
  unit_price: number;
}

/**
 * 품목 단가 조회 (견적 품목 추가 시 사용)
 *
 * @param itemCodes - 조회할 품목 코드 배열
 * @returns 품목 코드별 단가 정보
 *
 * @example
 * const prices = await fetchItemPrices(['N71807', 'N71808']);
 * console.log(prices['N71807']?.unit_price); // 1320000
 */
export async function fetchItemPrices(
  itemCodes: string[]
): Promise<Record<string, ItemPriceResult>> {
  if (!itemCodes.length) {
    return {};
  }

  try {
    // 프록시 경유: /api/proxy/quotes/items/prices → /api/v1/quotes/items/prices
    const response = await fetch('/api/proxy/quotes/items/prices', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ item_codes: itemCodes }),
      credentials: 'include',
    });

    if (!response.ok) {
      console.error('[fetchItemPrices] API 에러:', response.status);
      return {};
    }

    const result = await response.json();

    if (result.success && result.data) {
      return result.data as Record<string, ItemPriceResult>;
    }

    return {};
  } catch (error) {
    console.error('[fetchItemPrices] 에러:', error);
    return {};
  }
}