import { Injectable,HttpException,HttpStatus, Res, Inject } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Not, ILike  } from 'typeorm';
import { classToPlain } from 'class-transformer';
import { responseMessages } from '../../messages/response-messages';
import { FaqsRepository } from './repositories/faqs.repository';

// Entities Files
import { Constants } from 'src/common/constants';
import { Faqs } from '../../entities/faqs.entity';
import { Users, UserRoles } from '../../entities/users.entity';

// DTO Files
import { FaqsCreateDto } from './dtos/faqs-create.dto';
import { FaqsUpdateDto } from './dtos/faqs-update.dto';

@Injectable()
export class FaqsService {
    constructor(
        private faqsRepository: FaqsRepository,

        @InjectRepository(Faqs)
        private Faqs: Repository<Faqs>,

        @InjectRepository(Users)
        private Users: Repository<Users>,

    ) {}

    async list(queryParam:any,user:any)
    {
        const reqPage = queryParam.page ? queryParam.page : 0;
        const page = queryParam.page - 1;
        const pageSize = queryParam.per_page ? queryParam.per_page : Constants.faqs_list;
        const offset = page * pageSize;
        const nextPage = page + 1;
        const nextOffset = nextPage * pageSize;

        let sortByArr = {
            questions : 'faqs.questions',
            answers : 'faqs.answers',
            is_active : 'faqs.is_active',
            faq_for : 'faqs.faq_for',
            created_at : 'faqs.created_at',
        };

        let sort_by = queryParam.sort_by || 'created_at';
        let sort_type = queryParam.sort || 'ASC';
        sort_by = sortByArr[sort_by];

        let query = await this.Faqs
        .createQueryBuilder('faqs')
        .where('faqs.deleted_at is NULL')
            .select(['faqs.id', 'faqs.questions', 'faqs.faq_for', 'faqs.answers','faqs.is_active','faqs.created_at'])
        .orderBy(sort_by,sort_type);

        if((user.role != UserRoles.ADMIN)){
            query = query.andWhere('faqs.is_active = :is_active', { is_active: true })
                    .andWhere('faqs.faq_for = :role', { role: user.role })
        } 

        if (queryParam.search) {
            query = query.andWhere(`(faqs.questions ILIKE :search OR faqs.answers ILIKE :search OR faqs.faq_for ILIKE :search)`, { search: `%${queryParam.search}%` });
        }
        if(queryParam.faq_for){
            query = query.andWhere(`(faqs.faq_for = :faq_for)`, { faq_for: queryParam.faq_for });
        }
       
        if(reqPage !== 0){
            query = query.skip(offset).take(pageSize);
        }

        const [results, total] = await query.getManyAndCount();

        return {
            data: results,
            total : total,
            hasMoreResults : (total > nextOffset) ? 1 : 0,
        }
    }

    async faqDetail(param : any)
    {
        const faq = await this.Faqs
        .createQueryBuilder('faqs')
        .where('faqs.id = :id', { id : param.faq_id })
        .select(['faqs.id','faqs.questions','faqs.faq_for','faqs.answers','faqs.is_active','faqs.created_at'])
        .getOne();

        if(!faq){
            throw  new HttpException(responseMessages.en.faqs.faqs_not_exists,HttpStatus.NOT_FOUND);
        }

        return { data : faq }
    }

    async create(request: FaqsCreateDto, authUser:any)
    {
        request['created_by'] = authUser;
        this.faqsRepository.createFaqData(request);
        return;
    }

    async update(request : any,params : any,authUser:any)
    {
        const esistFaq = await this.Faqs.findOne({where:[{id : params.faq_id}]});
        if(!esistFaq){
            throw  new HttpException(responseMessages.en.faqs.faqs_not_exists,HttpStatus.NOT_FOUND);
        }

        esistFaq['questions'] = request.questions;
        esistFaq['answers'] = request.answers;
        esistFaq['faq_for'] = request.faq_for;
        esistFaq['updated_by'] = authUser;
        await  this.Faqs.save(esistFaq);
        return;
    }

    async delete(params : any)
    {
        const existsFaq = await this.Faqs.findOne({where: [{ id: params.faq_id }] });

        if (!existsFaq) {
            throw  new HttpException(responseMessages.en.faqs.faqs_not_exists,HttpStatus.NOT_FOUND);
        }

        let id = existsFaq.id;
        await this.Faqs.delete(id);
        return;
    }

    async changeStatus(params : any)
    {
        let existsFaq = await this.Faqs.findOne({ where: [{ id: params.faq_id }] });

        if(!existsFaq){
            throw  new HttpException(responseMessages.en.faqs.faqs_not_exists,HttpStatus.NOT_FOUND);
        }

        existsFaq['is_active'] = (existsFaq.is_active == true) ? false : true;
        await this.Faqs.save(existsFaq);
        return;
    }
}
