/**
 * 컴포넌트 타입 유틸리티
 * 레거시와 신규 컴포넌트 시스템 모두 지원하는 타입 감지 함수들
 */

import { ComponentData } from "@/types/screen";

/**
 * 파일 컴포넌트 여부를 확인합니다
 *
 * 지원하는 타입:
 * - 레거시: type="file"
 * - 레거시: type="widget" + widgetType="file"
 * - 신규: type="component" + widgetType="file"
 * - 신규: type="component" + componentType="file-upload"
 * - 신규: type="component" + componentConfig.webType="file"
 */
export const isFileComponent = (component: ComponentData): boolean => {
  if (!component || !component.type) return false;

  return (
    component.type === "file" ||
    (component.type === "widget" && (component as any).widgetType === "file") ||
    (component.type === "component" &&
      ((component as any).widgetType === "file" || // ✅ ScreenDesigner에서 설정됨
        (component as any).componentType === "file-upload" || // ✅ ComponentRegistry ID
        (component as any).componentConfig?.webType === "file"))
  ); // ✅ componentConfig 내부
};

/**
 * 버튼 컴포넌트 여부를 확인합니다
 */
export const isButtonComponent = (component: ComponentData): boolean => {
  if (!component || !component.type) return false;

  return (
    component.type === "button" ||
    (component.type === "widget" && (component as any).widgetType === "button") ||
    (component.type === "component" &&
      ((component as any).webType === "button" || (component as any).componentType === "button"))
  );
};

/**
 * 데이터 테이블 컴포넌트 여부를 확인합니다
 */
export const isDataTableComponent = (component: ComponentData): boolean => {
  if (!component || !component.type) return false;

  return (
    component.type === "datatable" ||
    (component.type === "component" &&
      ((component as any).componentType === "datatable" || (component as any).componentType === "data-table"))
  );
};

/**
 * 위젯 컴포넌트 여부를 확인합니다
 */
export const isWidgetComponent = (component: ComponentData): boolean => {
  if (!component || !component.type) return false;
  return component.type === "widget";
};

/**
 * 컴포넌트의 웹타입을 가져옵니다 (input_type 우선)
 */
export const getComponentWebType = (component: ComponentData): string | undefined => {
  if (!component || !component.type) return undefined;

  // 파일 컴포넌트는 무조건 "file" 웹타입 반환
  if (isFileComponent(component)) {
    console.log(`🎯 파일 컴포넌트 감지 → webType: "file" 반환`, {
      componentId: component.id,
      componentType: component.type,
      widgetType: (component as any).widgetType,
      componentConfig: (component as any).componentConfig,
    });
    return "file";
  }

  // 1. componentConfig.inputType 우선 확인 (새로 추가된 컴포넌트)
  const configInputType = (component as any).componentConfig?.inputType;
  if (configInputType) {
    console.log(`✅ 컴포넌트 componentConfig.inputType 사용:`, {
      componentId: component.id,
      tableName: (component as any).tableName,
      columnName: (component as any).columnName,
      inputType: configInputType,
      componentConfig: (component as any).componentConfig,
    });
    return configInputType;
  }

  // 2. 루트 레벨 input_type 확인 (하위 호환성)
  const rootInputType = (component as any).input_type || (component as any).inputType;
  if (rootInputType) {
    console.log(`✅ 컴포넌트 루트 inputType 사용:`, {
      componentId: component.id,
      tableName: (component as any).tableName,
      columnName: (component as any).columnName,
      inputType: rootInputType,
    });
    return rootInputType;
  }

  // 3. 기본 웹타입 확인
  const webType = component.type === "widget" 
    ? (component as any).widgetType 
    : component.type === "component"
    ? (component as any).widgetType || (component as any).componentConfig?.webType
    : component.type;

  console.log(`⚠️ inputType 없음, 기본 webType 사용:`, {
    componentId: component.id,
    tableName: (component as any).tableName,
    columnName: (component as any).columnName,
    type: component.type,
    widgetType: (component as any).widgetType,
    componentConfig: (component as any).componentConfig,
    resultWebType: webType,
  });

  return webType;
};

/**
 * 컴포넌트의 실제 타입을 가져옵니다 (신규 시스템용)
 */
export const getComponentType = (component: ComponentData): string => {
  if (!component || !component.type) return "unknown";

  if (component.type === "component") {
    return (component as any).componentType || (component as any).webType || "unknown";
  }
  return component.type;
};

/**
 * 컴포넌트가 입력 가능한 컴포넌트인지 확인합니다
 */
export const isInputComponent = (component: ComponentData): boolean => {
  const inputTypes = [
    "text",
    "number",
    "email",
    "password",
    "tel",
    "url",
    "search",
    "textarea",
    "select",
    "checkbox",
    "radio",
    "date",
    "time",
    "datetime-local",
    "file",
    "code",
    "entity",
  ];

  const webType = getComponentWebType(component);
  return webType ? inputTypes.includes(webType) : false;
};

