package org.qinan.safetyeval.infrastructure.gatewayimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.qinan.safetyeval.domain.entity.AccountEntity;
import org.qinan.safetyeval.domain.gateway.AccountGateway;
import org.qinan.safetyeval.domain.query.AccountQuery;
import org.qinan.safetyeval.domain.query.PageResult;
import org.qinan.safetyeval.infrastructure.dataobject.AccountDO;
import org.qinan.safetyeval.infrastructure.mapper.AccountMapper;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户Gateway实现（Infrastructure层）
 *
 * @author safety-eval
 */
@Component
public class AccountGatewayImpl implements AccountGateway {

    @Resource
    private AccountMapper accountMapper;

    @Override
    public AccountEntity save(AccountEntity entity) {
        AccountDO dataObject = toDO(entity);
        InsertFieldDefaults.applyIgnoreOrgId(dataObject);
        accountMapper.insert(dataObject);
        entity.setId(dataObject.getId());
        entity.setTenantId(dataObject.getTenantId());
        return entity;
    }

    @Override
    public AccountEntity get(Long id) {
        AccountDO dataObject = accountMapper.selectById(id);
        return toEntity(dataObject);
    }

    @Override
    public AccountEntity getByAccount(String account) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getAccount, account);
        wrapper.eq(AccountDO::getDeleteEnum, "false");
        AccountDO dataObject = accountMapper.selectOne(wrapper);
        return toEntity(dataObject);
    }

    @Override
    public AccountEntity modify(AccountEntity entity) {
        AccountDO dataObject = toDO(entity);
        dataObject.setId(entity.getId());
        InsertFieldDefaults.applyForUpdate(dataObject);
        accountMapper.updateById(dataObject);
        return get(entity.getId());
    }

    @Override
    public void delete(Long id) {
        accountMapper.deleteById(id);
    }

    @Override
    public PageResult<AccountEntity> page(AccountQuery query) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getDeleteEnum, "false");
        if (StringUtils.hasText(query.getUserName())) {
            wrapper.like(AccountDO::getUserName, query.getUserName());
        }
        if (StringUtils.hasText(query.getAccount())) {
            wrapper.like(AccountDO::getAccount, query.getAccount());
        }
        if (StringUtils.hasText(query.getPhone())) {
            wrapper.like(AccountDO::getPhone, query.getPhone());
        }
        if (query.getType() != null) {
            wrapper.eq(AccountDO::getType, query.getType());
        }

        Page<AccountDO> page = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<AccountDO> result = accountMapper.selectPage(page, wrapper);

        List<AccountEntity> entities = result.getRecords().stream()
                .map(this::toEntity)
                .collect(Collectors.toList());

        return PageResult.of(entities, result.getTotal(), result.getCurrent(), result.getSize());
    }

    private AccountDO toDO(AccountEntity entity) {
        AccountDO dataObject = new AccountDO();
        dataObject.setUserName(entity.getUserName());
        dataObject.setAccount(entity.getAccount());
        dataObject.setPhone(entity.getPhone());
        dataObject.setPassword(entity.getPassword());
        dataObject.setProfileUrl(entity.getProfileUrl());
        dataObject.setType(entity.getType());
        dataObject.setTenantId(entity.getTenantId());
        return dataObject;
    }

    private AccountEntity toEntity(AccountDO dataObject) {
        if (dataObject == null) {
            return null;
        }
        AccountEntity entity = new AccountEntity();
        entity.setId(dataObject.getId());
        entity.setUserName(dataObject.getUserName());
        entity.setAccount(dataObject.getAccount());
        entity.setPhone(dataObject.getPhone());
        entity.setPassword(dataObject.getPassword());
        entity.setProfileUrl(dataObject.getProfileUrl());
        entity.setType(dataObject.getType());
        entity.setTenantId(dataObject.getTenantId());
        return entity;
    }
}
