import { Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import axios from 'axios';
import { BaseSysParamEntity } from '../../base/entity/sys/param';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';

interface Ys7TokenData {
  accessToken: string;
  /** 萤石返回的毫秒级过期时间戳 */
  expireTime: number;
}

@Provide()
export class Ys7Service extends BaseService {
  @InjectEntityModel(BaseSysParamEntity)
  baseSysParamEntity: Repository<BaseSysParamEntity>;

  /** 内存并发锁 */
  private refreshing: Promise<Ys7TokenData> | null = null;

  /**
   * 对外暴露：拿 token（自动读缓存 / 续签）
   */
  async getAccessToken() {
    const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' });
    if (
      !token ||
      !token.updateTime ||
      Date.now() - new Date(token.updateTime).getTime() > 6 * 24 * 60 * 60 * 1000
    ) {
      await this.fetchAndSaveRemote();
    }
  }

  /** 真正调萤石 */
  private async fetchAndSaveRemote(): Promise<Ys7TokenData> {
    const appKey_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appKey' });
    const appSecret_result = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.appSecret' });

    if (!appKey_result || !appSecret_result) {
      throw new Error(
        '萤石云 appKey/appSecret 未配置，请在【系统参数】中维护 ys7.appKey / ys7.appSecret'
      );
    }

    const { data: res } = await axios.post(
      'https://open.ys7.com/api/lapp/token/get',
      new URLSearchParams({ appKey: appKey_result.data, appSecret: appSecret_result.data }),
      {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        timeout: 8000,
      }
    );

    if (String(res.code) !== '200') {
      throw new Error(`萤石云获取 Token 失败：${res.msg}（code: ${res.code}）`);
    }

    const tokenData: Ys7TokenData = {
      accessToken: res.data.accessToken,
      expireTime: res.data.expireTime,
    };

    // 写回系统参数表（Cool-Admin 自带 upsert）
    const token = await this.baseSysParamEntity.findOneBy({ keyName: 'ys7.accessToken' });
    this.baseSysParamEntity.save({
      ...token,
      data: tokenData.accessToken,
      updateTime: new Date(),
    }).catch(() => {
      // 忽略写回失败
    }); 
    return tokenData;
  }
}