package vn.azteam.tpf.web.rest;

import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.springframework.web.multipart.MultipartFile;
import vn.azteam.tpf.service.TBEnvironmentUpdateService;
import vn.azteam.tpf.service.dto.*;
import vn.azteam.tpf.web.rest.errors.BadRequestAlertException;
import vn.azteam.tpf.web.rest.util.HeaderUtil;
import vn.azteam.tpf.web.rest.util.PaginationUtil;
import vn.azteam.tpf.service.TBEnvironmentUpdateQueryService;
import io.github.jhipster.web.util.ResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import vn.azteam.tpf.service.util.UserRoleUtil;


/**
 * REST controller for managing TBEnvironmentUpdate.
 */
@RestController
@RequestMapping("/api")
public class TBEnvironmentUpdateResource {

    private final Logger log = LoggerFactory.getLogger(TBEnvironmentUpdateResource.class);

    private static final String ENTITY_NAME = "tBEnvironmentUpdate";

    private final TBEnvironmentUpdateService tBEnvironmentUpdateService;

    private final TBEnvironmentUpdateQueryService tBEnvironmentUpdateQueryService;

    private final UserRoleUtil userRoleUtil;

    private final ObjectMapper objectMapper;

    public TBEnvironmentUpdateResource(TBEnvironmentUpdateService tBEnvironmentUpdateService,
                                       TBEnvironmentUpdateQueryService tBEnvironmentUpdateQueryService,
                                       UserRoleUtil userRoleUtil,
                                       ObjectMapper objectMapper) {
        this.tBEnvironmentUpdateService = tBEnvironmentUpdateService;
        this.tBEnvironmentUpdateQueryService = tBEnvironmentUpdateQueryService;
        this.userRoleUtil = userRoleUtil;
        this.objectMapper = objectMapper;
    }

