/**
 * 다중 커넥션 관리 API 클라이언트
 */

import { apiClient } from "./client";

/**
 * 데이터 타입을 웹 타입으로 매핑하는 함수
 * @param dataType - 데이터베이스 데이터 타입
 * @returns 웹 타입 문자열
 */
const mapDataTypeToWebType = (dataType: string | undefined | null): string => {
  if (!dataType || typeof dataType !== "string") {
    console.warn(`⚠️ 잘못된 데이터 타입: ${dataType}, 기본값 'text' 사용`);
    return "text";
  }

  const lowerType = dataType.toLowerCase();

  // 텍스트 타입
  if (lowerType.includes("varchar") || lowerType.includes("char") || lowerType.includes("text")) {
    return "text";
  }

  // 숫자 타입
  if (lowerType.includes("int") || lowerType.includes("bigint") || lowerType.includes("smallint")) {
    return "number";
  }
  if (
    lowerType.includes("decimal") ||
    lowerType.includes("numeric") ||
    lowerType.includes("float") ||
    lowerType.includes("double")
  ) {
    return "decimal";
  }

  // 날짜/시간 타입
  if (lowerType.includes("timestamp") || lowerType.includes("datetime")) {
    return "datetime";
  }
  if (lowerType.includes("date")) {
    return "date";
  }
  if (lowerType.includes("time")) {
    return "time";
  }

  // 불린 타입
  if (lowerType.includes("boolean") || lowerType.includes("bit")) {
    return "boolean";
  }

  // 바이너리/파일 타입
  if (lowerType.includes("bytea") || lowerType.includes("blob") || lowerType.includes("binary")) {
    return "file";
  }

  // JSON 타입
  if (lowerType.includes("json")) {
    return "text";
  }

  // 기본값
  console.log(`🔍 알 수 없는 데이터 타입: ${dataType} → text로 매핑`);
  return "text";
};

/**
 * 컬럼명으로부터 코드 카테고리를 추론
 * 실제 존재하는 카테고리만 반환하도록 개선
 */
const inferCodeCategory = (columnName: string): string => {
  const lowerName = columnName.toLowerCase();

  // 실제 데이터베이스에 존재하는 것으로 확인된 카테고리만 반환
  if (lowerName.includes("status")) return "STATUS";

  // 다른 카테고리들은 실제 존재 여부를 확인한 후 추가
  // if (lowerName.includes("type")) return "TYPE";
  // if (lowerName.includes("grade")) return "GRADE";
  // if (lowerName.includes("level")) return "LEVEL";
  // if (lowerName.includes("priority")) return "PRIORITY";
  // if (lowerName.includes("category")) return "CATEGORY";
  // if (lowerName.includes("role")) return "ROLE";

  // 확인되지 않은 컬럼은 일단 STATUS로 매핑 (임시)
  return "STATUS";
};

export interface MultiConnectionTableInfo {
  tableName: string;
  displayName?: string;
  columnCount: number;
  connectionId: number;
  connectionName: string;
  dbType: string;
}

export interface ColumnInfo {
  columnName: string;
  displayName: string;
  dataType: string;
  dbType: string;
  webType: string;
  isNullable: boolean;
  isPrimaryKey: boolean;
  defaultValue?: string;
  maxLength?: number;
  description?: string;
}

export interface ConnectionInfo {
  id: number;
  connection_name: string;
  description?: string;
  db_type: string;
  host: string;
  port: number;
  database_name: string;
  username: string;
  is_active: string;
  company_code: string;
  created_date: Date;
  updated_date: Date;
}

export interface ValidationResult {
  isValid: boolean;
  error?: string;
  warnings?: string[];
}

/**
 * 제어관리용 활성 커넥션 목록 조회 (메인 DB 포함)
 */
export const getActiveConnections = async (): Promise<ConnectionInfo[]> => {
  const response = await apiClient.get("/external-db-connections/control/active");
  return response.data.data || [];
};

/**
 * 특정 커넥션의 테이블 목록 조회
 */
export const getTablesFromConnection = async (connectionId: number): Promise<MultiConnectionTableInfo[]> => {
  const response = await apiClient.get(`/multi-connection/connections/${connectionId}/tables`);
  return response.data.data || [];
};

/**
 * 특정 커넥션의 모든 테이블 정보 배치 조회 (컬럼 수 포함)
 */
