package io.renren.modules.sys.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import io.renren.common.constant.Constant;
import io.renren.common.exception.RenException;
import io.renren.common.page.PageData;
import io.renren.common.service.impl.CrudServiceImpl;
import io.renren.common.utils.ConvertUtils;
import io.renren.modules.sys.dao.BudgetDao;
import io.renren.modules.sys.dao.CompaniesDao;
import io.renren.modules.sys.dao.LandingPagesDao;
import io.renren.modules.sys.dao.ScopeCityCompanyDao;
import io.renren.modules.sys.dao.ScopeCityCostDao;
import io.renren.modules.sys.dao.ScopeCityDao;
import io.renren.modules.sys.dto.ScopeCityCompanyDTO;
import io.renren.modules.sys.entity.BudgetEntity;
import io.renren.modules.sys.entity.CompaniesEntity;
import io.renren.modules.sys.entity.LandingPagesEntity;
import io.renren.modules.sys.entity.ScopeCityCompanyEntity;
import io.renren.modules.sys.entity.ScopeCityCostEntity;
import io.renren.modules.sys.entity.ScopeCityEntity;
import io.renren.modules.sys.service.ScopeCityCompanyService;

/**
 * 落地城市公司明细表
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0 2022-05-28
 */
@Service
public class ScopeCityCompanyServiceImpl extends CrudServiceImpl<ScopeCityCompanyDao, ScopeCityCompanyEntity, ScopeCityCompanyDTO> implements ScopeCityCompanyService {

    @Autowired
    private BudgetDao budgetDao;
    @Autowired
    private ScopeCityDao scopeCityDao;
    @Autowired
    private LandingPagesDao landingPagesDao;
    @Autowired
    private ScopeCityCostDao scopeCityCostDao;
    @Autowired
    private CompaniesDao companiesDao;
    @Autowired
	private RedisTemplate<String, Object> redisTemplate;
    
    
    @Override
    public QueryWrapper<ScopeCityCompanyEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");
        String scopeCityId = (String)params.get("scopeCityId");
        String companyId = (String)params.get("companyId");

        QueryWrapper<ScopeCityCompanyEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id).eq("status",1)
                .eq(StringUtils.isNotBlank(scopeCityId), "scope_city_id", scopeCityId)
                .eq(StringUtils.isNotBlank(companyId), "company_id", companyId)
                .orderByDesc("id");

        return wrapper;
    }

    @Override
    public PageData<ScopeCityCompanyDTO> page(Map<String, Object> params) {
        IPage<ScopeCityCompanyEntity> page = baseDao.selectPage(
                getPage(params, null, false),
                getWrapper(params)
        );
        List<ScopeCityCompanyDTO> scopeCityCompanyDTOList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(page.getRecords())){
            ScopeCityCompanyDTO scopeCityCompanyDTO = null;
            for (ScopeCityCompanyEntity scopeCityCompanyEntity:page.getRecords()){
                scopeCityCompanyDTO = new ScopeCityCompanyDTO();
                BeanUtils.copyProperties(scopeCityCompanyEntity,scopeCityCompanyDTO);
                if(scopeCityCompanyEntity.getCompanyId()!=null){
                    CompaniesEntity companiesEntity = companiesDao.selectById(scopeCityCompanyEntity.getCompanyId());
                    if (companiesEntity!=null && companiesEntity.getStatus()==1) {
                        scopeCityCompanyDTO.setCompanyName(companiesEntity.getName());
                    }
                    scopeCityCompanyDTOList.add(scopeCityCompanyDTO);
                }
            }
        }
        return new PageData<>(scopeCityCompanyDTOList, page.getTotal());
    }

    @Override
    @Transactional
    public void save(ScopeCityCompanyDTO dto) {
        ScopeCityCompanyEntity entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
        entity = generateAvgPriceAndAssignPersonCount(entity);
        baseDao.insert(entity);
    }

    @Override
    @Transactional
    public void update(ScopeCityCompanyDTO dto) {
        ScopeCityCompanyEntity entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
        entity = generateAvgPriceAndAssignPersonCount(entity);
        baseDao.updateById(entity);
    }

    private ScopeCityCompanyEntity generateAvgPriceAndAssignPersonCount(ScopeCityCompanyEntity entity){
        //计算分配人数（公司预算/城市单价（调整价优先））
        entity.setAssignPersonCount(0);
        //1.查询落地城市主表
        ScopeCityEntity scopeCityEntity = scopeCityDao.selectById(entity.getScopeCityId());
        if (scopeCityEntity!=null && StringUtils.isNotEmpty(scopeCityEntity.getCity())){
            //2.查询公司预算（公司+城市）
            BudgetEntity budgetEntity = budgetDao.selectOne(new QueryWrapper<BudgetEntity>().eq("status",1)
                    .eq("company_id",entity.getCompanyId())
                    .eq("city",scopeCityEntity.getCity()).orderByDesc("scheduled_date").last("limit 1"));;
            if (budgetEntity!=null){
                //3.查询落地页账户id
                LandingPagesEntity landingPagesEntity = landingPagesDao.selectById(scopeCityEntity.getPageId());
                if (landingPagesEntity!=null && StringUtils.isNotEmpty(landingPagesEntity.getAdvertiserId())){
                    //4.查询受众城市单价(账户+城市)
                    ScopeCityCostEntity scopeCityCostEntity = scopeCityCostDao.selectOne(new QueryWrapper<ScopeCityCostEntity>().eq("status",1)
                            .eq("advertiser_id",landingPagesEntity.getAdvertiserId())
                            .eq("city",scopeCityEntity.getCity()).orderByDesc("date").last("limit 1"));
                    if (scopeCityCostEntity!=null){
                        //城市单价
                        entity.setAvgPrice(scopeCityCostEntity.getManuAvgCost()!=null?scopeCityCostEntity.getManuAvgCost():scopeCityCostEntity.getAvgCost());
                        //人数分配
                        if (budgetEntity.getTopLimitMoney()!=null && entity.getAvgPrice()!=null && entity.getAvgPrice().compareTo(BigDecimal.ZERO)!=0){
                            entity.setAssignPersonCount(budgetEntity.getTopLimitMoney().divide(entity.getAvgPrice(),0,BigDecimal.ROUND_HALF_UP).intValue());
                            //可分配人数有变动时，清除公司已分配人数缓存
                            redisTemplate.delete(Constant.COMPANY_COUNT_KEY+entity.getCompanyId());
                        }
                    }else{
                        throw new RenException("广告主账户在该城市没有受众城市单价记录，不允许操作");
                    }
                }
            }else{
                throw new RenException("公司在该城市没有预算记录，不允许操作");
            }
        }
        return entity;
    }

	@Override
	public List<String> getScopeCityIdByCompanyId(Long companyId) {
		return baseDao.getScopeCityIdByCompanyId(companyId);
	}
}