import { HttpService } from '@nestjs/axios';
import { Injectable, Logger } from '@nestjs/common';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class SupersetService {
  private readonly logger = new Logger(SupersetService.name);
  private supersetURL = process.env.SUPERSET_URL + '/api';
  private adminUsername = process.env.SUPERSET_ADMIN_USERNAME;
  private adminPassword = process.env.SUPERSET_ADMIN_PASSWORD;

  constructor(private readonly httpService: HttpService) {}

  async getLoginToken() {
    const data = {
      username: this.adminUsername,
      password: this.adminPassword,
      provider: 'db',
      refresh: true,
    };

    const response = await firstValueFrom(
      this.httpService.request({
        method: 'POST',
        url: `${this.supersetURL}/v1/security/login`,
        data: data,
      }),
    );

    return response.data.access_token;
  }

  async getCSRFToken() {
    const loginToken = await this.getLoginToken();
    const response = await firstValueFrom(
      this.httpService.request({
        method: 'GET',
        url: `${this.supersetURL}/v1/security/csrf_token/`,
        headers: { Authorization: `Bearer ${loginToken}` },
      }),
    );

    const cookie = response.headers['set-cookie'];

    return { loginToken, csrfToken: response.data.result, cookie };
  }

  async getGuestToken(uuid: string) {
    const { loginToken, csrfToken, cookie } = await this.getCSRFToken();

    const data = {
      resources: [{ type: 'dashboard', id: uuid }],
      rls: [],
      user: { username: 'pos_embed', first_name: 'pos', last_name: 'embed' },
    };

    const [requestCookie] = cookie[0].split(';');

    const headers = {
      Authorization: `Bearer ${loginToken}`,
      Cookie: requestCookie,
      'Content-Type': 'application/json',
      'X-CSRFToken': `${csrfToken}`,
      'Access-Control-Allow-Credentials': true,
    };

    const response = await firstValueFrom(
      this.httpService.request({
        method: 'POST',
        url: `${this.supersetURL}/v1/security/guest_token/`,
        data: data,
        headers: headers,
      }),
    ).catch((err) => {
      this.logger.verbose({ loginToken, csrfToken });
      this.logger.error(err.response.data);
      throw err;
    });

    return response.data.token;
  }
}
