package com.yuchen.saas.park.service.service.door.communication.impl;

import com.alibaba.fastjson.JSON;
import com.yuchen.saas.manage.user.api.entity.User;
import com.yuchen.saas.park.api.commons.domain.DoorAccessControlConfigTarget;
import com.yuchen.saas.park.service.mapper.door.adapter.AdapterRepository;
import com.yuchen.saas.park.service.service.door.communication.DoorAccessControlCommandService;
import com.yuchen.saas.park.service.service.door.communication.DoorAccessControlCommunicationComponent;
import com.yuchen.saas.park.service.service.door.communication.domain.CallResult;
import com.yuchen.saas.park.service.service.door.communication.domain.CommonsParameter;
import com.yuchen.saas.park.service.service.door.communication.domain.card.AddCardParameter;
import com.yuchen.saas.park.service.service.door.communication.domain.card.DeleteCardParameter;
import com.yuchen.saas.park.service.service.door.communication.domain.user.AddUserFacialParameter;
import com.yuchen.saas.park.service.service.door.communication.domain.user.AddUserParameter;
import com.yuchen.saas.park.service.service.door.communication.domain.user.DeleteUserParameter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Positive;
import java.util.NoSuchElementException;
import java.util.Set;

import static java.util.Optional.ofNullable;

@Service
@Slf4j
@RequiredArgsConstructor
public class DoorAccessControlCommandServiceImpl implements DoorAccessControlCommandService {
    private final DoorAccessControlCommunicationComponent doorAccessControlCommunicationComponent;
    private final AdapterRepository adapterRepository;

    @Override
    public CallResult addUser(DoorAccessControlConfigTarget target, @NotEmpty Set<@Positive Long> configNos) {
        val userId = target.getUserId();

        log.info("====== 调用iot添加用户:{}", JSON.toJSON(target));
        return doorAccessControlCommunicationComponent.addUser(this.getByTarget(target), AddUserParameter.of(userId, this.getUsernameById(userId), configNos));
    }

    @Override
    public CallResult deleteUser(DoorAccessControlConfigTarget target) {
        return doorAccessControlCommunicationComponent.deleteUser(this.getByTarget(target), DeleteUserParameter.of(target.getUserId()));
    }

    @Override
    public CallResult addCard(DoorAccessControlConfigTarget target, @NotBlank String no) {
        log.info("====== 调用iot添加卡:{}", JSON.toJSON(target));

        return doorAccessControlCommunicationComponent.addCard(this.getByTarget(target), AddCardParameter.of(target.getUserId(), no));
    }

    @Override
    public CallResult deleteCard(DoorAccessControlConfigTarget target, @NotBlank String no) {
        return doorAccessControlCommunicationComponent.deleteCard(this.getByTarget(target), DeleteCardParameter.of(target.getUserId(), no));
    }

    @Override
    public CallResult addUserFacial(DoorAccessControlConfigTarget target, @NotBlank String facial) {
        log.info("====== 调用iot添加人脸:{}", JSON.toJSON(target));

        return doorAccessControlCommunicationComponent.addUserFacial(this.getByTarget(target), AddUserFacialParameter.of(target.getUserId(), facial));
    }

    private CommonsParameter getByTarget(DoorAccessControlConfigTarget target) {
        val doorAccessControlId = target.getDoorAccessControlId();
        return adapterRepository.getCommonsParameterByDoorAccessControlId(doorAccessControlId).orElseThrow(() -> new NoSuchElementException("门禁 [" + doorAccessControlId + "] 信息有误"));
    }

    private String getUsernameById(@Positive long userId) {
        return ofNullable(adapterRepository.selectById(userId)).map(User::getRealName).filter(StringUtils::hasLength).orElse("***");
    }
}
