import {
  BadRequestException,
  ConflictException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { CreateJobDto } from './dto/create-job.dto';
import { UpdateJobDto } from './dto/update-job.dto';
import isValidUuidV4 from 'src/common/uuid validator/uuid-validate';
import { lan } from 'src/lan';
import { isEmpty } from 'src/common/helper';
import { JobEntity } from './entities/job.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { EntityManager, Repository } from 'typeorm';
import { JobRepository } from './job.repository';
import * as ExcelJS from 'exceljs';

@Injectable()
export class JobService {
  constructor(
    @InjectRepository(JobEntity)
    private readonly jobService: Repository<JobEntity>,
    private readonly jobRepository: JobRepository,
  ) {}

  async processExcelFile(
    filePath: string,
    manager: EntityManager,
  ): Promise<void> {
    try {
      const workbook = new ExcelJS.Workbook();

      await workbook.xlsx.readFile(filePath);

      const worksheet = workbook.getWorksheet('Final');
      if (!worksheet) {
        throw new Error('Worksheet not found');
      }

      const row = worksheet.getRow(1);
      if (!row) {
        throw new Error('Row not found');
      }

      const dataRows = [];
      const columnName = ['Name'];

      const rowName: string[] = [];

      row.eachCell({ includeEmpty: false }, (cell) => {
        // Convert cell values to string
        let cellValue;
        if (cell.value instanceof Object) {
          cellValue = JSON.stringify(cell.value);
        } else {
          cellValue = String(cell.value);
        }
        rowName.push(cellValue);
      });

      worksheet.eachRow((row, rowNumber) => {
        if (rowNumber > 1) {
          const cellValue = row.getCell('A').value;
          const rowData = {
            name:
              cellValue instanceof Object
                ? JSON.stringify(cellValue)
                : String(cellValue),
          };

          dataRows.push(rowData);
        }
      });

      for (const data of dataRows) {
        const createJobDto = new CreateJobDto();
        createJobDto.name = data.name;

        const jobEntity = new JobEntity();
        if (createJobDto.name) {
          jobEntity.name = createJobDto.name;
        }

        await manager.save(jobEntity);
      }
    } catch (error) {
      throw new BadRequestException('Error processing Excel file');
    }
  }

  async create(createJobDto: CreateJobDto) {
    const createJob: CreateJobDto = new JobEntity();
    const data = await this.jobRepository.findJob(createJobDto.name);

    if (!isEmpty(data)) {
      throw new ConflictException(lan('job.already.exist'));
    } else {
      Object.assign(createJob, createJobDto);

      const returnData = await this.jobService.save(createJob);

      return returnData;
    }
  }

  async findAll(take: number, skip: number, search: string) {
    return await this.jobRepository.findAll(take, skip, search);
  }

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

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

    return course;
  }

  async update(id: string, updateJobDto: UpdateJobDto) {
    if (!isValidUuidV4(id)) {
      throw new BadRequestException(lan('common.invalid_uuid_format'));
    }
    const jobObj = await this.jobRepository.findOne(id);

    const data = await this.jobRepository.findJob(updateJobDto.name, id);

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

    if (jobObj.name) {
      jobObj.name = updateJobDto.name;
    }

    if (updateJobDto.status !== undefined && updateJobDto.status !== null) {
      jobObj.status = updateJobDto.status;
    }

    if (!isEmpty(data)) {
      throw new ConflictException(lan('job.already.exist'));
    }

    await this.jobService.update(id, updateJobDto);

    return jobObj;
  }

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

    const job = await this.jobRepository.findOne(id);

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

    return this.jobService.softDelete(id);
  }
}