    /**
     * POST  /tb-environment-updates : Create a new tBEnvironmentUpdate.
     *
     * @param tBEnvironmentUpdateDTO the tBEnvironmentUpdateDTO to create
     * @return the ResponseEntity with status 201 (Created) and with body the new tBEnvironmentUpdateDTO, or with status 400 (Bad Request) if the tBEnvironmentUpdate has already an ID
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PostMapping("/tb-environment-updates")
    @Timed
    public ResponseEntity<TBEnvironmentUpdateDTO> createTBEnvironmentUpdate(@RequestBody TBEnvironmentUpdateDTO tBEnvironmentUpdateDTO) throws URISyntaxException {
        log.debug("REST request to save TBEnvironmentUpdate : {}", tBEnvironmentUpdateDTO);
        if (tBEnvironmentUpdateDTO.getId() != null) {
            throw new BadRequestAlertException("A new tBEnvironmentUpdate cannot already have an ID", ENTITY_NAME, "idexists");
        }
        TBEnvironmentUpdateDTO result = tBEnvironmentUpdateService.save(tBEnvironmentUpdateDTO);
        return ResponseEntity.created(new URI("/api/tb-environment-updates/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
            .body(result);
    }

    /**
     * PUT  /tb-environment-updates : Updates an existing tBEnvironmentUpdate.
     *
     * @param tBEnvironmentUpdateDTO the tBEnvironmentUpdateDTO to update
     * @return the ResponseEntity with status 200 (OK) and with body the updated tBEnvironmentUpdateDTO,
     * or with status 400 (Bad Request) if the tBEnvironmentUpdateDTO is not valid,
     * or with status 500 (Internal Server Error) if the tBEnvironmentUpdateDTO couldn't be updated
     * @throws URISyntaxException if the Location URI syntax is incorrect
     */
    @PutMapping("/tb-environment-updates")
    @Timed
    public ResponseEntity<TBEnvironmentUpdateDTO> updateTBEnvironmentUpdate(@RequestBody TBEnvironmentUpdateDTO tBEnvironmentUpdateDTO) throws URISyntaxException {
        log.debug("REST request to update TBEnvironmentUpdate : {}", tBEnvironmentUpdateDTO);
        if (tBEnvironmentUpdateDTO.getId() == null) {
            throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
        }
        TBEnvironmentUpdateDTO result = tBEnvironmentUpdateService.save(tBEnvironmentUpdateDTO);
        return ResponseEntity.ok()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, tBEnvironmentUpdateDTO.getId().toString()))
            .body(result);
    }

    /**
     * GET  /tb-environment-updates : get all the tBEnvironmentUpdates.
     *
     * @param pageable the pagination information
     * @param criteria the criterias which the requested entities should match
     * @return the ResponseEntity with status 200 (OK) and the list of tBEnvironmentUpdates in body
     */
    @GetMapping("/tb-environment-updates")
    @Timed
    public ResponseEntity<List<TBEnvironmentUpdateDTO>> getAllTBEnvironmentUpdates(TBEnvironmentUpdateCriteria criteria, Pageable pageable) {
        log.debug("REST request to get TBEnvironmentUpdates by criteria: {}", criteria);
        Page<TBEnvironmentUpdateDTO> page = tBEnvironmentUpdateQueryService.findByCriteria(criteria, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tb-environment-updates");
        return ResponseEntity.ok().headers(headers).body(page.getContent());
    }

    /**
    * GET  /tb-environment-updates/count : count all the tBEnvironmentUpdates.
    *
    * @param criteria the criterias which the requested entities should match
    * @return the ResponseEntity with status 200 (OK) and the count in body
    */
    @GetMapping("/tb-environment-updates/count")
    @Timed
    public ResponseEntity<Long> countTBEnvironmentUpdates(TBEnvironmentUpdateCriteria criteria) {
        log.debug("REST request to count TBEnvironmentUpdates by criteria: {}", criteria);
        return ResponseEntity.ok().body(tBEnvironmentUpdateQueryService.countByCriteria(criteria));
    }

    /**
     * GET  /tb-environment-updates/:id : get the "id" tBEnvironmentUpdate.
     *
     * @param id the id of the tBEnvironmentUpdateDTO to retrieve
     * @return the ResponseEntity with status 200 (OK) and with body the tBEnvironmentUpdateDTO, or with status 404 (Not Found)
     */
    @GetMapping("/tb-environment-updates/{id}")
    @Timed
    public ResponseEntity<TBEnvironmentUpdateDTO> getTBEnvironmentUpdate(@PathVariable Long id) {
        log.debug("REST request to get TBEnvironmentUpdate : {}", id);
        Optional<TBEnvironmentUpdateDTO> tBEnvironmentUpdateDTO = tBEnvironmentUpdateService.findOne(id);
        return ResponseUtil.wrapOrNotFound(tBEnvironmentUpdateDTO);
    }

    /**
     * DELETE  /tb-environment-updates/:id : delete the "id" tBEnvironmentUpdate.
     *
     * @param id the id of the tBEnvironmentUpdateDTO to delete
     * @return the ResponseEntity with status 200 (OK)
     */
    @DeleteMapping("/tb-environment-updates/{id}")
    @Timed
    public ResponseEntity<Void> deleteTBEnvironmentUpdate(@PathVariable Long id) {
        log.debug("REST request to delete TBEnvironmentUpdate : {}", id);
        tBEnvironmentUpdateService.delete(id);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }

    /**
     * SEARCH  /_search/tb-environment-updates?query=:query : search for the tBEnvironmentUpdate corresponding
     * to the query.
     *
     * @param query the query of the tBEnvironmentUpdate search
     * @param pageable the pagination information
     * @return the result of the search
     */
    @GetMapping("/_search/tb-environment-updates")
    @Timed
    public ResponseEntity<List<TBEnvironmentUpdateDTO>> searchTBEnvironmentUpdates(@RequestParam String query, Pageable pageable) {
        log.debug("REST request to search for a page of TBEnvironmentUpdates for query {}", query);
        Page<TBEnvironmentUpdateDTO> page = tBEnvironmentUpdateService.search(query, pageable);
        HttpHeaders headers = PaginationUtil.generateSearchPaginationHttpHeaders(query, page, "/api/_search/tb-environment-updates");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

    @PostMapping("/createEnv")
    @Timed
    public ResponseEntity<TBActivityDTO> createActivityEnv(@RequestParam("activityEnv") String data_body,
                                                             @RequestParam(value = "images") final MultipartFile[] images,
                                                             Pageable pageable
    ) throws IOException {
        ActivityEnvDTO activityEnvDTO = parseActivityEnvDTOFromJsonString(data_body);
        //@CUONGLT - Filter scope customer's data
        boolean check = userRoleUtil.currentUserHasPermissionByCropId(activityEnvDTO.getCropId());
        if(check){
            TBActivityDTO result = tBEnvironmentUpdateQueryService.createActivityEnv(activityEnvDTO, images, pageable);
            return ResponseEntity.ok()
                .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, result.getId().toString()))
                .body(result);
        }
        return ResponseEntity.badRequest()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, "Grant access this scope"))
            .body(null);

    }

    @PostMapping("/updateEnv")
    @Timed
    public ResponseEntity<TBActivityDTO> updateActivityEnv(@RequestParam("activityEnv") String data_body,
                                                             @RequestParam(value = "images") final MultipartFile[] images,
                                                             Pageable pageable
    ) throws IOException {
        ActivityEnvDTO activityEnvDTO = parseActivityEnvDTOFromJsonString(data_body);
        //@CUONGLT - Filter scope customer's data
        boolean check = userRoleUtil.currentUserHasPermissionByCropId(activityEnvDTO.getCropId());
        if(check){
            TBActivityDTO result = tBEnvironmentUpdateQueryService.updateActivityEnv(activityEnvDTO, images, pageable);
            return ResponseEntity.ok()
                .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, result.getId().toString()))
                .body(result);
        }
        return ResponseEntity.badRequest()
            .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, "Grant access this scope"))
            .body(null);
    }


    private ActivityEnvDTO parseActivityEnvDTOFromJsonString(String data_request) {
        ActivityEnvDTO data;
        try {
            data = this.objectMapper.readValue(data_request, ActivityEnvDTO.class);
        } catch (Exception e) {
            throw new BadRequestAlertException("1041", ENTITY_NAME, "1041");
        }
        return data;
    }

    @GetMapping("/list-environment-updates-display/{cropId}")
    @Timed
    public ResponseEntity<List<TBEnvironmentUpdateDisplayDTO>> getListTBEnvironmentUpdatesDisplay(@PathVariable Long cropId, TBEnvironmentUpdateCriteria criteria, Pageable pageable) {
        log.debug("REST request to get TBEnvironmentUpdates by criteria: {}", criteria);
        Page<TBEnvironmentUpdateDTO> page = tBEnvironmentUpdateQueryService.findByCriteria(criteria, pageable);

        List<TBEnvironmentUpdateDisplayDTO> result = userRoleUtil.currentUserHasPermissionByCropId(cropId) ? tBEnvironmentUpdateQueryService.getListTBEnvironmentUpdatesDisplay(cropId) : Lists.newArrayList();

        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/list-environment-updates-display");
        return ResponseEntity.ok().headers(headers).body(result);
    }

    @PostMapping("/notification/exceed-limit")
    public ResponseEntity sendNotificationExceedLimit(@RequestBody List<NotificationEnvAutoDTO> notificationEnvAutoDTOs, Pageable pageable) {
        tBEnvironmentUpdateQueryService.sendNotificationEnvAuto(notificationEnvAutoDTOs, pageable);
        return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Successful! Notification has been sent."), HttpStatus.OK);
    }
}
