import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Workbook } from 'exceljs';
import { Repository } from 'typeorm';
import { ErrorService } from '../../error/error.service';
import {
  applyFiltersToBuilder,
  applySortingToBuilder,
  paginationResult,
} from '../../utils';
import { CreateBonusCreditsDto } from './dto/create-bonus-credits.dto';
import { BonusCreditsEntity } from './entities/bonus-credit.entity';
import * as moment from 'jalali-moment';
import * as tmp from 'tmp';

@Injectable()
export class BonusCreditsService {
  constructor(
    @InjectRepository(BonusCreditsEntity)
    private bonusCreditsRepository: Repository<BonusCreditsEntity>,
    private error: ErrorService,
  ) {}

  /**
   * -------------------------------------------------------
   */
  async create(dto: CreateBonusCreditsDto) {
    const values = [];

    for (let i = 1; i <= dto.count; i++) {
      values.push({
        code: this._generateUniqueCode(),
        title: dto.title,
        userId: null,
        amount: dto.amount,
        used: false,
        usedAt: null,
        createdAt: new Date(),
        updatedAt: new Date(),
      });
    }

    await this.bonusCreditsRepository
      .createQueryBuilder()
      .insert()
      .values(values)
      .execute();

    return true;
  }

  /**
   * -------------------------------------------------------
   */
  private _generateUniqueCode(length = 8) {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

    let code = '';
    for (let i = 0; i < length; i++) {
      code += characters.charAt(Math.floor(Math.random() * characters.length));
    }

    return code;
  }

  /**
   * -------------------------------------------------------
   */
  async exportExcel(filters = null) {
    let builder = this.bonusCreditsRepository
      .createQueryBuilder('bonusCredits')
      .select([
        'bonusCredits.id',
        'bonusCredits.title',
        'bonusCredits.code',
        'bonusCredits.amount',
        'bonusCredits.used',
        'bonusCredits.createdAt',
      ]);
    builder.orderBy('bonusCredits.createdAt', 'DESC');
    builder = applyFiltersToBuilder(builder, filters);
    const items = await builder.getMany();

    // Create excel file
    const workbook = new Workbook();
    const worksheet = workbook.addWorksheet(`sheet1`);
    worksheet.views = [{ rightToLeft: true }];

    worksheet.addRow(['عنوان', 'کد هدیه', 'مبلغ هدیه', 'استفاده شده']);

    items.forEach((item) => {
      worksheet.addRow([
        item.title,
        item.code,
        item.amount,
        item.used ? 'بله' : 'خیر',
      ]);
    });

    worksheet.getRow(1).fill = {
      type: 'pattern',
      pattern: 'solid',
      fgColor: { argb: 'FFBFBFBF' },
    };

    worksheet.getColumn(1).width = 15;
    worksheet.getColumn(2).width = 20;
    worksheet.getColumn(3).width = 12;
    worksheet.getColumn(4).width = 12;

    // Save on tmp and export excel file
    try {
      const tmpobj = tmp.fileSync({
        mode: 0o644,
        prefix: `bonus_credits_${moment().format('YYYY-MM-DD')}`,
        postfix: '.xlsx',
        discardDescriptor: true,
      });
      await workbook.xlsx.writeFile(tmpobj.name);
      return tmpobj.name;
    } catch (err) {
      console.log(err);
      this.error.internalServerError(['در تولید فایل اکسل خطایی رخ داده است']);
    }
  }

  /**
   * -------------------------------------------------------
   */
  async getAll(page = 1, limit = 20, filters = null, sorts = null) {
    let builder = this.bonusCreditsRepository
      .createQueryBuilder('bonusCredits')
      .leftJoin('bonusCredits.user', 'user')
      .select([
        'bonusCredits.id',
        'bonusCredits.title',
        'bonusCredits.userId',
        'bonusCredits.code',
        'bonusCredits.amount',
        'bonusCredits.used',
        'bonusCredits.usedAt',
        'bonusCredits.createdAt',

        'user.id',
        'user.name',
        'user.surName',
        'user.mobile',
      ])
      .take(limit)
      .skip((page - 1) * limit);

    if (sorts) {
      builder = applySortingToBuilder(builder, sorts);
    } else {
      builder.orderBy('bonusCredits.createdAt', 'DESC');
    }

    builder = applyFiltersToBuilder(builder, filters);

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

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

  /**
   * -------------------------------------------------------
   * DELETE /bonus-credits/1
   */
  async deleteBonusCredits(id: number) {
    // find by id
    const bonus = await this.bonusCreditsRepository.findOne(id);

    if (bonus?.used) {
      this.error.methodNotAllowed([
        'امکان حذف کد اعتبار هدیه استفاده شده، وجود ندارد!',
      ]);
    }

    await bonus?.remove();

    return true;
  }
}
