import { HttpService } from '@nestjs/axios';
import { Injectable, ServiceUnavailableException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AxiosError } from 'axios';
import { firstValueFrom } from 'rxjs';
import { VllmAuthService } from './vllm-auth.service';

export type ChatMessage = {
  role: 'system' | 'user' | 'assistant';
  content: string;
};

@Injectable()
export class VllmClientService {
  constructor(
    private readonly http: HttpService,
    private readonly config: ConfigService,
    private readonly auth: VllmAuthService,
  ) {}

  async chat(messages: ChatMessage[]) {
    const token = await this.auth.getAccessToken();

    try {
      return await this.requestChat(token, messages);
    } catch (error) {
      if (this.isUnauthorized(error)) {
        const refreshed = await this.auth.refreshToken();
        return this.requestChat(refreshed, messages);
      }
      throw error;
    }
  }

  private async requestChat(accessToken: string, messages: ChatMessage[]) {
    const response = await firstValueFrom(
      this.http.post(
        `${this.baseUrl}/api/external/llm/v1/chat/completions`,
        {
          model: this.config.get<string>('VLLM_MODEL', 'qwen2.5-32b-gptq-int4'),
          messages,
          temperature: 0.2,
        },
        {
          headers: { Authorization: `Bearer ${accessToken}` },
          timeout: Number(this.config.get<string>('VLLM_TIMEOUT_MS') ?? 20000),
        },
      ),
    );
    return response.data;
  }

  private isUnauthorized(error: unknown) {
    return error instanceof AxiosError && error.response?.status === 401;
  }

  private get baseUrl() {
    const value = this.config.get<string>('VLLM_BASE_URL')?.trim();
    if (!value) {
      throw new ServiceUnavailableException('VLLM_BASE_URL is not configured');
    }
    return value.replace(/\/$/, '');
  }
}
