"use client";

import React from "react";
import * as LucideIcons from "lucide-react";
import { ComponentRendererProps } from "@/types/component";
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
import { StatsConfig, StatsItem, StatsOrientation, StatsStyle } from "./types";
import { useStatsData } from "./use-stats-data";

/**
 * Stats — 통합 통계/KPI 카드 컴포넌트
 *
 * items 배열을 받아 각각을 카드/칩/빅넘버 형태로 렌더. Phase G.1 부터 각 항목의
 * `dataSource.tableName` 이 있으면 백엔드 `/aggregate` 결과로 값을 채우고, 없으면
 * 기존 정적 `item.value` 를 그대로 사용. 디자인 모드에서는 API 호출 안 함.
 */

const VALID_ORIENTATIONS: StatsOrientation[] = ["horizontal", "vertical", "grid"];
const VALID_STYLES: StatsStyle[] = ["card", "chip", "bigNumber"];

export interface StatsComponentProps extends ComponentRendererProps {
  config?: StatsConfig;
}

export const StatsComponent: React.FC<StatsComponentProps> = ({
  component,
  isDesignMode = false,
  isSelected = false,
  onClick,
  onDragStart,
  onDragEnd,
  config,
  className,
  style,
  ...props
}) => {
  // ─── 4경로 머지 ───────────────────────────────────────────────────────
  const fromProps: Partial<StatsConfig> = {};
  const p = props as any;
  if (Array.isArray(p.items)) fromProps.items = p.items;
  if (typeof p.orientation === "string" && (VALID_ORIENTATIONS as string[]).includes(p.orientation))
    fromProps.orientation = p.orientation;
  if (typeof p.style === "string" && (VALID_STYLES as string[]).includes(p.style))
    fromProps.style = p.style;
  if (typeof p.columns === "number") fromProps.columns = p.columns;
  if (typeof p.sourceTable === "string") fromProps.sourceTable = p.sourceTable;
  if (typeof p.title === "string") fromProps.title = p.title;

  const componentConfig = {
    ...config,
    ...((component as any).config ?? {}),
    ...((component as any).componentConfig ?? {}),
    ...fromProps,
  } as StatsConfig;

  // Phase G.4.2 — DB-first default. 정적 value 박지 않음. dataSource 는 비어
  // 있어도 디자인 모드에서 "—" 로 표시. 운영 모드에서 사용자가 테이블/집계 채우면
  // 자동 동작.
  const items: StatsItem[] = componentConfig.items ?? [
    { label: "항목 1", dataSource: { aggregation: "count" } },
    { label: "항목 2", dataSource: { aggregation: "count" } },
    { label: "항목 3", dataSource: { aggregation: "count" } },
  ];

  // Phase G.1 — dataSource 가 있는 항목은 백엔드에서 가져온다.
  const userContext = React.useMemo(
    () => ({
      companyCode: (p.companyCode as string) || undefined,
      userId: (p.userId as string) || undefined,
      deptCode: (p.deptCode as string) || undefined,
      userName: (p.userName as string) || undefined,
    }),
    // 단순 값들이라 deps 직접 나열
    [p.companyCode, p.userId, p.deptCode, p.userName],
  );
  const statsData = useStatsData(items, {
    isDesignMode,
    formData: (p.formData as Record<string, unknown>) || undefined,
    userContext,
    refreshKey: (p.refreshKey as number | string | undefined) || undefined,
  });

  const orientation: StatsOrientation = componentConfig.orientation ?? "horizontal";
  const statsStyle: StatsStyle = componentConfig.style ?? "card";
  // columns 미지정 시 undefined → auto-fit 이 폭에 맞춰 자동 결정 (5개면 5열 등).
  // columns 지정 시에만 최대 컬럼 수 상한으로 동작.
  const columns: number | undefined = componentConfig.columns;
  const title = componentConfig.title;

  // componentConfig.style 이 "card" 같은 문자열인 경우, 또는 spread 잔재로 숫자 키가
  // 생긴 경우({0:"c",1:"a",...})에 대한 방어. CSS 로 쓸 수 없는 키/값은 제거.
  const asStyleObject = (v: any): React.CSSProperties => {
    if (!v || typeof v !== "object" || Array.isArray(v)) return {};
    const out: Record<string, any> = {};
    for (const [k, val] of Object.entries(v)) {
      if (/^\d+$/.test(k)) continue; // 숫자 키(indexed object 잔재) 제거
      if (Array.isArray(val)) continue; // 배열 값 제거
      out[k] = val;
    }
    return out;
  };
  const containerStyle: React.CSSProperties = {
    width: "100%",
    height: "100%",
    display: "flex",
    flexDirection: "column",
    gap: "8px",
    padding: "8px",
    boxSizing: "border-box",
    ...asStyleObject((component as any).style),
    ...asStyleObject(style),
  };

  if (isDesignMode && isSelected) {
    containerStyle.outline = "2px solid hsl(var(--primary))";
    containerStyle.outlineOffset = "2px";
  }

  // 반응 정책: columns 는 최대 컬럼 수 상한으로만 동작. 실제 배치는 auto-fit
  // minmax 로 처리해, 카드 폭이 줄어들면 자동으로 열 수가 감소하고 각 카드의
  // 최소 폭(180px)은 유지된다. (notes/2026-04-19-template-responsive-policy.md §4.3)
  const minItemWidth = 180;
  const itemsContainerStyle: React.CSSProperties = (() => {
    if (orientation === "vertical") {
      return {
        display: "flex",
        flexDirection: "column",
        gap: "8px",
        flex: 1,
        minHeight: 0,
      };
    }
    // horizontal / grid → auto-fit 재배치
    const gridTemplateColumns = columns
      ? `repeat(auto-fit, minmax(max(${minItemWidth}px, calc((100% - ${(columns - 1) * 8}px) / ${columns})), 1fr))`
      : `repeat(auto-fit, minmax(${minItemWidth}px, 1fr))`;
    return {
      display: "grid",
      gridTemplateColumns,
      gap: "8px",
      flex: 1,
      minHeight: 0,
    };
  })();

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClick?.();
  };

  /* eslint-disable @typescript-eslint/no-unused-vars */
  const {
    selectedScreen: _1,
    onZoneComponentDrop: _2,
    onZoneClick: _3,
    componentConfig: _4,
    component: _5,
    isSelected: _6,
    onClick: _7,
    onDragStart: _8,
    onDragEnd: _9,
    size: _10,
    position: _11,
    style: _12,
    screenId: _13,
    tableName: _14,
    onRefresh: _15,
    onClose: _16,
    web_type: _17,
    autoGeneration: _18,
    isInteractive: _19,
    formData: _20,
    onFormDataChange: _21,
    menuId: _22,
    menuObjid: _23,
    onSave: _24,
    userId: _25,
    userName: _26,
    companyCode: _27,
    isInModal: _28,
    readonly: _29,
    originalData: _30,
    _originalData: _31,
    _initialData: _32,
    _groupedData: _33,
    allComponents: _34,
    onUpdateLayout: _35,
    selectedRows: _36,
    selectedRowsData: _37,
    onSelectedRowsChange: _38,
    sortBy: _39,
    sortOrder: _40,
    tableDisplayData: _41,
    flowSelectedData: _42,
    flowSelectedStepId: _43,
    onFlowSelectedDataChange: _44,
    onConfigChange: _45,
    refreshKey: _46,
    flowRefreshKey: _47,
    onFlowRefresh: _48,
    isPreview: _49,
    groupedData: _50,
    // ★ StatsConfig 필드 제외
    items: _51,
    orientation: _52,
    style: _53_style,
    columns: _54,
    sourceTable: _55,
    title: _56,
    // 기타 noise
    disabled: _57,
    required: _58,
    ...domProps
  } = props as any;
  /* eslint-enable @typescript-eslint/no-unused-vars */

  const formatValue = (raw: unknown): string => {
    if (raw === null || raw === undefined || raw === "") return "—";
    if (typeof raw === "number") {
      // 정수면 그대로, 소수는 소숫점 둘째자리까지 컷
      if (Number.isInteger(raw)) return raw.toLocaleString();
      return raw.toLocaleString(undefined, { maximumFractionDigits: 2 });
    }
    return String(raw);
  };

  const renderIcon = (
    iconName: string | undefined,
    size: number,
    color: string,
  ): React.ReactNode => {
    if (!iconName) return null;
    const Icon = (LucideIcons as unknown as Record<string, React.ElementType | undefined>)[
      iconName
    ];
    if (Icon) {
      return React.createElement(Icon, {
        size,
        strokeWidth: 2,
        style: { color, flexShrink: 0 },
        "aria-hidden": true,
      });
    }
    return (
      <span style={{ lineHeight: 1, color, flexShrink: 0 }} aria-hidden="true">
        {iconName}
      </span>
    );
  };

  const renderItem = (item: StatsItem, idx: number) => {
    const key = item.id != null ? String(item.id) : String(idx);
    const fetched = statsData[key];
    const hasDataSource = !!item.dataSource?.tableName;

    let displayValue: React.ReactNode;
    let stateNote: { text: string; tone: "muted" | "error" } | null = null;

    if (hasDataSource) {
      if (fetched?.loading) {
        displayValue = "…";
        stateNote = { text: "로딩 중", tone: "muted" };
      } else if (fetched?.error) {
        displayValue = "—";
        stateNote = { text: fetched.error, tone: "error" };
      } else if (fetched?.value !== undefined) {
        displayValue = formatValue(fetched.value);
      } else {
        // fetch 아직 안 됨. fallback 있으면 표시, 아니면 "—"
        displayValue = item.value !== undefined ? formatValue(item.value) : "—";
        // 카드 안에 안내 (디자인 진단 도움)
        stateNote = { text: "대기 중 / 미실행", tone: "muted" };
      }
    } else {
      // dataSource 미완성: fallback 또는 dim 안내
      displayValue = item.value !== undefined ? formatValue(item.value) : "—";
      stateNote = { text: "테이블 미설정", tone: "muted" };
    }

    const color = item.color ?? "hsl(var(--primary))";

    if (statsStyle === "chip") {
      return (
        <div
          key={idx}
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: "6px",
            padding: "4px 10px",
            borderRadius: "999px",
            background: "hsl(var(--muted))",
            fontSize: "12px",
          }}
        >
          {renderIcon(item.icon, 13, color)}
          <span style={{ color: "hsl(var(--muted-foreground))" }}>{item.label}</span>
          <strong style={{ color }}>{displayValue}</strong>
        </div>
      );
    }

    if (statsStyle === "bigNumber") {
      return (
        <div
          key={idx}
          style={{
            display: "flex",
            flexDirection: "column",
            alignItems: "flex-start",
            gap: "2px",
            padding: "8px 12px",
            flex: 1,
            minWidth: 0,
          }}
        >
          <span
            style={{
              fontSize: "10px",
              color: "hsl(var(--muted-foreground))",
              textTransform: "uppercase",
              letterSpacing: "0.05em",
            }}
          >
            {renderIcon(item.icon, 12, "hsl(var(--muted-foreground))")}
            {item.label}
          </span>
          <span
            style={{
              fontSize: "28px",
              fontWeight: 700,
              color,
              lineHeight: 1,
            }}
          >
            {displayValue}
          </span>
          {stateNote && (
            <span
              style={{
                fontSize: "10px",
                color:
                  stateNote.tone === "error"
                    ? "hsl(var(--destructive))"
                    : "hsl(var(--muted-foreground))",
                maxWidth: "100%",
                overflow: "hidden",
                textOverflow: "ellipsis",
                whiteSpace: "nowrap",
              }}
              title={stateNote.text}
            >
              {stateNote.text}
            </span>
          )}
          {item.delta && (
            <span
              style={{
                fontSize: "11px",
                color:
                  item.deltaDirection === "down"
                    ? "hsl(var(--destructive))"
                    : item.deltaDirection === "up"
                      ? "hsl(142 71% 45%)"
                      : "hsl(var(--muted-foreground))",
              }}
            >
              {item.deltaDirection === "up" && "▲ "}
              {item.deltaDirection === "down" && "▼ "}
              {item.delta}
            </span>
          )}
        </div>
      );
    }

    // default: card
    return (
      <div
        key={idx}
        style={{
          display: "flex",
          flexDirection: "column",
          gap: "4px",
          padding: "10px 12px",
          border: "1px solid hsl(var(--border))",
          borderRadius: "8px",
          background: "hsl(var(--card))",
          flex: 1,
          minWidth: 0,
        }}
      >
        <span
          style={{
            fontSize: "11px",
            color: "hsl(var(--muted-foreground))",
            fontWeight: 600,
          }}
        >
          {renderIcon(item.icon, 12, "hsl(var(--muted-foreground))")}
          {item.label}
        </span>
        <span
          style={{
            fontSize: "20px",
            fontWeight: 700,
            color,
            lineHeight: 1.1,
          }}
        >
          {displayValue}
        </span>
        {stateNote && (
          <span
            style={{
              fontSize: "10px",
              color:
                stateNote.tone === "error"
                  ? "hsl(var(--destructive))"
                  : "hsl(var(--muted-foreground))",
              maxWidth: "100%",
              overflow: "hidden",
              textOverflow: "ellipsis",
              whiteSpace: "nowrap",
            }}
            title={stateNote.text}
          >
            {stateNote.text}
          </span>
        )}
        {item.delta && (
          <span
            style={{
              fontSize: "10px",
              color:
                item.deltaDirection === "down"
                  ? "hsl(var(--destructive))"
                  : item.deltaDirection === "up"
                    ? "hsl(142 71% 45%)"
                    : "hsl(var(--muted-foreground))",
            }}
          >
            {item.deltaDirection === "up" && "▲ "}
            {item.deltaDirection === "down" && "▼ "}
            {item.delta}
          </span>
        )}
      </div>
    );
  };

  return (
    <div
      style={containerStyle}
      className={className}
      onClick={handleClick}
      onDragStart={onDragStart}
      onDragEnd={onDragEnd}
      {...filterDOMProps(domProps)}
    >
      {title && (
        <div
          style={{
            fontSize: "13px",
            fontWeight: 700,
            color: "hsl(var(--foreground))",
          }}
        >
          {title}
        </div>
      )}
      <div style={itemsContainerStyle}>
        {items.map((item, idx) => renderItem(item, idx))}
      </div>
    </div>
  );
};

export const StatsWrapper: React.FC<StatsComponentProps> = (props) => {
  return <StatsComponent {...props} />;
};
