import {
  BadRequestException,
  ConflictException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { CreateCityDto } from './dto/create-city.dto';
import { UpdateCityDto } from './dto/update-city.dto';
import isValidUuidV4 from 'src/common/uuid validator/uuid-validate';
import { isEmpty } from 'src/common/helper';
import { lan } from 'src/lan';
import { CityEntity } from './entities/city.entity';
import { CityRepository } from './cities.repository';
import { InjectRepository } from '@nestjs/typeorm';
import { EntityManager, Repository } from 'typeorm';
import { saveLogs } from 'src/api-logs/api-error-log';
import { cityData } from '../common/city-json';
@Injectable()
export class CitiesService {
  constructor(
    @InjectRepository(CityEntity)
    private readonly courseService: Repository<CityEntity>,
    private readonly courseRepository: CityRepository,
  ) {}

  async bulkUpload(manager: EntityManager) {
    const citiesToInsert: any[] = [];

    Object.keys(cityData).forEach((state) => {
      cityData[state].forEach((city) => {
        if (
          !citiesToInsert.some(
            (item) => item.name === city && item.state === state,
          )
        ) {
          citiesToInsert.push({ name: city, state });
        }
      });
    });

    await manager.getRepository(CityEntity).save(citiesToInsert);
  }

  async create(createCourseDto: CreateCityDto) {
    const createCourse: CreateCityDto = new CityEntity();

    const data = await this.courseRepository.findByCity(createCourseDto.name);

    if (!isEmpty(data)) {
      throw new ConflictException(lan('city.already.exist'));
    } else {
      Object.assign(createCourse, createCourseDto);
      const returnData = await this.courseService.save(createCourse);

      return returnData;
    }
  }

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

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

    const course = await this.courseRepository.findOne(id);

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

    return course;
  }

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

    const courseObj = await this.courseRepository.findOne(id);

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

    const data = await this.courseRepository.findByCity(
      updateCourseDto.name,
      id,
    );

    Object.assign(courseObj, updateCourseDto);

    if (
      updateCourseDto.status !== undefined &&
      updateCourseDto.status !== null
    ) {
      courseObj.status = updateCourseDto.status;
    }

    if (!isEmpty(data)) {
      throw new ConflictException('City Already Exists');
    }

    await this.courseService.update(id, updateCourseDto);

    return courseObj;
  }

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

    const cityObj = await this.courseRepository.findOne(id);

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

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