/**
 * 数据库工具 - 基于TypeORM
 * 提供基于表的ORM式操作
 */

import { BaseTool } from './ITool';
import { DataSource, EntityManager } from 'typeorm';
import 'reflect-metadata';

export interface DatabaseConfig {
  type?: 'mysql' | 'mariadb' | 'postgres' | 'sqlite';
  host?: string;
  port?: number;
  username?: string;
  password?: string;
  database?: string;
  // 可选：表定义
  tables?: {
    [tableName: string]: {
      columns: Record<string, string>;  // { columnName: type }
      primaryKey?: string;
    };
  };
}

export class DatabaseTool extends BaseTool<DatabaseConfig> {
  readonly name = 'database';
  
  private dataSource!: DataSource;
  private manager!: EntityManager;
  
  protected validateConfig(config: DatabaseConfig): void {
    if (!config.host) throw new Error('Database host is required');
    if (!config.database) throw new Error('Database name is required');
  }
  
  protected async doInitialize(): Promise<void> {
    const dbType = this.config.type || 'mysql';
    
    // 创建数据源（根据类型使用不同配置）
    this.dataSource = new DataSource({
      type: dbType as any,
      host: this.config.host,
      port: this.config.port || 3306,
      username: this.config.username || 'root',
      password: this.config.password || '',
      database: this.config.database,
      synchronize: false,
      logging: false,
      entities: [],
    } as any);
    
    // 初始化连接
    await this.dataSource.initialize();
    this.manager = this.dataSource.manager;
    
    console.log(`✓ Database connected: ${this.config.host}/${this.config.database}`);
    
    // 如果配置了表定义，自动创建表
    if (this.config.tables) {
      await this.createTablesIfNotExist();
    }
  }
  
  /**
   * 1. 检查表是否存在
   */
  async tableExists(tableName: string): Promise<boolean> {
    this.ensureInitialized();
    
    const result = await this.manager.query(
      `SELECT COUNT(*) as count FROM information_schema.tables 
       WHERE table_schema = ? AND table_name = ?`,
      [this.config.database, tableName]
    );
    
    return result[0].count > 0;
  }
  
  /**
   * 2. 检查数据是否存在
   */
  async exists(tableName: string, where: Record<string, any>): Promise<boolean> {
    this.ensureInitialized();
    
    const { whereClause, params } = this.buildWhereClause(where);
    const sql = `SELECT COUNT(*) as count FROM ${tableName} WHERE ${whereClause}`;
    
    const result = await this.manager.query(sql, params);
    return result[0].count > 0;
  }
  
  /**
   * 3. 插入数据
   */
  async insert(tableName: string, data: Record<string, any>): Promise<any> {
    this.ensureInitialized();
    
    const columns = Object.keys(data);
    const values = Object.values(data);
    const placeholders = columns.map(() => '?').join(', ');
    
    const sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
    const result = await this.manager.query(sql, values);
    
    return { insertId: result.insertId, affectedRows: result.affectedRows };
  }
  
  /**
   * 4. 更新数据
   */
  async update(
    tableName: string, 
    where: Record<string, any>, 
    data: Record<string, any>
  ): Promise<number> {
    this.ensureInitialized();
    
    const setClauses = Object.keys(data).map(key => `${key} = ?`).join(', ');
    const setValues = Object.values(data);
    
    const { whereClause, params: whereParams } = this.buildWhereClause(where);
    
    const sql = `UPDATE ${tableName} SET ${setClauses} WHERE ${whereClause}`;
    const result = await this.manager.query(sql, [...setValues, ...whereParams]);
    
    return result.affectedRows;
  }
  
  /**
   * 5. 删除数据
   */
  async delete(tableName: string, where: Record<string, any>): Promise<number> {
    this.ensureInitialized();
    
    const { whereClause, params } = this.buildWhereClause(where);
    const sql = `DELETE FROM ${tableName} WHERE ${whereClause}`;
    
    const result = await this.manager.query(sql, params);
    return result.affectedRows;
  }
  
  /**
   * 6. 查询数据
   */
  async find(tableName: string, where?: Record<string, any>): Promise<any[]> {
    this.ensureInitialized();
    
    let sql = `SELECT * FROM ${tableName}`;
    let params: any[] = [];
    
    if (where) {
      const { whereClause, params: whereParams } = this.buildWhereClause(where);
      sql += ` WHERE ${whereClause}`;
      params = whereParams;
    }
    
    return await this.manager.query(sql, params);
  }
  
  /**
   * 7. 查询单条数据
   */
  async findOne(tableName: string, where: Record<string, any>): Promise<any | null> {
    const results = await this.find(tableName, where);
    return results.length > 0 ? results[0] : null;
  }
  
  /**
   * 8. 执行原始SQL（高级用法）
   */
  async query(sql: string, params?: any[]): Promise<any> {
    this.ensureInitialized();
    return await this.manager.query(sql, params);
  }
  
  /**
   * 创建表（如果不存在）
   */
  async createTable(tableName: string, columns: Record<string, string>, primaryKey?: string): Promise<void> {
    this.ensureInitialized();
    
    const exists = await this.tableExists(tableName);
    if (exists) {
      console.log(`  ℹ️  Table ${tableName} already exists`);
      return;
    }
    
    const columnDefs = Object.entries(columns).map(([name, type]) => {
      let def = `${name} ${type}`;
      if (name === primaryKey) {
        def += ' PRIMARY KEY AUTO_INCREMENT';
      }
      return def;
    });
    
    const sql = `CREATE TABLE ${tableName} (${columnDefs.join(', ')})`;
    await this.manager.query(sql);
    
    console.log(`  ✓ Table ${tableName} created`);
  }
  
  /**
   * 根据配置创建所有表
   */
  private async createTablesIfNotExist(): Promise<void> {
    if (!this.config.tables) return;
    
    for (const [tableName, tableDef] of Object.entries(this.config.tables)) {
      await this.createTable(tableName, tableDef.columns, tableDef.primaryKey);
    }
  }
  
  /**
   * 构建WHERE子句
   */
  private buildWhereClause(where: Record<string, any>): { whereClause: string; params: any[] } {
    const conditions: string[] = [];
    const params: any[] = [];
    
    for (const [key, value] of Object.entries(where)) {
      conditions.push(`${key} = ?`);
      params.push(value);
    }
    
    return {
      whereClause: conditions.join(' AND '),
      params
    };
  }
  
  /**
   * 清理资源
   */
  async cleanup(): Promise<void> {
    if (this.dataSource?.isInitialized) {
      await this.dataSource.destroy();
      console.log('  ✓ database cleaned up');
    }
  }
}
