package cn.lihongjie.coal.organization.service;

import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.coalParameterDef.service.CoalParameterDefService;
import cn.lihongjie.coal.organization.dto.CreateOrganizationDto;
import cn.lihongjie.coal.organization.dto.OrganizationDto;
import cn.lihongjie.coal.organization.dto.UpdateOrganizationDto;
import cn.lihongjie.coal.organization.entity.OrganizationEntity;
import cn.lihongjie.coal.organization.mapper.OrganizationMapper;
import cn.lihongjie.coal.organization.repository.OrganizationRepository;
import cn.lihongjie.coal.rabbitmq.RabbitMQService;
import cn.lihongjie.coal.user.dto.CreateOrgAdminDto;
import cn.lihongjie.coal.user.service.UserService;

import jakarta.annotation.PostConstruct;

import lombok.extern.slf4j.Slf4j;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;

@Service
@Slf4j
@Transactional
public
class OrganizationService extends BaseService<OrganizationEntity, OrganizationRepository> {

    @Autowired OrganizationRepository repository;

    @Autowired OrganizationMapper mapper;
    @Autowired ConversionService conversionService;

    @Autowired UserService userService;

    @Autowired CoalParameterDefService coalParameterDefService;

    @Autowired RabbitMQService rabbitMQService;

    @PostConstruct
    public void init() {}

    @Autowired RabbitTemplate rabbitTemplate;

    public OrganizationDto create(CreateOrganizationDto request) {

        OrganizationEntity entity = mapper.toEntity(request);

        this.repository.save(entity);

        CreateOrgAdminDto dto = new CreateOrgAdminDto();
        dto.setOrganizationId(entity.getId());
        dto.setUsername(request.getOrgAdminUserName());
        dto.setPassword(request.getOrgAdminPassword());
        userService.createOrgAdmin(dto);
        rabbitMQService.sendToSysExchange("organization.create", entity.getId(), new HashMap<String, String>());
        return getById(entity.getId());
    }

    public OrganizationDto update(UpdateOrganizationDto request) {
        OrganizationEntity entity = this.repository.get(request.getId());
        this.mapper.updateEntity(entity, request);

        this.repository.save(entity);
        rabbitMQService.sendToSysExchange("organization.update", entity.getId(), new HashMap<String, String>());
        return getById(entity.getId());
    }

    public void delete(IdRequest request) {

        this.repository.deleteAllById(request.getIds());
    }

    public OrganizationDto getById(String id) {

        OrganizationEntity entity = repository.get(id);

        return mapper.toDto(entity);
    }

    public Page<OrganizationDto> list(CommonQuery query) {

        Page<OrganizationEntity> page =
                repository.findAll(
                        query.specification(conversionService),
                        PageRequest.of(
                                query.getPageNo(),
                                query.getPageSize(),
                                Sort.by(query.getOrders())));

        return page.map(this.mapper::toDto);
    }

    public OrganizationEntity initOrGetAdminOrg() {

        OrganizationEntity adminOrg = this.repository.findByCode("adminOrg");

        if (adminOrg == null) {

            adminOrg = new OrganizationEntity();

            adminOrg.setParent(null);
            adminOrg.setName("管理员机构");
            adminOrg.setCode("adminOrg");
            adminOrg.setMaxUser(100);
            adminOrg.setExpireTime(LocalDateTime.now().plusYears(100));
            adminOrg.setStatus(1);

            this.repository.save(adminOrg);
        }

        return adminOrg;
    }
}
