"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import {
  selectTableRows,
  type SelectRowsOrderBy,
  type SelectRowsResponse,
} from "@/lib/api/stats";
import type { OptionFilter } from "@/lib/registry/components/input/use-option-loader";

/**
 * useTableRows — Phase G.3.1 view 컴포넌트 (card-list / grouped-table) 공통 fetch hook.
 *
 *   - 디자인 모드: API 호출 0. preview row 반환
 *   - dataSource.tableName 없으면 preview
 *   - request key 캐시
 *   - version counter race guard
 *   - 카드/탭 단위 error 격리
 *   - `OptionFilter.value_type` 의 field / user 는 formData / userContext 로 치환
 */

export interface TableRowsDataSource {
  tableName?: string;
  columns?: string[];
  filters?: OptionFilter[];
  orderBy?: SelectRowsOrderBy[];
  limit?: number;
}

export interface UseTableRowsOptions {
  isDesignMode?: boolean;
  formData?: Record<string, unknown>;
  userContext?: {
    companyCode?: string;
    userId?: string;
    deptCode?: string;
    userName?: string;
  };
  refreshKey?: number | string;
  /** preview 모드의 가짜 row 개수 (기본 4) */
  previewCount?: number;
  /** preview row 생성기 — 컴포넌트별 맞춤 가능 */
  previewBuilder?: (index: number) => Record<string, any>;
}

export interface TableRowsState {
  rows: Record<string, any>[];
  loading: boolean;
  error?: string;
  /** dataSource 미완성으로 preview 만 보여주는 중인지 */
  isPreview: boolean;
}

function defaultPreview(count: number): Record<string, any>[] {
  const out: Record<string, any>[] = [];
  for (let i = 0; i < count; i++) {
    out.push({
      __preview: true,
      __index: i,
      title: `샘플 ${i + 1}`,
      subtitle: `미리보기 항목 ${i + 1}`,
      value: (i + 1) * 7,
    });
  }
  return out;
}

function resolveFilters(
  filters: OptionFilter[] | undefined,
  formData: Record<string, unknown> | undefined,
  userContext: UseTableRowsOptions["userContext"],
): { resolved: Array<{ column: string; operator: string; value?: unknown }>; ok: boolean } {
  if (!filters || filters.length === 0) return { resolved: [], ok: true };
  const out: Array<{ column: string; operator: string; value?: unknown }> = [];
  for (const f of filters) {
    if (!f || !f.column) continue;
    const op = f.operator ?? "=";
    if (op === "isNull" || op === "isNotNull") {
      out.push({ column: f.column, operator: op });
      continue;
    }
    let value: unknown = f.value;
    const valueType = f.value_type ?? "static";
    if (valueType === "field") {
      const ref = f.field_ref;
      if (!ref) return { resolved: [], ok: false };
      value = formData?.[ref];
      if (value === undefined) return { resolved: [], ok: false };
    } else if (valueType === "user") {
      const uf = f.user_field;
      if (!uf) return { resolved: [], ok: false };
      value = userContext?.[uf];
      if (value === undefined || value === "") return { resolved: [], ok: false };
    }
    if (value === undefined || value === null) continue;
    out.push({ column: f.column, operator: op, value });
  }
  return { resolved: out, ok: true };
}

function buildRequestKey(
  ds: TableRowsDataSource,
  filters: Array<{ column: string; operator: string; value?: unknown }>,
): string {
  return JSON.stringify({
    t: ds.tableName,
    c: ds.columns ?? null,
    o: ds.orderBy ?? null,
    l: ds.limit ?? 50,
    f: filters,
  });
}

function isReady(ds: TableRowsDataSource | undefined): boolean {
  return !!(ds && ds.tableName);
}

export function useTableRows(
  dataSource: TableRowsDataSource | undefined,
  opts: UseTableRowsOptions = {},
): TableRowsState {
  const { isDesignMode, formData, userContext, refreshKey, previewCount, previewBuilder } = opts;

  const previewRows = useMemo<Record<string, any>[]>(() => {
    const n = Math.max(2, Math.min(12, previewCount ?? 4));
    if (previewBuilder) {
      const out: Record<string, any>[] = [];
      for (let i = 0; i < n; i++) out.push(previewBuilder(i));
      return out;
    }
    return defaultPreview(n);
  }, [previewCount, previewBuilder]);

  const [state, setState] = useState<TableRowsState>({
    rows: previewRows,
    loading: false,
    isPreview: true,
  });

  const plan = useMemo(() => {
    if (!isReady(dataSource)) return { skip: true as const };
    const { resolved, ok } = resolveFilters(dataSource!.filters, formData, userContext);
    if (!ok) return { skip: true as const, pending: true as const };
    const reqKey = buildRequestKey(dataSource!, resolved);
    return {
      skip: false as const,
      reqKey,
      req: {
        tableName: dataSource!.tableName!,
        columns: dataSource!.columns,
        filters: resolved,
        orderBy: dataSource!.orderBy,
        limit: dataSource!.limit ?? 50,
      },
    };
  }, [dataSource, formData, userContext]);

  const cacheRef = useRef<Map<string, Record<string, any>[]>>(new Map());
  const versionRef = useRef(0);

  useEffect(() => {
    if (isDesignMode) {
      cacheRef.current.clear();
      setState({ rows: previewRows, loading: false, isPreview: true });
      return;
    }
    if (plan.skip) {
      setState({ rows: previewRows, loading: false, isPreview: true });
      return;
    }

    versionRef.current += 1;
    const myVersion = versionRef.current;
    let cancelled = false;

    if (refreshKey !== undefined) cacheRef.current.clear();

    const cached = cacheRef.current.get(plan.reqKey!);
    if (cached !== undefined && refreshKey === undefined) {
      setState({ rows: cached, loading: false, isPreview: false });
      return;
    }

    setState((prev) => ({ ...prev, loading: true, error: undefined }));

    (async () => {
      try {
        const res: SelectRowsResponse = await selectTableRows(plan.req!.tableName, {
          columns: plan.req!.columns,
          filters: plan.req!.filters as any,
          orderBy: plan.req!.orderBy,
          limit: plan.req!.limit,
        });
        if (cancelled || versionRef.current !== myVersion) return;
        cacheRef.current.set(plan.reqKey!, res.rows);
        setState({ rows: res.rows, loading: false, isPreview: false });
      } catch (err: any) {
        if (cancelled || versionRef.current !== myVersion) return;
        const msg = err?.response?.data?.message || err?.message || "데이터 로드 실패";
        setState({ rows: [], loading: false, isPreview: false, error: String(msg) });
      }
    })();

    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [plan, isDesignMode, refreshKey, previewRows]);

  return state;
}
