import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '@core/database/prisma/prisma.service';
import axios from 'axios';

const GLOBAL_CONFIG_KEY = 'GLOBAL';

@Injectable()
export class DingtalkAuthService {
  private readonly logger = new Logger(DingtalkAuthService.name);
  private accessToken = '';
  private tokenExpireAt = 0;
  private cachedEnabled: boolean | null = null;
  private cacheExpireAt = 0;

  constructor(
    private configService: ConfigService,
    private prisma: PrismaService,
  ) {}

  get appKey(): string {
    return this.configService.get<string>('DINGTALK_APP_KEY', '');
  }

  get appSecret(): string {
    return this.configService.get<string>('DINGTALK_APP_SECRET', '');
  }

  get agentId(): string {
    return this.configService.get<string>('DINGTALK_AGENT_ID', '');
  }

  get systemToken(): string {
    return this.configService.get<string>('DINGTALK_YIDA_SYSTEM_TOKEN', '');
  }

  get appType(): string {
    return this.configService.get<string>('DINGTALK_YIDA_APP_TYPE', '');
  }

  get operatorId(): string {
    return this.configService.get<string>('DINGTALK_YIDA_OPERATOR_ID', '');
  }

  /** 同步读取：优先用缓存，fallback 到环境变量 */
  get isEnabled(): boolean {
    if (this.cachedEnabled !== null && Date.now() < this.cacheExpireAt) {
      return this.cachedEnabled;
    }
    return this.configService.get<string>('DINGTALK_SYNC_ENABLED', 'false') === 'true';
  }

  /** 异步读取：从数据库获取最新值 */
  async getIsEnabled(): Promise<boolean> {
    try {
      const config = await this.prisma.dingtalkSyncConfig.findUnique({
        where: { taskCode: GLOBAL_CONFIG_KEY },
      });
      if (config) {
        const enabled = (config.metadata as any)?.enabled === true;
        this.cachedEnabled = enabled;
        this.cacheExpireAt = Date.now() + 60_000; // 缓存1分钟
        return enabled;
      }
    } catch (error) {
      this.logger.warn('读取数据库开关失败，使用环境变量', error);
    }
    return this.configService.get<string>('DINGTALK_SYNC_ENABLED', 'false') === 'true';
  }

  /** 更新启用状态到数据库 */
  async setEnabled(enabled: boolean): Promise<void> {
    await this.prisma.dingtalkSyncConfig.upsert({
      where: { taskCode: GLOBAL_CONFIG_KEY },
      create: {
        taskCode: GLOBAL_CONFIG_KEY,
        syncDirection: 'NONE',
        metadata: { enabled },
      },
      update: {
        metadata: { enabled },
      },
    });
    this.cachedEnabled = enabled;
    this.cacheExpireAt = Date.now() + 60_000;
    this.logger.log(`钉钉同步已${enabled ? '启用' : '禁用'}`);
  }

  async getAccessToken(): Promise<string> {
    const now = Date.now();
    if (this.accessToken && now < this.tokenExpireAt) {
      return this.accessToken;
    }

    try {
      this.logger.log(`[API→] GET /gettoken appkey=${this.appKey.slice(0, 6)}***`);
      const resp = await axios.get('https://oapi.dingtalk.com/gettoken', {
        params: { appkey: this.appKey, appsecret: this.appSecret },
      });
      this.logger.log(`[API←] gettoken errcode=${resp.data.errcode} expires_in=${resp.data.expires_in}`);

      if (resp.data.errcode !== 0) {
        throw new Error(`获取Token失败: ${resp.data.errmsg}`);
      }

      this.accessToken = resp.data.access_token;
      this.tokenExpireAt = now + 6900 * 1000;
      this.logger.log('钉钉AccessToken刷新成功');
      return this.accessToken;
    } catch (error: any) {
      this.logger.error(`获取钉钉AccessToken失败: ${error.message} response=${JSON.stringify(error.response?.data || {}).slice(0, 500)}`);
      throw error;
    }
  }

  async getNewApiHeaders(): Promise<Record<string, string>> {
    const token = await this.getAccessToken();
    return { 'x-acs-dingtalk-access-token': token };
  }
}
