import {
  BadRequestException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { paginate, PaginateQuery } from 'nestjs-paginate';
import axios from 'axios';
import * as crypto from 'crypto';
import { ConfigService as CSL } from '@nestjs/config';
import { Product } from 'src/entities/product.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
import AppResponse from 'src/system/response/app-response';
import { SystemLang } from 'src/system/lang/system.lang';
import { ProductListed } from 'src/entities/product-listed.entity';

@Injectable()
export class ProductsService {
  constructor(
    @InjectRepository(Product)
    public readonly repo: Repository<Product>,
    @InjectRepository(ProductListed)
    public readonly repoProductlisted: Repository<ProductListed>,
    private readonly csl: CSL,
    readonly configService: ConfigService,
  ) {}

  async index(query: PaginateQuery) {
    const qb = this.repo.createQueryBuilder('product');

    let info_hash: string | null = null;

    // Nếu có filter.info → hash nó lại (ở đây bạn truyền sẵn hash)
    if (query.filter?.info) {
      info_hash = (query.filter.info as string) || null;
    }

    // Nếu có info_hash → chỉ join những bản ghi có info_hash đó
    if (info_hash) {
      qb.leftJoinAndMapMany(
        'product.listedProducts',
        'product_listed',
        'listed',
        'listed.product_id = product.ebayListingId AND listed.info_hash = :info_hash',
        { info_hash },
      );
    } else {
      qb.leftJoinAndMapMany(
        'product.listedProducts',
        'product_listed',
        'listed',
        'listed.product_id = product.ebayListingId',
      );
    }

    // ----- Lọc theo status -----
    if (query.filter?.status === 'listed') {
      qb.where('listed.id IS NOT NULL');
    } else if (query.filter?.status === 'unlist') {
      if (info_hash) {
        qb.where(
          `product.ebayListingId NOT IN (
          SELECT pl.product_id FROM product_listed pl WHERE pl.info_hash = :info_hash
        )`,
          { info_hash },
        );
      } else {
        qb.where('listed.id IS NULL');
      }
    }

    const data = await paginate(query, qb, {
      sortableColumns: ['createdAt'],
      searchableColumns: ['id', 'code', 'name', 'title'],
      defaultLimit: 10,
      defaultSortBy: [['createdAt', 'DESC'] as any],
      maxLimit: 100,
    });

    return AppResponse.toPagination<Product>(data, true, Product);
  }

  async show(id: Product['ebayListingId']) {
    const product = await this.repo.findOne({ where: { ebayListingId: id } });

    if (!product) {
      throw new NotFoundException(
        AppResponse.toResponse(null, {
          message: SystemLang.getText('messages', 'not_found'),
        }),
      );
    }

    const a = await axios({
      method: 'POST',
      headers: { Authorization: `Bearer ${this.csl.get('VITE_API_TOKEN')}` },
      url: 'transferGetData',
      baseURL: this.csl.get('BASE_URL'),
      data: {
        filter: {
          where: {
            account: 'prology_net',
            condition: product.condition,
            productModelCode: product.code,
          },
        },
        pageCurrent: '/ebaytools/listing-ebay',
        urlAPI: '/api/ebay-listing/get-image-listing',
      },
    });

    return AppResponse.toResponse({ ...product, ...a.data?.data });
  }

  async publish(id: Product['ebayListingId'], data: any) {
    const info_hash = data?.hash_info || '';

    const prev = await this.repoProductlisted.findOne({
      where: { product: { ebayListingId: id }, info_hash: info_hash },
    });

    if (prev) {
      return AppResponse.toResponse(prev);
    }

    const result = await this.repoProductlisted.save({
      product: { ebayListingId: id },
      info: data?.info || {},
      info_hash: info_hash,
    });

    if (!result)
      throw new BadRequestException(
        AppResponse.toResponse(null, {
          message: SystemLang.getText('messages', 'error'),
        }),
      );

    return AppResponse.toResponse(result);
  }

  async unlist(id: Product['ebayListingId'], data: any) {
    const info_hash = data?.hash_info || '';

    const prev = await this.repoProductlisted.findOne({
      where: { product: { ebayListingId: id }, info_hash: info_hash },
    });

    if (!prev) {
      throw new NotFoundException(
        AppResponse.toResponse(false, {
          message: SystemLang.getText('messages', 'not_found'),
        }),
      );
    }

    await this.repoProductlisted.delete({ id: prev.id });

    return AppResponse.toResponse(true);
  }
}
