import { Injectable, BadRequestException, InternalServerErrorException } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { firstValueFrom, lastValueFrom } from 'rxjs';
import FormData from 'form-data';

@Injectable()
export class AiScannerService {
  private readonly fastApiUrl: string;
  private readonly authToken: string;

  constructor(
    private readonly httpService: HttpService,
    private readonly configService: ConfigService,
  ) {
    this.fastApiUrl = this.configService.get<string>('FASTAPI_URL');
    this.authToken = this.configService.get<string>('FASTAPI_TOKEN');
  }

  async analyzeText(text: string) {
    try {
      const response = await firstValueFrom(
        this.httpService.post(
          `${this.fastApiUrl}/text/analyse`,
          { text },
          {
            headers: {
              Authorization: `Bearer ${this.authToken}`,
              'Content-Type': 'application/json',
            },
          },
        ),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze text');
    }
  }

  async analyzeSentences(text: string) {
    try {
      const response = await firstValueFrom(
        this.httpService.post(
          `${this.fastApiUrl}/text/analyse-sentences`,
          { text },
          {
            headers: {
              Authorization: `Bearer ${this.authToken}`,
              'Content-Type': 'application/json',
            },
          },
        ),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze sentences');
    }
  }
  // file handling we use multer
  async analyzeFile(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/text/upload`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }

  async analyzeFileSentences(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/text/analyse-sentance-file`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file sentences');
    }
  }

  // Nepali languasge analyse
  async nepalianalyze(text: string) {
    try {
      const response = await firstValueFrom(
        this.httpService.post(
          `${this.fastApiUrl}/NP/analyse`,
          { text },
          {
            headers: {
              Authorization: `Bearer ${this.authToken}`,
              'Content-Type': 'application/json',
            },
          },
        ),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze sentences');
    }
  }
  async nepalianalyzeSentences(text: string) {
    try {
      const response = await firstValueFrom(
        this.httpService.post(
          `${this.fastApiUrl}/NP/analyse-sentences`,
          { text },
          {
            headers: {
              Authorization: `Bearer ${this.authToken}`,
              'Content-Type': 'application/json',
            },
          },
        ),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze sentences');
    }
  }
  async nepalianalyzeFile(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/NP/upload`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }
  async nepalianalyzeFileSentences(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/NP/file-sentences-analyse`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      return response.data;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file sentences');
    }
  }

  async aiimageanalyze(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/AI-image/analyse`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      const result = response.data;

      if (result.label === 'Human Generated') {
        result.label = 'Human';
      } else if (result.label === 'AI Generated') {
        result.label = 'AI';
      }

      return result;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }
  // detector system
  async elaimagedetectorsystem(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/detect/ela`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      const result = response.data;
      return result;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }
  async fftimagedetectorsystem(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/detect/fft`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      const result = response.data;
      return result;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }

  async metaimagedetectorsystem(file: Express.Multer.File) {
    try {
      const formData = new FormData();
      formData.append('file', file.buffer, {
        filename: file.originalname,
        contentType: file.mimetype,
      });

      const response = await firstValueFrom(
        this.httpService.post(`${this.fastApiUrl}/detect/meta`, formData, {
          headers: {
            Authorization: `Bearer ${this.authToken}`,
            ...formData.getHeaders(),
          },
        }),
      );
      const result = response.data;
      return result;
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }

  async imageforensicssystem(file: Express.Multer.File) {
    try {
      const urls = [`${this.fastApiUrl}/detect/fft`, `${this.fastApiUrl}/detect/ela`, `${this.fastApiUrl}/detect/meta`];

      const requests = urls.map(url => {
        const formData = new FormData();
        formData.append('file', file.buffer, {
          filename: file.originalname,
          contentType: file.mimetype,
        });

        const headers = {
          Authorization: `Bearer ${this.authToken}`,
          ...formData.getHeaders(),
        };

        return lastValueFrom(this.httpService.post(url, formData, { headers }));
      });

      const [fftRes, elaRes, metaRes] = await Promise.all(requests);
      console.log([fftRes.data, elaRes.data, metaRes.data]);

      const decision = this._determineDecision(elaRes.data, fftRes.data, metaRes.data);
      return { decision: decision, fft: fftRes.data, ela: elaRes.data, metaRes: metaRes.data };
    } catch (error) {
      this.handleError(error, 'Failed to analyze file');
    }
  }

  private _determineDecision(
    elaData: { is_edited: boolean },
    fftData: { edited: boolean },
    metaData: { source: 'ai_generated' | 'edited' | 'undetermined' },
  ): string {
    const ela = elaData?.is_edited ?? false;
    const fft = fftData?.edited ?? false;
    const meta = metaData?.source ?? 'undetermined';

    if (ela && fft && meta === 'ai_generated') return 'ai_generated';
    if (ela && !fft && meta === 'edited') return 'edited';
    if (ela && !fft && meta === 'undetermined') return 'edited';
    if (!ela && fft && meta === 'ai_generated') return 'ai_generated';
    if (!ela && fft && meta === 'undetermined') return 'possibly_ai_generated';
    if (!ela && !fft && meta === 'ai_generated') return 'ai_generated';
    if (!ela && !fft && meta === 'edited') return 'possibly_edited';
    if (!ela && !fft && meta === 'undetermined') return 'authentic';

    return 'undetermined';
  }

  private handleError(error: any, defaultMessage: string) {
    console.error('FastAPI Error:', error.response?.data || error.message);

    if (error.response?.status === 400) {
      throw new BadRequestException(error.response.data?.detail || 'Invalid request data');
    }
  }
}
