'use client';

/**
 * BlockRenderer — 하나의 BlockV2 를 실제 React 컴포넌트로 렌더한다.
 *   ComponentRegistry 에서 componentId 로 정의를 찾아 위임.
 *
 * TemplateRenderer (line grid) 와 PopupTemplateRenderer (absolute) 양쪽에서
 * 공유되는 최소 단위. 별도 파일로 분리한 이유는 팝업 번들 경량화 —
 * PopupTemplateRenderer 가 TemplateRenderer 전체(line layout 알고리즘 800+줄)
 * 를 딸려 로드하지 않도록.
 */

import React from 'react';
import type { BlockV2, CanvasV2 } from '@/types/invyone-component';
import { ComponentRegistry } from '@/lib/registry/ComponentRegistry';
import { isTableLikeComponentType } from '@/lib/utils/componentTypeUtils';
// side-effect: 컴포넌트 레지스트리 등록
import '@/lib/registry/components';
import type { TemplateRenderContext, ViewKey } from './TemplateRenderer';

export function BlockRenderer({
  block,
  context,
  view,
  canvas,
  runtimeSize,
}: {
  block: BlockV2;
  context: TemplateRenderContext;
  view: ViewKey;
  /**
   * 선택: 제공되면 block 의 %좌표를 px 로 환산해 컴포넌트에 전달한다.
   * line grid 의 실제 runtime cell 크기를 component.size 로 전달한다.
   */
  canvas?: CanvasV2;
  runtimeSize?: {
    width: number;
    height: number;
  };
}) {
  const resolvedTableName =
    block.config?.selectedTable ||
    block.config?.tableName ||
    context.primaryTable;
  const resolvedColumnName =
    block.config?.columnName ||
    block.config?.column_name ||
    block.config?.fieldKey ||
    block.config?.bindField ||
    block.config?.column;
  const resolvedValue =
    resolvedColumnName != null
      ? context.formRow?.[resolvedColumnName]
      : undefined;
  // 사용자가 ConfigPanel 에 설정한 defaultValue 를 form data 값이 없을 때 보존.
  // formRow[col] 가 의미있는 값일 때만 defaultValue 로 hijack — undefined/null 은 무시.
  const runtimeConfig =
    resolvedColumnName != null && resolvedValue !== undefined && resolvedValue !== null
      ? { ...block.config, defaultValue: resolvedValue }
      : block.config;
  const handleFormValueChange = (
    fieldNameOrPatch: string | Record<string, any>,
    value?: any,
  ) => {
    if (typeof fieldNameOrPatch === 'string') {
      context.onFormRowChange?.({ [fieldNameOrPatch]: value });
      return;
    }
    context.onFormRowChange?.(fieldNameOrPatch);
  };

  const registryComponentId = isTableLikeComponentType(block.componentId)
    ? 'table'
    : block.componentId;
  const def = ComponentRegistry.getComponent(registryComponentId);
  if (!def?.component) {
    return (
      <div className="flex h-full w-full items-center justify-center rounded border border-dashed border-slate-300 bg-slate-50 p-2 text-center text-[10px] text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
        <div>
          <div className="font-mono text-[11px] font-bold">
            {block.componentId || '(empty)'}
          </div>
          <div className="opacity-70">미등록</div>
        </div>
      </div>
    );
  }
  const Cmp = def.component as React.ComponentType<any>;

  const bw = canvas?.baseWidth ?? 0;
  const bh = canvas?.baseHeight ?? 0;
  const position = {
    x: bw > 0 ? block.xPct * bw : 0,
    y: bh > 0 ? block.yPct * bh : 0,
    z: 1,
  };
  const size = {
    width: bw > 0 ? block.wPct * bw : 0,
    height: bh > 0 ? block.hPct * bh : 0,
  };
  const isButtonLike =
    block.componentId === 'button' ||
    block.componentId === 'button-bar' ||
    block.componentId === 'pagination';
  const effectiveSize =
    isButtonLike && runtimeSize
      ? {
          width:
            runtimeSize.width > 0
              ? Math.min(size.width, Math.max(0, runtimeSize.width - 2))
              : size.width,
          height:
            runtimeSize.height > 0
              ? Math.min(size.height, Math.max(0, runtimeSize.height - 2))
              : size.height,
        }
      : size;

  return (
    <Cmp
      component={{
        id: block.id,
        componentType: block.componentId,
        tableName: resolvedTableName,
        columnName: resolvedColumnName,
        column_name: resolvedColumnName,
        value: resolvedValue,
        position,
        size: effectiveSize,
        componentConfig: runtimeConfig,
        component_config: runtimeConfig,
        style: {},
      }}
      componentConfig={runtimeConfig}
      config={runtimeConfig}
      tableName={resolvedTableName}
      columnName={resolvedColumnName}
      column_name={resolvedColumnName}
      value={resolvedValue}
      isDesignMode={false}
      isPreview={true}
      isInteractive={true}
      formData={context.formRow}
      form_data={context.formRow}
      onFormDataChange={(fieldName: string, value: any) =>
        handleFormValueChange(fieldName, value)
      }
      onChange={(value: any) =>
        resolvedColumnName
          ? handleFormValueChange(resolvedColumnName, value)
          : undefined
      }
      originalData={context.formRow}
      _originalData={context.formRow}
      onSearch={context.onSearch}
      searchParams={context.searchParams}
      onRowSelect={context.onRowSelect}
      onAdd={context.onAdd}
      onEdit={context.onEdit}
      onDelete={context.onDelete}
      onFormSubmit={context.onFormSubmit}
      onFormCancel={context.onFormCancel}
      selectedRow={context.selectedRow}
      view={view}
    />
  );
}
