package com.fsd.hellovelo.controller;


import com.fsd.hellovelo.entity.EStatus;
import com.fsd.hellovelo.entity.Station;
import com.fsd.hellovelo.exceptions.ForeignKeyConstraintException;
import com.fsd.hellovelo.exceptions.ResourceNotFoundException;
import com.fsd.hellovelo.payload.request.RentalRequest;
import com.fsd.hellovelo.payload.response.GeocodeResponse;
import com.fsd.hellovelo.payload.response.MessageResponse;
import com.fsd.hellovelo.repository.StationRepository;
import com.fsd.hellovelo.service.StationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping("/api/admin/stations")
public class StationController {


    private final StationService stationService;

    @Autowired
    public StationController(StationService stationService) {
        this.stationService = stationService;
    }

    @GetMapping("")
    public  ResponseEntity<?> getAllStations() {
        try {
            List<Station> stations = stationService.findAllStations();
            return ResponseEntity.status(HttpStatus.OK).body(stations);
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
        }

    }

    @PostMapping
    public ResponseEntity<?> addStation(@Valid @RequestBody Station station) {
        try {
            return ResponseEntity.status(HttpStatus.OK).body(stationService.addNewStation(station));
        }
        catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(e.getMessage()));
        }
    }

    @DeleteMapping(path = "{stationId}")
    public ResponseEntity<?> deleteStation(@PathVariable("stationId") Long stationId) {
        try {
            stationService.deleteStation(stationId);
            return ResponseEntity.status(HttpStatus.OK).body("station deleted");
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(e.getMessage()));
        }
        catch (ForeignKeyConstraintException | IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(e.getMessage()));
        }
    }

    @GetMapping(path = "{stationId}")
    public ResponseEntity<?> getStation(@PathVariable("stationId") Long stationId) {
        try {
            Station station = stationService.getStation(stationId);
            return ResponseEntity.status(HttpStatus.OK).body(station);
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(e.getMessage()));
        }
    }

    @GetMapping("/transfer/{stationId}")
    public ResponseEntity<?> getStationWithBikes(@PathVariable("stationId") Long stationId) {
        try {
            Station station = stationService.getStationWithBikes(stationId);
            return ResponseEntity.status(HttpStatus.OK).body(station);
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(e.getMessage()));
        }
    }

    @GetMapping("/transfer/list/{stationId}")
    public ResponseEntity<?> getAllTransferStations(@PathVariable("stationId") Long stationId) {
        try {
            List<Station> stations = stationService.findAllTransferStations(stationId);
            return ResponseEntity.status(HttpStatus.OK).body(stations);
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(e.getMessage()));
        }
    }

    @PutMapping(path = "{stationId}")
    public ResponseEntity<?> updateStation(@PathVariable("stationId") Long stationId, @Valid @RequestBody Station newStation) {
        try {
            return ResponseEntity.status(HttpStatus.OK).body(stationService.updateStation(stationId, newStation));
        }
        catch (ResourceNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse(e.getMessage()));
        }
        catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(e.getMessage()));
        }
    }

    @GetMapping("/full")
    public ResponseEntity<?> getFullStations() {
        return ResponseEntity.status(HttpStatus.OK).body(stationService.getFullStations());
    }

    @GetMapping("/empty")
    public ResponseEntity<?> getEmptyStations() {
        return ResponseEntity.status(HttpStatus.OK).body(stationService.getEmptyStations());
    }

    @PostMapping("/closestStation")
    public ResponseEntity<?> getClosestStation(@RequestBody (required=false) String postalCode) {
        try{
            if(postalCode == null){
                throw new ResourceNotFoundException("Error: Invalid postal code.");
            }
            String regex = "[ABCEGHJ-NPRSTVXYabceghj-nprstvxy]\\d[ABCEGHJ-NPRSTV-Zabceghj-nprstv-z][ -]?\\d[ABCEGHJ-NPRSTV-Zabceghj-nprstv-z]\\d";
            if(!postalCode.matches(regex)){
                throw new ResourceNotFoundException("Error: Invalid postal code.!" + postalCode);
            }
            return ResponseEntity.status(HttpStatus.OK).body(stationService.getClosestStation(postalCode));
        }catch (ResourceNotFoundException ex){
            return ResponseEntity.badRequest().body(new MessageResponse(ex.getMessage()));
        }catch (IllegalArgumentException ex){
            return ResponseEntity.badRequest().body(ex.getMessage());
        }
    }
}
