import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ErrorService } from 'src/error/error.service';
import { Repository } from 'typeorm';
import {
  applyFiltersToBuilder,
  applySortingToBuilder,
  paginationResult,
} from '../../utils';
import { UserService } from '../user/user.service';
import { UpdateWithdrawDto } from './dto/update-withdraw.dto';
import { WithdrawEntity, WithdrawStatus } from './entities/withdraw.entity';

@Injectable()
export class WithdrawService {
  constructor(
    @InjectRepository(WithdrawEntity)
    private withdrawRepository: Repository<WithdrawEntity>,

    private error: ErrorService,
    private userService: UserService,
  ) {}

  /**
   * -------------------------------------------------------
   * Get withdraw by id
   */
  async getById(withdrawId: number) {
    const builder = this.withdrawRepository.createQueryBuilder('withdraw');

    builder.leftJoin('withdraw.user', 'user');

    builder.select([
      'withdraw.id',
      'withdraw.userId',
      'withdraw.amount',
      'withdraw.status',
      'withdraw.bankName',
      'withdraw.accountNumber',
      'withdraw.cardNumber',
      'withdraw.sheba',
      'withdraw.reasonRejected',
      'withdraw.createdAt',

      'user.id',
      'user.name',
      'user.surName',
      'user.realWallet',
      'user.virtualWallet',
    ]);

    builder.where({ id: withdrawId });

    return await builder.getOne();
  }

  /**
   * -------------------------------------------------------
   * GET /withdraws
   */
  async withdrawList(page = 1, limit = 20, filters = null, sorts = null) {
    let builder = this.withdrawRepository.createQueryBuilder('withdraw');

    builder.leftJoin('withdraw.user', 'user');

    builder.select([
      'withdraw.id',
      'withdraw.userId',
      'withdraw.amount',
      'withdraw.status',
      'withdraw.reasonRejected',
      'withdraw.createdAt',

      'user.id',
      'user.name',
      'user.surName',
      'user.realWallet',
      'user.virtualWallet',
    ]);

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

    const [items, totalItems] = await builder
      .take(limit)
      .skip((page - 1) * limit)
      .getManyAndCount();

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

  /**
   * -------------------------------------------------------
   * PUT /withdraws/1
   */
  async updateWithdraw(withdrawId: number, dto: UpdateWithdrawDto) {
    const withdraw = await this.withdrawRepository.findOne(withdrawId);

    if (withdraw?.status !== WithdrawStatus.pending) {
      this.error.unprocessableEntity([
        'این درخواست وجه قبلا تعیین وضعیت شده است!',
      ]);
    }

    if (dto.status === WithdrawStatus.rejected) {
      await this.userService.updateWallet(withdraw.userId, withdraw.amount);
    }

    return await this.withdrawRepository
      .createQueryBuilder()
      .update()
      .set(dto)
      .where({ id: withdrawId })
      .execute();
  }
}
