import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom, timeout, catchError } from 'rxjs';
import { of } from 'rxjs';

// authorization-service 返回格式（经过 TransformInterceptor 包装）
export interface AuthorizationServiceResponse<T> {
  success: boolean;
  data: T;
  timestamp: string;
}

export interface NearestAuthorizationResult {
  accountSequence: string | null;  // 格式: D + YYMMDD + 5位序号
}

/**
 * Authorization Service 客户端
 * 用于查询用户推荐链中最近的省/市/社区授权用户
 */
@Injectable()
export class AuthorizationServiceClient {
  private readonly logger = new Logger(AuthorizationServiceClient.name);
  private readonly baseUrl: string;
  private readonly timeoutMs: number;

  constructor(
    private readonly configService: ConfigService,
    private readonly httpService: HttpService,
  ) {
    this.baseUrl =
      this.configService.get<string>('AUTHORIZATION_SERVICE_URL') ||
      'http://localhost:3009';
    this.timeoutMs = this.configService.get<number>('AUTHORIZATION_SERVICE_TIMEOUT_MS') || 5000;
  }

  /**
   * 查找用户推荐链中最近的社区授权用户
   * @param accountSequence 用户的 accountSequence (格式: D + YYMMDD + 5位序号)
   * @returns 最近社区授权用户的 accountSequence，如果没有则返回 null
   */
  async findNearestCommunity(accountSequence: string): Promise<string | null> {
    try {
      const response = await firstValueFrom(
        this.httpService
          .get<AuthorizationServiceResponse<NearestAuthorizationResult>>(
            `${this.baseUrl}/api/v1/authorization/nearest-community`,
            {
              params: { accountSequence },
            },
          )
          .pipe(
            timeout(this.timeoutMs),
            catchError((error) => {
              this.logger.warn(
                `Failed to find nearest community for accountSequence=${accountSequence}: ${error.message}`,
              );
              return of({ data: { success: false, data: { accountSequence: null }, timestamp: '' } });
            }),
          ),
      );

      // authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
      return response.data.data?.accountSequence ?? null;
    } catch (error) {
      this.logger.error(
        `Error finding nearest community for accountSequence=${accountSequence}`,
        error,
      );
      return null;
    }
  }

  /**
   * 查找用户推荐链中最近的省公司授权用户（匹配指定省份）
   * @param accountSequence 用户的 accountSequence (格式: D + YYMMDD + 5位序号)
   * @param provinceCode 省份代码
   * @returns 最近省公司授权用户的 accountSequence，如果没有则返回 null
   */
  async findNearestProvince(
    accountSequence: string,
    provinceCode: string,
  ): Promise<string | null> {
    try {
      const response = await firstValueFrom(
        this.httpService
          .get<AuthorizationServiceResponse<NearestAuthorizationResult>>(
            `${this.baseUrl}/api/v1/authorization/nearest-province`,
            {
              params: { accountSequence, provinceCode },
            },
          )
          .pipe(
            timeout(this.timeoutMs),
            catchError((error) => {
              this.logger.warn(
                `Failed to find nearest province for accountSequence=${accountSequence}, provinceCode=${provinceCode}: ${error.message}`,
              );
              return of({ data: { success: false, data: { accountSequence: null }, timestamp: '' } });
            }),
          ),
      );

      // authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
      return response.data.data?.accountSequence ?? null;
    } catch (error) {
      this.logger.error(
        `Error finding nearest province for accountSequence=${accountSequence}, provinceCode=${provinceCode}`,
        error,
      );
      return null;
    }
  }

  /**
   * 查找用户推荐链中最近的市公司授权用户（匹配指定城市）
   * @param accountSequence 用户的 accountSequence (格式: D + YYMMDD + 5位序号)
   * @param cityCode 城市代码
   * @returns 最近市公司授权用户的 accountSequence，如果没有则返回 null
   */
  async findNearestCity(
    accountSequence: string,
    cityCode: string,
  ): Promise<string | null> {
    try {
      const response = await firstValueFrom(
        this.httpService
          .get<AuthorizationServiceResponse<NearestAuthorizationResult>>(
            `${this.baseUrl}/api/v1/authorization/nearest-city`,
            {
              params: { accountSequence, cityCode },
            },
          )
          .pipe(
            timeout(this.timeoutMs),
            catchError((error) => {
              this.logger.warn(
                `Failed to find nearest city for accountSequence=${accountSequence}, cityCode=${cityCode}: ${error.message}`,
              );
              return of({ data: { success: false, data: { accountSequence: null }, timestamp: '' } });
            }),
          ),
      );

      // authorization-service 返回格式: { success, data: { accountSequence }, timestamp }
      return response.data.data?.accountSequence ?? null;
    } catch (error) {
      this.logger.error(
        `Error finding nearest city for accountSequence=${accountSequence}, cityCode=${cityCode}`,
        error,
      );
      return null;
    }
  }

  /**
   * 并行查询所有授权信息
   * 优化性能：同时发起三个请求
   */
  async findAllNearestAuthorizations(
    accountSequence: string,  // 格式: D + YYMMDD + 5位序号
    provinceCode: string,
    cityCode: string,
  ): Promise<{
    nearestCommunity: string | null;
    nearestProvinceAuth: string | null;
    nearestCityAuth: string | null;
  }> {
    const [nearestCommunity, nearestProvinceAuth, nearestCityAuth] =
      await Promise.all([
        this.findNearestCommunity(accountSequence),
        this.findNearestProvince(accountSequence, provinceCode),
        this.findNearestCity(accountSequence, cityCode),
      ]);

    this.logger.debug(
      `Authorization lookup for accountSequence=${accountSequence}: ` +
        `community=${nearestCommunity}, province=${nearestProvinceAuth}, city=${nearestCityAuth}`,
    );

    return {
      nearestCommunity,
      nearestProvinceAuth,
      nearestCityAuth,
    };
  }
}
