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

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.device.DeviceDto;
import cz.muni.fi.pa165.model.dto.house.HouseCreateDto;
import cz.muni.fi.pa165.model.dto.house.HouseDto;
import cz.muni.fi.pa165.model.dto.house.HouseUpdateDto;
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.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.CrossOrigin;
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.*;

import java.util.List;

@RestController
@RequestMapping("/api/house")
@Tag(name = "House", description = "House API")

public class HouseController {

  private final HouseFacade houseFacade;

  @Autowired
  public HouseController(HouseFacade houseFacade) {
	  this.houseFacade = houseFacade;
  }

  @Operation(summary = "Find all houses with pagination or without", responses = {
          @ApiResponse(responseCode = "200", description = "List of houses", content = {
                  @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Result.class))
          })
  })
  @GetMapping
  public Result<HouseDto> 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 houseFacade.findAllPageable(pageWithElements);
  }

  @Operation(
          summary = "Get a house by ID",
          description = "Retrieve a house with the specified ID."
  )
  @ApiResponse(responseCode = "200", description = "House found", content = {
          @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = HouseDto.class))
  })
  @ApiResponse(responseCode = "404", description = "House not found", content = @Content)
  @GetMapping("/{id}")
  public HouseDto findById(@PathVariable String id) {
	  return houseFacade.findById(id);
  }

  @Operation(
          summary = "Create a new house",
          description = "Create a new house with the specified details."
  )
  @ApiResponse(responseCode = "201", description = "The newly created house",
          content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                  schema = @Schema(implementation = HouseDto.class)))
  @PostMapping
  public HouseDto create(@RequestBody HouseCreateDto houseCreateDtoDto) {
	  return houseFacade.create(houseCreateDtoDto);
  }

  @Operation(
          summary = "Update specific house",
          description = "Updates the house with the specified id."
  )
  @ApiResponse(responseCode = "201", description = "The updated house",
          content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                  schema = @Schema(implementation = HouseDto.class)))
  @ApiResponse(responseCode = "404", description = "House not found", content = @Content)
  @PutMapping("/{id}")
  public HouseDto updateById(@RequestBody HouseUpdateDto houseUpdateDto, @PathVariable String id) {
	  return houseFacade.updateById(houseUpdateDto, id);
  }

  @Operation(
          summary = "Deletes specific house",
          description = "Deletes the house with the specified id."
  )
  @ApiResponse(responseCode = "200", description = "The deleted house",
          content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                  schema = @Schema(implementation = HouseDto.class)))
  @ApiResponse(responseCode = "404", description = "House not found", content = @Content)
  @ApiResponse(responseCode = "422", description = "House could not be deleted", content = @Content)
  @ApiResponse(responseCode = "505", description = "Error occurred", content = @Content)
  @DeleteMapping("/{id}")
  public ResponseEntity<?> deleteById(@PathVariable String id) {
    try {
      return ResponseEntity.status(HttpStatus.OK).body(houseFacade.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 occurred");
    }
  }
}
