import { GenericCrudService } from '@d8d/shared-crud';
import { DataSource, In } from 'typeorm';
import { SystemConfig } from '../entities/system-config.entity';
import { redisUtil } from '@d8d/shared-utils';

export class SystemConfigService extends GenericCrudService<SystemConfig> {
  constructor(dataSource: DataSource) {
    super(dataSource, SystemConfig, {
      userTracking: {
        createdByField: 'createdBy',
        updatedByField: 'updatedBy'
      }
    });
  }

  /**
   * 根据配置键获取配置值（带缓存）
   */
  async getConfigByKey(configKey: string): Promise<string | null> {
    // 1. 先尝试从缓存获取
    const cachedValue = await redisUtil.getSystemConfig(configKey);

    // 2. 如果缓存命中且不是空值缓存
    if (cachedValue !== null && !redisUtil.isNullValue(cachedValue)) {
      return cachedValue;
    }

    // 3. 如果是空值缓存，直接返回null
    if (cachedValue !== null && redisUtil.isNullValue(cachedValue)) {
      return null;
    }

    // 4. 缓存未命中，查询数据库
    const config = await this.repository.findOne({
      where: { configKey }
    });
    const configValue = config?.configValue || null;

    // 5. 将结果写入缓存
    if (configValue !== null) {
      // 正常值，缓存1小时
      await redisUtil.setSystemConfig(configKey, configValue, 3600);
    } else {
      // 空值，缓存5分钟防止缓存穿透
      await redisUtil.setNullSystemConfig(configKey, 300);
    }

    return configValue;
  }

  /**
   * 根据配置键获取配置值，如果不存在则返回默认值
   */
  async getConfigByKeyWithDefault(configKey: string, defaultValue: string): Promise<string> {
    const value = await this.getConfigByKey(configKey);
    return value || defaultValue;
  }

  /**
   * 批量获取配置（带缓存）
   */
  async getConfigsByKeys(configKeys: string[]): Promise<Record<string, string>> {
    // 1. 先尝试从缓存批量获取
    const cachedValues = await redisUtil.getSystemConfigs(configKeys);

    const result: Record<string, string> = {};
    const missingKeys: string[] = [];

    // 2. 处理缓存命中的键
    configKeys.forEach(key => {
      const cachedValue = cachedValues[key];
      if (cachedValue === undefined) {
        // 空值缓存，跳过
        return;
      }
      if (cachedValue === null) {
        // 缓存未命中，需要查询数据库
        missingKeys.push(key);
      } else if (!redisUtil.isNullValue(cachedValue)) {
        // 有效缓存值
        result[key] = cachedValue;
      }
      // 如果是空值缓存（redisUtil.isNullValue返回true），不添加到结果中
    });

    // 3. 如果有未命中的键，查询数据库
    if (missingKeys.length > 0) {
      const configs = await this.repository.find({
        where: {
          configKey: In(missingKeys)
        }
      });
      const dbValues: Record<string, string> = {};

      configs.forEach(config => {
        if (config.configValue !== null) {
          dbValues[config.configKey] = config.configValue;
        }
      });

      // 4. 处理数据库查询结果并更新缓存
      const cachePromises: Promise<void>[] = [];
      missingKeys.forEach(key => {
        const dbValue = dbValues[key];
        if (dbValue !== undefined) {
          // 数据库中有值，添加到结果并缓存
          result[key] = dbValue;
          cachePromises.push(redisUtil.setSystemConfig(key, dbValue, 3600));
        } else {
          // 数据库中无值，设置空值缓存
          cachePromises.push(redisUtil.setNullSystemConfig(key, 300));
        }
      });

      // 等待所有缓存操作完成
      if (cachePromises.length > 0) {
        await Promise.all(cachePromises);
      }
    }

    return result;
  }

  /**
   * 设置配置值，如果配置键不存在则创建，存在则更新
   */
  async setConfig(configKey: string, configValue: string, description?: string): Promise<SystemConfig> {
    const existingConfig = await this.repository.findOne({
      where: { configKey }
    });

    if (existingConfig) {
      // 更新现有配置
      const updatedConfig = await this.update(existingConfig.id, {
        configValue,
        description: description || existingConfig.description
      });

      // 清除相关缓存
      await redisUtil.deleteSystemConfig(configKey);

      return updatedConfig!;
    } else {
      // 创建新配置
      const newConfig = await this.create({
        configKey,
        configValue,
        description
      } as SystemConfig);

      // 清除相关缓存（如果之前有空值缓存）
      await redisUtil.deleteSystemConfig(configKey);

      return newConfig!;
    }
  }

  /**
   * 获取所有配置
   */
  async getAllConfigs(): Promise<SystemConfig[]> {
    return await this.repository.find();
  }

  /**
   * 删除配置
   */
  async deleteConfig(configKey: string): Promise<boolean> {
    const config = await this.repository.findOne({
      where: { configKey }
    });
    if (!config) {
      return false;
    }

    await this.delete(config.id);

    // 清除相关缓存
    await redisUtil.deleteSystemConfig(configKey);

    return true;
  }

  /**
   * 重写update方法，在更新时清除缓存
   */
  override async update(id: number, data: Partial<SystemConfig>): Promise<SystemConfig | null> {
    const updatedConfig = await super.update(id, data);

    if (updatedConfig) {
      // 清除相关缓存
      await redisUtil.deleteSystemConfig(updatedConfig.configKey);
    }

    return updatedConfig;
  }

  /**
   * 重写delete方法，在删除时清除缓存
   */
  override async delete(id: number): Promise<boolean> {
    // 先获取配置信息，以便后续清除缓存
    const config = await this.getById(id);

    const result = await super.delete(id);

    if (result && config) {
      // 清除相关缓存
      await redisUtil.deleteSystemConfig(config.configKey);
    }

    return result;
  }

  /**
   * 缓存预热 - 预加载常用配置到缓存
   */
  async warmUpCache(configKeys?: string[]): Promise<void> {
    // 如果没有指定配置键，预加载所有配置
    const keysToWarm = configKeys || ['app.login.enabled', 'app.payment.enabled', 'app.notification.enabled'];

    // 批量获取配置并缓存
    await this.getConfigsByKeys(keysToWarm);
  }
}