package com.izouma.nineth.web;

import com.izouma.nineth.domain.AirDrop;
import com.izouma.nineth.domain.User;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.enums.AirDropType;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.lock.RedisLockException;
import com.izouma.nineth.repo.AirDropRepo;
import com.izouma.nineth.repo.UserRepo;
import com.izouma.nineth.repo.UserWareHouseRepo;
import com.izouma.nineth.service.AirDropService;
import com.izouma.nineth.service.CollectionService;
import com.izouma.nineth.utils.excel.ExcelUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/airDrop")
@Slf4j
@AllArgsConstructor
public class AirDropController extends BaseController {

    private static Thread airDropThread;

    private AirDropService airDropService;
    private AirDropRepo airDropRepo;

    private CollectionService collectionService;
    private UserRepo userRepo;
    private UserWareHouseRepo userWareHouseRepo;

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/save")
    public AirDrop save(@RequestBody AirDrop record) {
        try {
            AirDrop airDrop = airDropService.create(record);

            //需要减少缓存库存
            if (AirDropType.asset == airDrop.getType() && airDrop.getDropCount() != null) {
                collectionService.increaseStockCache(airDrop.getCollectionId(), -airDrop.getDropCount());
            }

            return airDrop;
        } catch (RedisLockException e) {
            throw new BusinessException("相同的空投操作正在执行，请稍后再试");
        }

    }

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/batchCreate")
    public AirDrop batchCreate(@RequestBody AirDrop record) {
        try {
            AirDrop airDrop = airDropService.batchCreate(record);

            //需要减少缓存库存
            if (AirDropType.asset == airDrop.getType() && airDrop.getDropCount() != null) {
                collectionService.increaseStockCache(airDrop.getCollectionId(), -airDrop.getDropCount());
            }

            return airDrop;
        } catch (RedisLockException e) {
            throw new BusinessException("相同的空投操作正在执行，请稍后再试");
        }

    }

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/sendBox")
    public synchronized int sendBox(@RequestParam String createdAt, @RequestParam Long surpriseBoxId, @RequestParam Integer projectId) {
        LocalDateTime dateTime = LocalDateTime.parse(createdAt, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        if(airDropThread != null && airDropThread.isAlive()){
            throw new BusinessException("一个空投任务正在处理，请稍后再试");
        }


        airDropThread = new Thread(() -> {


            List<User> users = userRepo.getUserLocalDateTime(dateTime);
            int totalCount = users.size();
            List<Long> usersbox =  userWareHouseRepo.findUserIdBoxByTargetCollectionId(surpriseBoxId);;
            users.removeIf(user ->  {
                for (Long id  :usersbox)    {
                    if (Objects.equals(id, user.getId()))   {
                        return true;
                    }
                }
                return false;
            });

            log.info("开始投放盒子{}, 总投放人数{}，已经投放的人数{},需要投放人数{}", surpriseBoxId, totalCount, usersbox.size(), users.size());

            //批量处理
            int batchSize = 500;
            int dropCount = 0;
            int batchCount = 0;
            long startMillis = System.currentTimeMillis();
            try {
                while (users != null && users.size() > 0){
                    batchCount++;
                    List<User> batchUser = null;
                    if (users.size() > batchSize) {
                        batchUser = users.subList(0, batchSize);
                        users = users.subList(batchSize, users.size());
                    } else {
                        batchUser = users;
                        users = null;
                    }


                    List<String> phoneList = batchUser.stream().map(User::getPhone).collect(Collectors.toList());
                    List<Long> idList = batchUser.stream().map(User::getId).collect(Collectors.toList());
                    long timeMillis = System.currentTimeMillis();
                    AirDrop airDrop = AirDrop.builder()
                            .name(createdAt+AirDropType.SURPRISE_BOX.getDescription())
                            .type(AirDropType.SURPRISE_BOX)
                            .surpriseBoxId(surpriseBoxId)
                            .phone(phoneList)
                            .userIds(idList)
                            .projectId(projectId)
                            .build();
                    airDropService.surpriseBoxAirDrop(airDrop);
                    Long duration = System.currentTimeMillis() - timeMillis;
                    log.info("完成第{}批投放数量：{} ,耗时 {}", batchCount, batchUser.size(), duration);

                    dropCount += batchUser.size();

                }

            }finally{
                Long duration = System.currentTimeMillis() - startMillis;
                log.info("完成投放盒子{}, 总完成{}批投放 , 完成数量{}，耗时 {}", surpriseBoxId,  batchCount, dropCount, duration);
            }


        });

        airDropThread.start();;

        return -1;


    }


    //@PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/all")
    public Page<AirDrop> all(@RequestBody PageQuery pageQuery) {
        return airDropService.all(pageQuery);
    }

    @GetMapping("/get/{id}")
    public AirDrop get(@PathVariable Long id) {
        return airDropRepo.findById(id).orElseThrow(new BusinessException("空投无记录"));
    }

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/del/{id}")
    public void del(@PathVariable Long id) {
//        airDropRepo.softDelete(id);
        throw new BusinessException("空投记录不能删除");
    }

    @PostMapping("/excel")
    @ResponseBody
    public void excel(HttpServletResponse response, @RequestBody PageQuery pageQuery) throws IOException {
        List<AirDrop> data = all(pageQuery).getContent();
        ExcelUtils.export(response, data);
    }


    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/upload")
    public void uploadFile(@RequestParam("file") MultipartFile file, @RequestParam Long collectionId) {
        try {
            airDropService.createWithUpload(file.getInputStream(), collectionId);
        } catch (IOException e) {
            log.error("上传失败", e);
            throw new BusinessException("上传失败", e.getMessage());
        }
    }


}

