package com.nisum.example.mongodb.controller;

import com.nisum.example.mongodb.model.Employee;
import com.nisum.example.mongodb.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * Controller class having http POST, GET, UPDATE and DELETE methods
 */
@RestController
public class EmployeeController {

    @Autowired
    private IEmployeeService employeeService;

    /**
     * POST method to perform record creation
     * @param e
     * @return Mono
     */
    @PostMapping(path = "/create")
   @ResponseStatus(HttpStatus.CREATED)
    public Mono<Employee> create(@RequestBody Employee e) {

        return employeeService.insert(e).log();
    }

    /**
     * GET method to fetch record based on Id
     * @param id
     * @return Mono
     */
    @GetMapping("/{id}")
    public Mono<ResponseEntity<Employee>> findById(@PathVariable("id") Integer id) {
        return employeeService.fetchById(id)
                .log()
                .map(employee -> new ResponseEntity<>(employee,HttpStatus.OK))
                .log()
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * GET method to fetch record based on name
     * @param name
     * @return Flux
     */
    @GetMapping("/name/{name}")
    public Flux<Employee> findByName(@PathVariable("name") String name) {
        return employeeService.fetchByName(name).log();

    }

    /**
     * GET method to fetch all records
     * @return Flux
     */
    @GetMapping(value = "")
    public Flux<Employee> findAll() {
        Flux<Employee> emps = employeeService.fetchAll()
                .log()
                .filter(employee -> employee.getSalary()>2000);
        return emps;
    }

    /**
     * PUT method to do modify of record
     * @param emp
     * @return Mono
     */
    @PutMapping("/update")
    public Mono<Employee> update(@RequestBody Employee emp) {
        return employeeService.modify(emp).log();
    }

    @PutMapping("/{id}")
    public Mono<ResponseEntity<Employee>> updateById(@PathVariable("id") Integer id,
                                                     @RequestBody Employee employee){
        return employeeService.modifyById(id)
                .flatMap(emp->{
                    emp.setSalary(employee.getSalary());
                    return employeeService.insert(emp);
                })
                .log()
                .map(updateEmp-> new ResponseEntity<>(updateEmp,HttpStatus.OK))
                .log()
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));

    }
    /**
     * DELETE method to remove record based on Id
     * @param id
     * @return Void
     */
    @DeleteMapping("/delete/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteById(@PathVariable("id") Integer id) {
        employeeService.removeById(id);
    }

}