export const getBatchTablesWithColumns = async (
  connectionId: number,
): Promise<{ tableName: string; displayName?: string; columnCount: number }[]> => {
  console.log(`🚀 getBatchTablesWithColumns 호출: connectionId=${connectionId}`);

  try {
    const response = await apiClient.get(`/multi-connection/connections/${connectionId}/tables/batch`);
    console.log("✅ 배치 테이블 정보 조회 성공:", response.data);

    const result = response.data.data || [];
    console.log(`📊 배치 조회 결과: ${result.length}개 테이블`, result);

    return result;
  } catch (error) {
    console.error("❌ 배치 테이블 정보 조회 실패:", error);
    throw error;
  }
};

/**
 * 특정 커넥션의 테이블 컬럼 정보 조회
 */
export const getColumnsFromConnection = async (connectionId: number, tableName: string): Promise<ColumnInfo[]> => {
  console.log(`🔍 getColumnsFromConnection 호출: connectionId=${connectionId}, tableName=${tableName}`);

  try {
    // 메인 데이터베이스(connectionId = 0)인 경우 기존 API 사용
    if (connectionId === 0) {
      console.log("📡 메인 DB API 호출:", `/table-management/tables/${tableName}/columns`);
      const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
      console.log("✅ 메인 DB 응답:", response.data);

      const rawResult = response.data.data || [];

      // 메인 DB는 페이지네이션 구조로 반환됨: {columns: [], total, page, size, totalPages}
      const columns = rawResult.columns || rawResult;

      // 메인 DB 컬럼에도 코드 타입 감지 로직 적용
      const result = Array.isArray(columns)
        ? columns.map((col: any) => {
            const columnName = col.columnName || "";

            // 컬럼명으로 코드 타입 감지
            const isCodeColumn =
              columnName.toLowerCase().includes("code") ||
              columnName.toLowerCase().includes("status") ||
              columnName.toLowerCase().includes("type") ||
              columnName.toLowerCase().includes("grade") ||
              columnName.toLowerCase().includes("level");

            return {
              ...col,
              webType: isCodeColumn ? "code" : col.webType || mapDataTypeToWebType(col.dataType),
              codeCategory: isCodeColumn ? inferCodeCategory(columnName) : col.codeCategory,
            };
          })
        : columns;

      console.log("📊 메인 DB 최종 결과:", {
        rawType: typeof rawResult,
        rawIsArray: Array.isArray(rawResult),
        hasColumns: rawResult && typeof rawResult === "object" && "columns" in rawResult,
        finalType: typeof result,
        finalIsArray: Array.isArray(result),
        length: Array.isArray(result) ? result.length : "N/A",
        sample: Array.isArray(result) ? result.slice(0, 1) : result,
      });

      return result;
    }

    // 외부 커넥션인 경우 external-db-connections API 사용
    console.log("📡 외부 DB API 호출:", `/external-db-connections/${connectionId}/tables/${tableName}/columns`);
    const response = await apiClient.get(`/external-db-connections/${connectionId}/tables/${tableName}/columns`);
    console.log("✅ 외부 DB 응답:", response.data);

    const rawResult = response.data.data || [];

    // 외부 DB 컬럼 구조를 메인 DB 형식으로 변환
    const result = Array.isArray(rawResult)
      ? rawResult.map((col: any) => {
          const columnName = col.column_name || col.columnName || "";
          const dataType = col.data_type || col.dataType || "unknown";

          // 컬럼명이 '_code'로 끝나거나 'status', 'type' 등의 이름을 가진 경우 코드 타입으로 간주
          const isCodeColumn =
            columnName.toLowerCase().includes("code") ||
            columnName.toLowerCase().includes("status") ||
            columnName.toLowerCase().includes("type") ||
            columnName.toLowerCase().includes("grade") ||
            columnName.toLowerCase().includes("level");

          return {
            columnName: columnName,
            displayName: col.column_comment || col.displayName || columnName,
            dataType: dataType,
            dbType: dataType,
            webType: isCodeColumn ? "code" : mapDataTypeToWebType(dataType),
            isNullable: col.is_nullable === "YES" || col.isNullable === true,
            columnDefault: col.column_default || col.columnDefault,
            description: col.column_comment || col.description,
            // 코드 타입인 경우 카테고리 추론
            codeCategory: isCodeColumn ? inferCodeCategory(columnName) : undefined,
          };
        })
      : rawResult;

    console.log("📊 외부 DB 최종 결과:", {
      rawType: typeof rawResult,
      rawIsArray: Array.isArray(rawResult),
      finalType: typeof result,
      finalIsArray: Array.isArray(result),
      length: Array.isArray(result) ? result.length : "N/A",
      sample: Array.isArray(result) ? result.slice(0, 1) : result,
      sampleOriginal: Array.isArray(rawResult) ? rawResult.slice(0, 1) : rawResult,
    });

    return result;
  } catch (error) {
    console.error("❌ 컬럼 정보 조회 실패:", error);

    // 개발 환경에서 Mock 데이터 반환
    if (process.env.NODE_ENV === "development") {
      console.warn("🔄 개발 환경: Mock 컬럼 데이터 사용");
      const mockResult = getMockColumnsForTable(tableName);
      console.log("📊 Mock 데이터 반환:", {
        type: typeof mockResult,
        isArray: Array.isArray(mockResult),
        length: mockResult.length,
        sample: mockResult.slice(0, 1),
      });
      return mockResult;
    }

    throw error;
  }
};

