import { Get, Query, Req, Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Merchant } from './merchant.entity';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
@Injectable()
export class MerchantService {
  constructor(
    @InjectRepository(Merchant)
    private merchantRepo: Repository<Merchant>,
  ) {}

  async getAll(page: number = 1, limit: number = 100): Promise<Merchant[]> {
    const offset = (page - 1) * limit;
    const fetchData = await this.merchantRepo.query(
      `SELECT m.*, mt.Description AS merchent_type_des 
     FROM merchant m 
     INNER JOIN merchant_type mt ON m.Merchant_type_idMerchant_type = mt.idMerchantType 
     LIMIT ? OFFSET ?`,
      [limit, offset],
    );

    return fetchData;
  }

  @Get()
  async getAllHttp(
    @Req() req: Request,
    @Query('page') page: string = '1',
    @Query('limit') limit: string = '100',
  ) {
    const protocol = req.protocol;
    const host = req.get('host') || '';
    const pageNum = parseInt(page, 10);
    const limitNum = parseInt(limit, 10);

    const baseUrl = `${protocol}://${host}/uploads/merchant/`;
    const baseUrl2 = `${protocol}://${host}/uploads/merchant/documents/`;

    const merchants = await this.merchantService.getAll(pageNum, limitNum);
    const allDocuments = await this.merchantDocumentsService.findAll();

    const merchantsWithDetails = await Promise.all(
      merchants.map(async (merchant) => {
        const logoUrl = merchant.Logo_Path
          ? baseUrl + merchant.Logo_Path
          : null;

        const merchantDocs = allDocuments
          .filter((doc) => doc.Merchant_idMerchant === merchant.idMerchant)
          .map((doc) => ({
            ...doc,
            Path_Link: baseUrl2 + doc.Path,
          }));

        const merchant_Has_categories =
          await this.merchantHasCategoriesService.getMerchantHasCategoriesByMerchantId(
            merchant.idMerchant,
          );

        return {
          ...merchant,
          Logo_Path_Link: logoUrl,
          Documents: merchantDocs,
          merchant_Has_categories,
        };
      }),
    );

    return merchantsWithDetails;
  }

  async getById(id: number): Promise<Merchant> {
    const merchant = await this.merchantRepo.query(
      `SELECT m.*,mt.Description AS merchent_type_des FROM merchant m INNER JOIN merchant_type mt ON m.Merchant_type_idMerchant_type = mt.idMerchantType WHERE m.idMerchant = ?`,
      [id],
    );
    if (!merchant) {
      throw new NotFoundException('merchant Not Found!');
    }
    return merchant[0];
  }

  async create(data: any, logo: Express.Multer.File): Promise<any> {
    const hashedPassword = await bcrypt.hash(data.Password, 10);

    const savedMerchant = this.merchantRepo.create({
      ...data,
      Password: hashedPassword,
      Logo_Path: logo?.filename || '',
    });

    await this.merchantRepo.save(savedMerchant);

    return savedMerchant;
  }

  // async update(id: number, data: any, logo: Express.Multer.File): Promise<any> {
  //   const merchant = await this.merchantRepo.findOneBy({ idMerchant: id });
  //   if (!merchant) {
  //     throw new NotFoundException('Merchant not found!');
  //   }

  //   if (data.Password) {
  //     data.Password = await bcrypt.hash(data.Password, 10);
  //   }

  //   const updatedMerchant = {
  //     ...merchant,
  //     ...data,
  //     Logo_Path: logo ? logo.filename : merchant.Logo_Path,
  //   };

  //   await this.merchantRepo.save(updatedMerchant);

  //   return {
  //     message: 'Merchant updated successfully!',
  //     merchant: updatedMerchant,
  //   };
  // }

  async update(
    id: number,
    data: any,
    logo?: Express.Multer.File,
  ): Promise<Merchant> {
    const merchant = await this.merchantRepo.findOne({
      where: { idMerchant: id },
    });
    if (!merchant) throw new Error('Merchant not found');
    delete data.idMerchant;
    // If password is provided, hash it
    if (data.Password) {
      data.Password = await bcrypt.hash(data.Password, 10);
    } else {
      delete data.Password; // avoid overwriting existing password with null
    }

    // Update fields
    Object.assign(merchant, data);

    // If new logo uploaded, update the path
    if (logo) {
      merchant.Logo_Path = logo.filename;
    }

    return await this.merchantRepo.save(merchant);
  }

  async findById(id: number): Promise<Merchant> {
    const merchant = await this.merchantRepo.findOne({
      where: { idMerchant: id },
    });
    if (!merchant) {
      throw new Error('Merchant not found');
    }
    return merchant;
  }
}
