package net.zstong.awump.monitoring.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import net.zstong.awump.base.entity.AwWarehouseEntity;
import net.zstong.awump.base.service.AwWarehouseService;
import net.zstong.awump.monitoring.entity.AwMonitoringAreaDeviceInfo;
import net.zstong.awump.monitoring.entity.AwMonitoringAreaEntity;
import net.zstong.awump.monitoring.entity.AwMonitoringDeviceEntity;
import net.zstong.awump.monitoring.entity.AwMonitoringDeviceInfo;
import net.zstong.awump.monitoring.service.AwMonitoringAreaService;
import net.zstong.awump.monitoring.service.AwMonitoringDeviceService;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryNoPagingOperation;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.QueryAction;
import org.hswebframework.web.authorization.annotation.Resource;
import org.hswebframework.web.crud.service.ReactiveCrudService;
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@RestController
@RequestMapping({"/aw/monitoring/device"})
@Resource(id = "aw-monitoring-deivce", name = "监控设备信息接口")
@Tag(name = "监控设备信息接口")
@Slf4j
public class AwMonitoringDeviceController implements ReactiveServiceCrudController<AwMonitoringDeviceEntity, String> {

    @Autowired
    private AwMonitoringDeviceService awMonitoringDeviceService;

    @Autowired
    private AwMonitoringAreaService awMonitoringAreaService;

    @Autowired
    private AwWarehouseService awWarehouseService;

    @Override
    public ReactiveCrudService<AwMonitoringDeviceEntity, String> getService() {
        return awMonitoringDeviceService;
    }


    @PostMapping("/info/_query")
    @QueryAction
    @Operation(summary = "分页查询监控设备信息详情")
    public Mono<PagerResult<AwMonitoringDeviceInfo>> queryInfo(@RequestBody Mono<QueryParamEntity> paramBody) {
        return paramBody
            .flatMap(param -> awMonitoringDeviceService.queryPager(param)
                .flatMap(result -> Flux
                    .fromIterable(result.getData()).flatMap(tp2 -> convert(tp2))
                    .collectList()
                    .map(info -> PagerResult.of(result.getTotal(), info, param))
                )
            );
    }

    private Mono<AwMonitoringDeviceInfo> convert(AwMonitoringDeviceEntity entity) {
        return Mono.just(AwMonitoringDeviceInfo.of(entity)).flatMap(e -> {

            return Mono.zip(
                e.getAreaId() != null ? awMonitoringAreaService.findById(e.getAreaId()).defaultIfEmpty(new AwMonitoringAreaEntity()) : Mono.just(new AwMonitoringAreaEntity()),
                e.getWarehouseId() != null ? awWarehouseService.findById(e.getWarehouseId()).defaultIfEmpty(new AwWarehouseEntity()) : Mono.just(new AwWarehouseEntity()),
                (m, w) -> {
                    e.setWarehouse(w);
                    e.setArea(m);
                    return e;
                }
            );
        });
    }

    @GetMapping("/_tree")
    @QueryNoPagingOperation(summary = "获取全部区域与监控设备(树结构)")
    @Authorize(merge = false)
    public Flux<AwMonitoringAreaDeviceInfo> getAllAreaDeviceTree(@Parameter(hidden = true) QueryParamEntity query) {
        return this
            .awMonitoringAreaService
            .createQuery()
            .setParam(query)
            .fetch()
            .flatMap(e -> {
                return Flux.merge(Mono.just(AwMonitoringAreaDeviceInfo.of(e)),
                    awMonitoringDeviceService.createQuery().where(AwMonitoringDeviceEntity::getAreaId, e.getId()).and(AwMonitoringDeviceEntity::getDeviceType,"NVR").fetch().flatMap(d -> {
                        d.setParentId(e.getId());
                        return Flux.merge(Mono.just(AwMonitoringAreaDeviceInfo.of(d)), awMonitoringDeviceService.createQuery().where(AwMonitoringDeviceEntity::getParentId, d.getId()).fetch().map(ccc -> AwMonitoringAreaDeviceInfo.of(ccc)));
                    })
                );
            })
            .map(o -> {
                    System.out.println("=====ooooo=========" + o.getClass());
                    return (AwMonitoringAreaDeviceInfo) o;
                }
            )
            .collectList()
            .flatMapMany(all -> {
                return Flux.fromIterable(TreeSupportEntity.list2tree(all, AwMonitoringAreaDeviceInfo::setChildren));
            });
    }

}
