/**
 * FieldConfig Adapter — INVYONE FieldConfig[] 를 기존 v2-* 컴포넌트 내부 포맷
 * (ColumnConfig / SearchField / FormField) 으로 변환한다.
 *
 * 역할:
 *   화면 디자이너에서 Screen 수준으로 정의한 fields 배열을 각 컴포넌트가
 *   소비할 수 있는 기존 포맷으로 풀어주는 브리지. 컴포넌트 자체를 FieldConfig
 *   네이티브로 리팩토링하기 전까지의 호환 레이어.
 *
 * 원칙:
 *   - 호환성 우선. 기존 포맷에 없는 필드는 버리고 기본값은 보존.
 *   - 타입은 Record<string, any>. v2-* 포맷이 컴포넌트마다 달라 강타입 못 씀.
 *   - fields 가 없으면 호출부는 fallback 으로 기존 config.columns 사용 (이 파일
 *     호출 자체를 건너뛰어야 함).
 */
import type { FieldConfig } from "@/types/invyone-component";

/**
 * FieldConfig[] → v2-table-list 의 ColumnConfig[] 호환 배열.
 *
 * 상세 매핑 규칙은 v2-table-list 내부 포맷 확정 후 보강한다. 현재는 공통 필드
 * (column_name / column_label / visible / display_order / width / align / sortable)
 * 만 매핑.
 */
export function fieldsToColumns(
  fields: FieldConfig[],
): Record<string, any>[] {
  return [...fields]
    .filter((f) => f.visible !== false && !f.system)
    .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
    .map((f) => ({
      column_name: f.column,
      column_label: f.label,
      label: f.label,
      visible: f.visible !== false,
      display_order: f.order ?? 0,
      width: f.width,
      align: f.align ?? (f.type === "number" ? "right" : "left"),
      sortable: f.sortable ?? true,
      data_type: f.type,
      format: f.format,
      pk: f.pk ?? false,
      editable: f.editable ?? true,
    }));
}

/**
 * FieldConfig[] → 검색 위젯의 SearchField[] 호환 배열.
 *
 * searchable: true 인 것만 포함. 타입별 기본 검색 모드 매핑:
 *   date/datetime/number → 'range'
 *   select                → 'multi'
 *   entity                → 'single' (팝업)
 *   code                  → 'exact'
 *   text/textarea         → 'partial'
 *   checkbox              → 'tri' (전체/✓/✗)
 */
export function fieldsToSearchFields(
  fields: FieldConfig[],
): Record<string, any>[] {
  return fields
    .filter((f) => f.searchable && !f.system)
    .map((f) => ({
      column_name: f.column,
      column_label: f.label,
      label: f.label,
      data_type: f.type,
      search_mode: getDefaultSearchMode(f.type),
      options: f.options,
      ref: f.ref,
      default_value: f.defaultValue,
    }));
}

/**
 * FieldConfig[] → 폼 컴포넌트의 FormField[] 호환 배열.
 *
 * system 필드는 자동 제외. required / editable / options / ref / computed 는
 * 그대로 전달. pk 이고 code 타입이면 readonly 자동 설정 (자동채번).
 */
export function fieldsToFormFields(
  fields: FieldConfig[],
): Record<string, any>[] {
  return [...fields]
    .filter((f) => f.visible !== false && !f.system)
    .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
    .map((f) => ({
      column_name: f.column,
      column_label: f.label,
      label: f.label,
      data_type: f.type,
      required: f.required ?? false,
      editable: f.editable ?? true,
      readonly: f.editable === false || f.type === "code",
      default_value: f.defaultValue,
      placeholder: f.placeholder,
      options: f.options,
      ref: f.ref,
      format: f.format,
      computed: f.computed,
      pk: f.pk ?? false,
    }));
}

/**
 * 역방향: 기존 컬럼 포맷 → FieldConfig[] 추정.
 *
 * 마이그레이션 도우미. 완벽하지 않음 (검색 모드 역추정 불가, computed 등 누락
 * 가능). 화면 디자이너에서 기존 Screen 을 "FieldConfig 로 자동 채우기" 할 때
 * 초기값 생성용.
 */
export function columnsToFields(
  columns: Record<string, any>[],
): FieldConfig[] {
  return columns.map((col, idx) => ({
    column: col.column_name ?? col.column ?? `col_${idx}`,
    label:
      col.column_label ?? col.label ?? col.column_name ?? `컬럼 ${idx + 1}`,
    type: normalizeType(col.data_type ?? col.type ?? "text"),
    visible: col.visible !== false,
    order: col.display_order ?? idx,
    required: col.required === true,
    editable: col.editable !== false,
    width: col.width,
    align: col.align,
    sortable: col.sortable !== false,
    searchable: col.searchable === true,
    format: col.format,
    options: col.options,
    ref: col.ref,
    pk: col.pk === true,
    system: col.system === true,
  }));
}

// ─── 내부 헬퍼 ──────────────────────────────────────────────────────────

type SearchMode = "exact" | "partial" | "range" | "multi" | "single" | "tri";

function getDefaultSearchMode(type: FieldConfig["type"]): SearchMode {
  switch (type) {
    case "date":
    case "datetime":
    case "number":
      return "range";
    case "select":
      return "multi";
    case "entity":
      return "single";
    case "code":
      return "exact";
    case "checkbox":
      return "tri";
    case "text":
    case "textarea":
    default:
      return "partial";
  }
}

function normalizeType(raw: string): FieldConfig["type"] {
  const allowed: FieldConfig["type"][] = [
    "text",
    "number",
    "date",
    "datetime",
    "time",
    "daterange",
    "select",
    "entity",
    "checkbox",
    "textarea",
    "file",
    "code",
  ];
  return (allowed as string[]).includes(raw)
    ? (raw as FieldConfig["type"])
    : "text";
}
