/**
 * INVYONE 스튜디오 ↔ templates 테이블 어댑터
 *
 * ScreenDesigner 의 layout 객체는 screens 테이블(layout-v2 JSON)을 기준으로 설계되어 있음.
 * INVYONE 스튜디오는 templates 테이블(fields/views/connections 3-jsonb 분리) 을 사용하므로
 * 두 포맷 사이 왕복 변환을 이 어댑터가 담당한다.
 *
 * - saveTemplate: 현재 layout + 3뷰 캐시 → templates.views JSON 으로 저장
 * - loadTemplateAsLayout: templates.views JSON → ScreenDesigner 가 기대하는 layout + 3뷰 캐시
 *
 * 규칙: Record<string, any> 원칙 유지 (invyone-component.ts 의 확정 타입 외 금지).
 */

import {
  getTemplateInfo,
  insertTemplate,
  updateTemplate,
} from "@/lib/api/template";
import { convertLegacyToV2, convertV2ToLegacy } from "./layoutV2Converter";

export interface TemplateSavePayload {
  templateId: string;
  name: string;
  category?: string;
  description?: string;
  primaryTable?: string;
  /** 현재 list 뷰 layout (components, gridSettings, screenResolution 포함) */
  layout: Record<string, any>;
  /** v2 포맷 컴포넌트 배열 — 등록/수정 뷰 */
  v2Views?: {
    create?: Record<string, any>[];
    edit?: Record<string, any>[];
  };
  /** 뷰별 해상도 */
  viewScreenResolutions?: {
    list?: Record<string, any>;
    create?: Record<string, any>;
    edit?: Record<string, any>;
  };
  /** 템플릿 수준 필드 규격 (아직 미사용, 확장용) */
  fields?: Record<string, any>[];
  /** DataPort 연결 (아직 미사용, 확장용) */
  connections?: Record<string, any>[];
}

/**
 * 현재 layout + 3뷰 캐시를 templates.views JSON 으로 직렬화해서 updateTemplate 호출.
 * 등록/수정/수정용 뷰는 v2 포맷으로, list 뷰는 convertLegacyToV2 를 거친 후 함께 묶어서 저장.
 */
export async function saveTemplate(p: TemplateSavePayload): Promise<void> {
  const v2Layout = convertLegacyToV2(p.layout as any);

  // screenResolutions 병합을 key-level 폴백으로 강화.
  // 기존: `p.viewScreenResolutions ?? 전체폴백` → {} 나 일부 키 누락 시 정보 유실
  // 개선: 항상 3뷰 모두 값이 보장되게 key 별로 폴백 처리
  const fallbackSr = p.layout.screenResolution;
  const vsrIn = (p.viewScreenResolutions ?? {}) as Record<string, any>;
  const screenResolutions = {
    list: vsrIn.list ?? fallbackSr,
    create: vsrIn.create ?? fallbackSr,
    edit: vsrIn.edit ?? fallbackSr,
  };

  const viewsJson = {
    list: (v2Layout as any)?.components ?? [],
    create: p.v2Views?.create ?? [],
    edit: p.v2Views?.edit ?? [],
    gridSettings: p.layout.gridSettings,
    screenResolution: fallbackSr,
    screenResolutions,
    mainTableName: p.primaryTable,
  };

  // 진단 로그 — 저장 payload 확인용. 문제 재현 시 여기서 확인 가능.
  /* eslint-disable no-console */
  console.log("[saveTemplate] payload", {
    templateId: p.templateId,
    viewsKeys: Object.keys(viewsJson),
    screenResolutions,
    listCount: viewsJson.list.length,
    createCount: viewsJson.create.length,
    editCount: viewsJson.edit.length,
  });
  /* eslint-enable no-console */

  const payload: Record<string, any> = {
    name: p.name,
    category: p.category ?? "custom",
    description: p.description ?? "",
    primary_table: p.primaryTable ?? "",
    fields: JSON.stringify(p.fields ?? []),
    views: JSON.stringify(viewsJson),
    connections: JSON.stringify(p.connections ?? []),
  };
  await updateTemplate(p.templateId, payload);
}

