import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ErrorService } from 'src/error/error.service';
import { getLastDisplayOrder } from 'src/utils/last-display-order';
import { Repository } from 'typeorm';
import {
  applyFiltersToBuilder,
  applySortingToBuilder,
  paginationResult,
} from '../../utils';
import { ProductService } from '../product/product.service';
import { CreateAttributeOptionDto } from './dto/create-attribute-option.dto';
import { CreateAttributeDto } from './dto/create-attribute.dto';
import { UpdateAttributeDto } from './dto/update-attribute.dto';
import { AttributeOptionEntity } from './entities/attribute-option.entity';
import { AttributeEntity } from './entities/attribute.entity';

@Injectable()
export class AttributeService {
  constructor(
    @InjectRepository(AttributeEntity)
    private attributeRepository: Repository<AttributeEntity>,

    @InjectRepository(AttributeOptionEntity)
    private attributeOptionRepository: Repository<AttributeOptionEntity>,

    private error: ErrorService,
    private productService: ProductService,
  ) {}

  /**
   * -------------------------------------------------------
   */
  async getAll(page = 1, limit = 20, filters = null, sorts = null) {
    let builder = this.attributeRepository
      .createQueryBuilder('attribute')
      .leftJoinAndSelect('attribute.attributeOptions', 'attributeOptions')
      .leftJoin(
        'attributeOptions.productAttributeOptionMappings',
        'productAttributeOptionMappings',
      );

    builder.take(limit);
    builder.skip((page - 1) * limit);

    if (sorts) {
      builder = applySortingToBuilder(builder, sorts);
    } else {
      builder.orderBy(`${builder.alias}.displayOrder`, 'DESC');
    }

    builder = applyFiltersToBuilder(builder, filters);

    const [items, totalItems] = await builder.getManyAndCount();

    return {
      items: items,
      pagination: paginationResult(page, limit, totalItems),
    };
  }

  /**
   * -------------------------------------------------------
   */
  async addAttribute(dto: CreateAttributeDto) {
    const newAttribute = new AttributeEntity();

    newAttribute.name = dto.name;
    newAttribute.displayOrder = await getLastDisplayOrder(AttributeEntity.name);
    newAttribute.createdAt = new Date();
    newAttribute.updatedAt = new Date();

    const { identifiers } = await this.attributeRepository
      .createQueryBuilder()
      .insert()
      .values(newAttribute)
      .execute();

    const newAttributeId = identifiers[0].id;
    return await this.attributeRepository.findOne(newAttributeId);
  }

  /**
   * -------------------------------------------------------
   */
  async addAttributeOption(dto: CreateAttributeOptionDto) {
    const newOption = new AttributeOptionEntity();

    newOption.specificationAttributeId = dto.attributeId;
    newOption.name = dto.name;
    newOption.displayOrder = await getLastDisplayOrder(
      AttributeOptionEntity.name,
    );

    newOption.createdAt = new Date();
    newOption.updatedAt = new Date();

    const { identifiers } = await this.attributeOptionRepository
      .createQueryBuilder()
      .insert()
      .values(newOption)
      .execute();

    const newOptionId = identifiers[0].id;
    return await this.attributeOptionRepository.findOne(newOptionId);
  }

  /**
   * -------------------------------------------------------
   */
  async getById(id: number) {
    return await this.attributeRepository
      .createQueryBuilder('attribute')
      .leftJoinAndSelect('attribute.attributeOptions', 'attributeOptions')
      .andWhere({ id })
      .getOne();
  }

  /**
   * -------------------------------------------------------
   */
  async updateAttribute(id: number, dto: UpdateAttributeDto) {
    return await this.attributeRepository
      .createQueryBuilder()
      .update()
      .set({ ...dto, updatedAt: new Date() })
      .where({ id })
      .execute();
  }

  /**
   * -------------------------------------------------------
   */
  async deleteAttribute(id: number) {
    return await this.attributeRepository
      .createQueryBuilder()
      .update()
      .set({ deleted: true, updatedAt: new Date() })
      .where({ id })
      .execute();
  }

  // /**
  //  * -------------------------------------------------------
  //  */
  // async deleteAttribute(id: number) {
  //   // const productMappingCount =
  //   //   await this.productService.getCountAttributeMapping(id);

  //   // if (productMappingCount > 0) {
  //   //   this.error.internalServerError([
  //   //     'امکان حذف این ویژگی، به دلیل ارتباط با حداقل یک محصول، وجود ندارد',
  //   //   ]);
  //   // }

  //   try {
  //     await this.attributeOptionRepository.delete({
  //       specificationAttributeId: id,
  //     });

  //     return await this.attributeRepository.delete(id);
  //   } catch (e) {
  //     this.error.internalServerError([
  //       'امکان حذف این ویژگی، به دلیل ارتباط با حداقل یک محصول، وجود ندارد',
  //     ]);
  //   }
  // }

  /**
   * -------------------------------------------------------
   */
  async deleteOption(id: number) {
    return await this.attributeOptionRepository.delete(id);
  }
}
