package cz.muni.fi.pa165.core.smartmeter;

import cz.muni.fi.pa165.core.Jwt.AuthService;
import cz.muni.fi.pa165.core.helpers.exceptions.EntityDeletionException;
import cz.muni.fi.pa165.model.dto.common.Result;
import cz.muni.fi.pa165.model.dto.smartDevice.SmartMeterCreateDto;
import cz.muni.fi.pa165.model.dto.smartDevice.SmartMeterUpdateDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.PositiveOrZero;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/smart-meter")
@Tag(name = "SmartMeter", description = "Smart Meter API")
public class SmartMeterController {

	private final SmartMeterFacade smartMeterFacade;

	@Autowired
	public SmartMeterController(SmartMeterFacade smartMeterFacade) {
		this.smartMeterFacade = smartMeterFacade;
	}

	@Operation(summary = "Find all smart meters with pagination or without", responses = {
			@ApiResponse(responseCode = "200", description = "List of smart meters", content = {
					@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Result.class))
			})
	})
	@GetMapping
	public ResponseEntity<?> findAll(@Parameter(description = "Page number of results to retrieve") @RequestParam(defaultValue = "0", required = false) @PositiveOrZero int page,
									   @Parameter(description = "Page size of results to retrieve") @RequestParam(defaultValue = "-1", required = false) int pageSize) {
		if(pageSize < 0)
			pageSize = 10;
		Pageable pageWithElements = PageRequest.of(page, pageSize);
		System.out.println(pageWithElements.getClass());
		return ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.findAllPageable(pageWithElements));
	}

	@Operation(summary = "Find smart meter by ID", description = "Returns the smart meter with the specified ID.")
	@GetMapping("/{id}")
	@ApiResponse(responseCode = "200", description = "Successfully retrieved the smart meter.")
	@ApiResponse(responseCode = "404", description = "Smart meter not found.")
	public ResponseEntity<?> findById(@PathVariable @Parameter(description = "The ID of the smart meter to retrieve.") String id) {
		return ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.findById(id));
	}

	@Operation(summary = "Create smart meter", description = "Creates a new smart meter.")
	@PostMapping
	@ApiResponse(responseCode = "201", description = "Successfully created a new smart meter.")
	@ApiResponse(responseCode = "404", description = "House not found.")
	public ResponseEntity<?> create(@RequestBody @Valid SmartMeterCreateDto smartMeterCreateDto) {
		if (!AuthService.HasUserCompanyRoleOrAdmin()){
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("You do not have enough permissions to create Smart Meter device.");
		}
		return ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.create(smartMeterCreateDto));
	}

	@Operation(summary = "Delete smart meter", description = "Deletes the smart meter with the specified ID.")
	@DeleteMapping("/{id}")
	@ApiResponse(responseCode = "200", description = "Successfully deleted the smart meter.")
	@ApiResponse(responseCode = "404", description = "Smart meter not found.")
	@ApiResponse(responseCode = "422", description = "Smart meter could not be deleted", content = @Content)
	@ApiResponse(responseCode = "505", description = "Error occurred", content = @Content)
	public ResponseEntity<?> deleteById(@PathVariable @Parameter(description = "The ID of the smart meter to delete.") String id) {
		try {
			if (!AuthService.HasUserCompanyRoleOrAdmin()){
				return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("You do not have enough permissions to delete Smart Meter device.");
			}
			return ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.deleteById(id));
		} catch (EntityDeletionException ex) {
			return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY)
					.body(ex.getMessage());
		} catch (Exception e) {
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("Error occured");
		}
	}

	@Operation(summary = "Update smart meter", description = "Updates the smart meter with the specified ID.")
	@PutMapping("/{id}")
	@ApiResponse(responseCode = "200", description = "Successfully updated the smart meter.")
	@ApiResponse(responseCode = "404", description = "Smart meter not found.")
	public ResponseEntity<?> updateById(@PathVariable @Parameter(description = "The ID of the smart meter to update.") String id,
									@RequestBody @Valid SmartMeterUpdateDto smartMeterUpdateDto) {
		if (!AuthService.HasUserCompanyRoleOrAdmin()){
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("You do not have enough permissions to create Smart Meter device.");
		}
		return ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.updateById(smartMeterUpdateDto, id));
	}

	@Operation(summary = "Activate smart meter", description = "Activate the smart meter with the specified ID.")
	@PutMapping("/turnOn/{id}")
	@ApiResponse(responseCode = "200", description = "Successfully activate the smart meter.")
	@ApiResponse(responseCode = "404", description = "Smart meter not found.")
	public ResponseEntity<?> turnOn(@PathVariable @Parameter(description = "The ID of the smart meter to activate.") String id) {
		if (!AuthService.HasUserHouseRoleOrAdmin()){
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("You do not have enough permissions to create Smart Meter device.");
		}
		return  ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.changeActiveState(id, true));
	}

	@Operation(summary = "Deactivate smart meter", description = "Deactivate the smart meter with the specified ID.")
	@PutMapping("/turnOff/{id}")
	@ApiResponse(responseCode = "200", description = "Successfully deactivate the smart meter.")
	@ApiResponse(responseCode = "404", description = "Smart meter not found.")
	public ResponseEntity<?> turnOff(@PathVariable @Parameter(description = "The ID of the smart meter to deactivate.") String id) {
		if (!AuthService.HasUserHouseRoleOrAdmin()){
			return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("You do not have enough permissions to create Smart Meter device.");
		}
		return  ResponseEntity.status(HttpStatus.OK).body(smartMeterFacade.changeActiveState(id, false));
	}
}