/**
 * 신규 template 레코드 생성 — 빈 views/fields/connections 로 시작.
 * 반환된 template_id 는 URL 쿼리 등에 사용.
 */
export async function createTemplate(data: {
  name: string;
  category?: string;
  description?: string;
  primaryTable?: string;
}): Promise<Record<string, any>> {
  const payload: Record<string, any> = {
    name: data.name,
    category: data.category ?? "custom",
    description: data.description ?? "",
    primary_table: data.primaryTable ?? "",
    fields: JSON.stringify([]),
    views: JSON.stringify({ list: [], create: [], edit: [] }),
    connections: JSON.stringify([]),
  };
  const res = await insertTemplate(payload);
  return res ?? {};
}

export interface LoadedTemplate {
  templateInfo: Record<string, any>;
  /** ScreenDesigner 의 layout 상태에 그대로 setLayout 으로 주입 가능 */
  layout: Record<string, any>;
  /** viewLayoutsRef.current.create / edit 에 주입할 legacy 컴포넌트 배열 */
  viewLayouts: {
    create: any[];
    edit: any[];
  };
  primaryTable: string;
  screenResolution?: Record<string, any>;
  viewScreenResolutions?: {
    list?: Record<string, any>;
    create?: Record<string, any>;
    edit?: Record<string, any>;
  };
}

function parseJsonMaybe(raw: any): any {
  if (raw == null) return null;
  if (typeof raw === "object") return raw;
  if (typeof raw === "string") {
    try {
      return JSON.parse(raw);
    } catch {
      return null;
    }
  }
  return null;
}

/**
 * templates.views JSON → ScreenDesigner layout + 3뷰 캐시로 역직렬화.
 * 목록/등록/수정 3뷰가 모두 저장되어 있으면 각각 Legacy 포맷으로 변환.
 */
export async function loadTemplateAsLayout(
  templateId: string,
): Promise<LoadedTemplate | null> {
  const template = await getTemplateInfo(templateId);
  if (!template) return null;

  const viewsObj =
    parseJsonMaybe(template.views) ?? parseJsonMaybe(template.VIEWS) ?? {};

  const listV2 = Array.isArray(viewsObj.list) ? viewsObj.list : [];
  const createV2 = Array.isArray(viewsObj.create) ? viewsObj.create : [];
  const editV2 = Array.isArray(viewsObj.edit) ? viewsObj.edit : [];
  const viewScreenResolutions = viewsObj.screenResolutions ?? {
    list: viewsObj.screenResolution,
    create: viewsObj.screenResolution,
    edit: viewsObj.screenResolution,
  };

  const legacyListLayout = convertV2ToLegacy({
    components: listV2,
    gridSettings: viewsObj.gridSettings,
    screenResolution: viewsObj.screenResolution,
  } as any) ?? { components: [] };

  const createLegacy = createV2.length
    ? convertV2ToLegacy({ components: createV2 } as any)?.components ?? []
    : [];
  const editLegacy = editV2.length
    ? convertV2ToLegacy({ components: editV2 } as any)?.components ?? []
    : [];

  return {
    templateInfo: template,
    layout: {
      ...legacyListLayout,
      gridSettings: viewsObj.gridSettings ?? (legacyListLayout as any).gridSettings,
      screenResolution:
        viewsObj.screenResolution ?? (legacyListLayout as any).screenResolution,
    },
    viewLayouts: {
      create: createLegacy,
      edit: editLegacy,
    },
    primaryTable:
      template.primary_table ?? template.PRIMARY_TABLE ?? viewsObj.mainTableName ?? "",
    screenResolution: viewsObj.screenResolution,
    viewScreenResolutions,
  };
}
