import {
  BadRequestException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { CreateTipDto } from './dto/create-tip.dto';
import { UpdateTipDto } from './dto/update-tip.dto';
import { Repository } from 'typeorm';
import { TipsRepository } from './tips.repository';
import { InjectRepository } from '@nestjs/typeorm';
import { Tip } from './entities/tip.entity';
import { CategoryRepository } from 'src/categories/categories.repository';
import { isEmpty } from 'src/common/helper';
import { lan } from 'src/lan';
import { Category } from 'src/categories/entities/category.entity';
import isValidUuidV4 from 'src/common/uuid validator/uuid-validate';
import { CreateTipsImageDto } from './dto/create-tip-image.dto';
import { TipsMedias } from './entities/tip_media.entity';

@Injectable()
export class TipsService {
  constructor(
    @InjectRepository(Tip)
    private readonly tipsEntity: Repository<Tip>,
    private readonly tipsRepository: TipsRepository,
    private readonly categoryRepository: CategoryRepository,
    @InjectRepository(TipsMedias)
    private readonly tipsMediaEntity: Repository<TipsMedias>,
  ) {}
  async create(
    createTipDto: CreateTipDto,
    createTipsImageDto: CreateTipsImageDto,
  ) {
    if (!isEmpty(createTipDto.category_id)) {
      const categories = await this.categoryRepository.findById(
        createTipDto.category_id,
      );

      if (isEmpty(categories)) {
        throw new NotFoundException(lan('common.data_not_found'));
      }
    }

    const categories: any = new Category();
    Object.assign(categories, createTipDto);

    const data = await this.tipsEntity.save(createTipDto);

    const tipsImages: TipsMedias[] = [];

    for (const attachment of createTipsImageDto.media) {
      const tipsImage: TipsMedias = new TipsMedias();
      tipsImage.media = attachment.path;
      tipsImage.tips_id = data.id;
      tipsImage.media_type = attachment.mimetype[0];

      const savedImage = await this.tipsMediaEntity.save(tipsImage);

      tipsImages.push(savedImage);
    }

    return tipsImages;
  }

  async findAll(take: number, skip: number, categoryId: string, headers: any) {
    return await this.tipsRepository.findAll(take, skip, categoryId, headers);
  }

  async findOne(id: string) {
    if (!isValidUuidV4(id)) {
      throw new BadRequestException(lan('common.invalid_uuid_format'));
    }

    const tips = await this.tipsRepository.findOne(id);

    if (isEmpty(tips)) {
      throw new NotFoundException(lan('common.data_not_found'));
    }

    return tips;
  }

  async update(
    id: string,
    updateTipDto: UpdateTipDto,
    updateTipsImageDto: CreateTipsImageDto,
  ): Promise<TipsMedias[]> {
    if (!isValidUuidV4(id)) {
      throw new BadRequestException(lan('common.invalid_uuid_format'));
    }

    const tip = await this.tipsRepository.findOneById(id);

    if (isEmpty(tip)) {
      throw new NotFoundException(lan('common.data_not_found'));
    }

    Object.assign(tip, updateTipDto);

    const data: any = await this.tipsEntity.update(id, updateTipDto);

    const tipsImages: TipsMedias[] = [];

    if (!isEmpty(updateTipsImageDto.media)) {
      for (const attachment of updateTipsImageDto.media) {
        let tipsImage = tip.tips_medias.find(
          (img) => img.media === attachment.path,
        );

        if (!tipsImage) {
          tipsImage = new TipsMedias();
          tipsImage.media = attachment.path;
          tipsImage.tips_id = id;
          tipsImage.media_type = attachment.mimetype[0];
        }

        const savedImage = await this.tipsMediaEntity.save(tipsImage);
        tipsImages.push(savedImage);
      }
    }

    return data;
  }

  async remove(id: string) {
    if (!isValidUuidV4(id)) {
      throw new BadRequestException(lan('common.invalid_uuid_format'));
    }
    const tip = await this.tipsRepository.findOne(id);

    if (isEmpty(tip)) {
      throw new NotFoundException(lan('common.data_not_found'));
    }

    return this.tipsEntity.softDelete(id);
  }

  async deleteImage(tipsId: string, imageId: string): Promise<void> {
    const tips = await this.tipsRepository.findOne(tipsId);

    if (isEmpty(tips)) {
      throw new NotFoundException(lan('common.data_not_found'));
    }

    const image = tips.tips_medias.find((img) => img.id === imageId);

    if (isEmpty(image)) {
      throw new NotFoundException(lan('common.data_not_found'));
    }

    await this.tipsMediaEntity.softDelete(imageId);
  }
}