/**
 * 컴포넌트가 표시용 컴포넌트인지 확인합니다
 */
export const isDisplayComponent = (component: ComponentData): boolean => {
  const displayTypes = ["label", "text", "image", "video", "chart", "table", "datatable"];

  const webType = getComponentWebType(component);
  return webType ? displayTypes.includes(webType) : false;
};

/**
 * 컴포넌트의 필드명을 가져옵니다
 */
export const getComponentFieldName = (component: ComponentData): string => {
  if (!component) return "";
  return (component as any).columnName || component.id || "";
};

/**
 * 컴포넌트의 라벨을 가져옵니다
 */
export const getComponentLabel = (component: ComponentData): string => {
  if (!component) return "";
  return (component as any).label || (component as any).title || component.id || "";
};

/**
 * ────────────────────────────────────────────────────────────────────────
 * Canonical Table-like helpers
 *
 * INVYONE canonical data-view cleanup 이후, 화면 전반에서 `table-list` 단독
 * 체크를 canonical-aware 형태로 옮긴다.
 *
 * - 새 생성 경로: `table` (canonical)
 * - 레거시 호환: `table-list`
 * - 폐기 예정 hidden legacy: `v2-table-list` (registry/schema에 hard blocker로
 *   보존 중이므로 런타임에서 인식해야 함)
 * - 일부 외부 코드가 사용: `data-table`, `datatable`
 *
 * 단일 typeValue 비교용은 `isTableLikeComponentType`, 컴포넌트 객체용은
 * `isTableLikeComponent`, table name 추출은 `getTableNameFromTableLikeComponent`
 * 를 사용한다.
 * ──────────────────────────────────────────────────────────────────────── */

/**
 * canonical table 및 호환 alias 전체 집합.
 * v2-table-list 는 registry/schemas hard blocker 로 보존되므로 여기서도 인식한다.
 */
const TABLE_LIKE_COMPONENT_TYPES: ReadonlySet<string> = new Set([
  "table",
  "table-list",
  "v2-table-list",
  "data-table",
  "datatable",
]);

/**
 * 단일 문자열(componentType, widgetType, url 등) 이 table-like 인지 판정.
 * URL/경로처럼 prefix 가 붙은 경우 마지막 segment 도 확인한다.
 */
export const isTableLikeComponentType = (typeValue: unknown): boolean => {
  if (typeof typeValue !== "string" || typeValue.length === 0) return false;
  const lower = typeValue.toLowerCase();
  if (TABLE_LIKE_COMPONENT_TYPES.has(lower)) return true;
  const lastSegment = lower.split("/").pop() ?? "";
  if (lastSegment && TABLE_LIKE_COMPONENT_TYPES.has(lastSegment)) return true;
  return false;
};

/**
 * 컴포넌트 객체에서 가능한 모든 type 필드를 검사하여 table-like 여부 판정.
 * camelCase / snake_case / componentConfig.type / component_config.type / url
 * 까지 모두 후보로 본다. 어느 한 필드라도 table-like 면 true.
 */
export const isTableLikeComponent = (component: unknown): boolean => {
  if (!component || typeof component !== "object") return false;
  const c = component as Record<string, any>;
  const candidates: unknown[] = [
    c.componentType,
    c.component_type,
    c.type,
    c.widgetType,
    c.widget_type,
    c.componentConfig?.type,
    c.component_config?.type,
    c.url,
  ];
  return candidates.some((v) => isTableLikeComponentType(v));
};

/**
 * table-like 컴포넌트에서 테이블명을 안전하게 추출.
 *
 * 탐색 순서:
 *   1) componentConfig.selectedTable
 *   2) componentConfig.tableName
 *   3) componentConfig.table_name
 *   4) component_config.selectedTable
 *   5) component_config.tableName
 *   6) component_config.table_name
 *   7) root tableName
 *   8) root table_name
 *
 * 어떤 후보도 비어있지 않은 string 으로 발견되지 않으면 undefined.
 */
export const getTableNameFromTableLikeComponent = (component: unknown): string | undefined => {
  if (!component || typeof component !== "object") return undefined;
  const c = component as Record<string, any>;
  const cfg = c.componentConfig ?? {};
  const cfgSnake = c.component_config ?? {};
  const candidates: unknown[] = [
    cfg.selectedTable,
    cfg.tableName,
    cfg.table_name,
    cfgSnake.selectedTable,
    cfgSnake.tableName,
    cfgSnake.table_name,
    c.tableName,
    c.table_name,
  ];
  for (const v of candidates) {
    if (typeof v === "string" && v.length > 0) return v;
  }
  return undefined;
};