/**
 * Mock 컬럼 데이터 (개발/테스트용)
 */
const getMockColumnsForTable = (tableName: string): ColumnInfo[] => {
  const baseColumns: ColumnInfo[] = [
    {
      columnName: "id",
      displayName: "ID",
      dataType: "NUMBER",
      webType: "number",
      isNullable: false,
      isPrimaryKey: true,
      columnComment: "고유 식별자",
    },
    {
      columnName: "name",
      displayName: "이름",
      dataType: "VARCHAR",
      webType: "text",
      isNullable: false,
      isPrimaryKey: false,
      columnComment: "이름",
    },
    {
      columnName: "status",
      displayName: "상태",
      dataType: "VARCHAR",
      webType: "code",
      isNullable: true,
      isPrimaryKey: false,
      columnComment: "상태 코드",
      codeCategory: "STATUS",
    },
    {
      columnName: "created_date",
      displayName: "생성일시",
      dataType: "TIMESTAMP",
      webType: "datetime",
      isNullable: true,
      isPrimaryKey: false,
      columnComment: "생성일시",
    },
    {
      columnName: "updated_date",
      displayName: "수정일시",
      dataType: "TIMESTAMP",
      webType: "datetime",
      isNullable: true,
      isPrimaryKey: false,
      columnComment: "수정일시",
    },
  ];

  // 테이블명에 따라 추가 컬럼 포함
  if (tableName.toLowerCase().includes("user")) {
    baseColumns.push({
      columnName: "email",
      displayName: "이메일",
      dataType: "VARCHAR",
      webType: "email",
      isNullable: true,
      isPrimaryKey: false,
      columnComment: "이메일 주소",
    });
  }

  if (tableName.toLowerCase().includes("product")) {
    baseColumns.push({
      columnName: "price",
      displayName: "가격",
      dataType: "DECIMAL",
      webType: "decimal",
      isNullable: true,
      isPrimaryKey: false,
      columnComment: "상품 가격",
    });
  }

  return baseColumns;
};

/**
 * 특정 커넥션에서 데이터 조회
 */
export const queryDataFromConnection = async (
  connectionId: number,
  tableName: string,
  conditions?: Record<string, any>,
): Promise<Record<string, any>[]> => {
  const response = await apiClient.post(`/multi-connection/connections/${connectionId}/query`, {
    tableName,
    conditions,
  });
  return response.data.data || [];
};

/**
 * 특정 커넥션에 데이터 삽입
 */
export const insertDataToConnection = async (
  connectionId: number,
  tableName: string,
  data: Record<string, any>,
): Promise<any> => {
  const response = await apiClient.post(`/multi-connection/connections/${connectionId}/insert`, {
    tableName,
    data,
  });
  return response.data.data || {};
};

/**
 * 특정 커넥션의 데이터 업데이트
 */
export const updateDataInConnection = async (
  connectionId: number,
  tableName: string,
  data: Record<string, any>,
  conditions: Record<string, any>,
): Promise<any> => {
  const response = await apiClient.put(`/multi-connection/connections/${connectionId}/update`, {
    tableName,
    data,
    conditions,
  });
  return response.data.data || {};
};

/**
 * 특정 커넥션에서 데이터 삭제
 */
export const deleteDataFromConnection = async (
  connectionId: number,
  tableName: string,
  conditions: Record<string, any>,
  maxDeleteCount?: number,
): Promise<any> => {
  const response = await apiClient.delete(`/multi-connection/connections/${connectionId}/delete`, {
    data: {
      tableName,
      conditions,
      maxDeleteCount,
    },
  });
  return response.data.data || {};
};

/**
 * 자기 자신 테이블 작업 검증
 */
export const validateSelfTableOperation = async (
  tableName: string,
  operation: "update" | "delete",
  conditions: any[],
): Promise<ValidationResult> => {
  const response = await apiClient.post("/multi-connection/validate-self-operation", {
    tableName,
    operation,
    conditions,
  });
  return response.data.data || {};
};
