import {
  DatabaseConnector,
  ConnectionConfig,
  QueryResult,
} from "../interfaces/DatabaseConnector";
import { ConnectionTestResult, TableInfo } from "../types/externalDbTypes";
// @ts-ignore
import * as mysql from "mysql2/promise";

export class MariaDBConnector implements DatabaseConnector {
  private connection: mysql.Connection | null = null;
  private config: ConnectionConfig;

  constructor(config: ConnectionConfig) {
    this.config = config;
  }

  async connect(): Promise<void> {
    if (!this.connection) {
      this.connection = await mysql.createConnection({
        host: this.config.host,
        port: this.config.port,
        user: this.config.user,
        password: this.config.password,
        database: this.config.database,
        connectTimeout: this.config.connectionTimeoutMillis,
        ssl: typeof this.config.ssl === "boolean" ? undefined : this.config.ssl,
      });
    }
  }

  async disconnect(): Promise<void> {
    if (this.connection) {
      await this.connection.end();
      this.connection = null;
    }
  }

  async testConnection(): Promise<ConnectionTestResult> {
    const startTime = Date.now();
    try {
      await this.connect();
      const [rows] = await this.connection!.query(
        "SELECT VERSION() as version"
      );
      const version = (rows as any[])[0]?.version || "Unknown";
      const responseTime = Date.now() - startTime;
      await this.disconnect();
      return {
        success: true,
        message: "MariaDB/MySQL 연결이 성공했습니다.",
        details: {
          response_time: responseTime,
          server_version: version,
        },
      };
    } catch (error: any) {
      await this.disconnect();
      return {
        success: false,
        message: "MariaDB/MySQL 연결에 실패했습니다.",
        error: {
          code: "CONNECTION_FAILED",
          details: error.message || "알 수 없는 오류",
        },
      };
    }
  }

  async executeQuery(query: string, params: any[] = []): Promise<QueryResult> {
    try {
      await this.connect();
      const [rows, fields] = await this.connection!.query(query, params);
      await this.disconnect();
      return {
        rows: rows as any[],
        rowCount: Array.isArray(rows) ? rows.length : 0,
        fields: fields as any[],
      };
    } catch (error: any) {
      await this.disconnect();
      throw new Error(`쿼리 실행 실패: ${error.message}`);
    }
  }

  async getTables(): Promise<TableInfo[]> {
    try {
      await this.connect();
      const [rows] = await this.connection!.query(`
        SELECT 
          TABLE_NAME as table_name,
          TABLE_COMMENT as description
        FROM information_schema.TABLES
        WHERE TABLE_SCHEMA = DATABASE()
        ORDER BY TABLE_NAME;
      `);

      // 테이블 목록만 반환 (컬럼 정보는 getColumns에서 개별 조회)
      const tables: TableInfo[] = (rows as any[]).map((row) => ({
        table_name: row.table_name,
        description: row.description || null,
        columns: [],
      }));

      await this.disconnect();
      return tables;
    } catch (error: any) {
      await this.disconnect();
      throw new Error(`테이블 목록 조회 실패: ${error.message}`);
    }
  }

  async getColumns(tableName: string): Promise<any[]> {
    try {
      console.log(`[MariaDBConnector] getColumns 호출: tableName=${tableName}`);
      await this.connect();
      console.log(`[MariaDBConnector] 연결 완료, 쿼리 실행 시작`);

      const [rows] = await this.connection!.query(
        `
        SELECT 
          c.COLUMN_NAME  AS column_name,
          c.DATA_TYPE    AS data_type,
          c.IS_NULLABLE  AS is_nullable,
          c.COLUMN_DEFAULT AS column_default,
          c.COLUMN_COMMENT AS description,
          CASE 
            WHEN tc.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 'YES' 
            ELSE 'NO' 
          END AS is_primary_key
        FROM information_schema.COLUMNS c
        LEFT JOIN information_schema.KEY_COLUMN_USAGE k
          ON  c.TABLE_SCHEMA = k.TABLE_SCHEMA
          AND c.TABLE_NAME  = k.TABLE_NAME
          AND c.COLUMN_NAME = k.COLUMN_NAME
        LEFT JOIN information_schema.TABLE_CONSTRAINTS tc
          ON  k.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
          AND k.CONSTRAINT_NAME  = tc.CONSTRAINT_NAME
          AND k.TABLE_SCHEMA     = tc.TABLE_SCHEMA
          AND k.TABLE_NAME       = tc.TABLE_NAME
          AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
        WHERE c.TABLE_SCHEMA = DATABASE() 
          AND c.TABLE_NAME  = ?
        ORDER BY c.ORDINAL_POSITION;
      `,
        [tableName]
      );

      console.log(`[MariaDBConnector] 쿼리 결과:`, rows);
      console.log(
        `[MariaDBConnector] 결과 개수:`,
        Array.isArray(rows) ? rows.length : "not array"
      );

      await this.disconnect();
      return rows as any[];
    } catch (error: any) {
      console.error(`[MariaDBConnector] getColumns 오류:`, error);
      await this.disconnect();
      throw new Error(`컬럼 정보 조회 실패: ${error.message}`);
    }
  }
}
