package pedidos.pedidos.core.producto;

import org.springframework.beans.factory.annotation.Autowired;
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.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.lang.reflect.Field;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.persistence.ManyToOne;

@RestController
@RequestMapping("api/producto")
@CrossOrigin({"*"})
public class ProductoController {
    @Autowired ProductoService productoService;

    @GetMapping("/")
    public List<Producto> findAll(){
        return productoService.findAll();
    }

    @GetMapping("/{id}/")
    public Producto findById(@PathVariable long id){
        return productoService.findById(id);
    }

    @PostMapping("/")
    public Producto save(@RequestBody Producto entity){
        return productoService.save(entity);
    }

    @PutMapping("/{id}/")
    public Producto update(@RequestBody Producto entity){
        return productoService.save(entity);
    }

    @DeleteMapping("/{id}/")
    public void deleteById(@PathVariable long id){
        productoService.deleteById(id);
    }

    @PatchMapping("/{id}/")
    public Producto partialUpdate(@PathVariable long id, @RequestBody Map<String, Object> fields){

        Producto entity = findById(id);

        // itera sobre los campos que se desean actualizar
        for (Map.Entry<String, Object> field : fields.entrySet()) {
            String fieldName = field.getKey();
            Object fieldValue = null;
            if (fieldName.equals("precio")){
                fieldValue= new BigDecimal (field.getValue().toString());
            }else if (fieldName.equals("creado")){
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
                fieldValue = LocalDateTime.parse(field.getValue().toString(),formatter);
            }else {
                fieldValue =field.getValue();
            }

            // utiliza reflection para establecer el valor del campo en la entidad
            try {
                ObjectMapper mapper = new ObjectMapper();
                mapper.registerModule(new JavaTimeModule());
                //Field campoEntidad = Producto.class.getDeclaredField(fieldName);
                java.lang.reflect.Field campoEntidad = org.springframework.util.ReflectionUtils.findField(Producto.class, fieldName);
                campoEntidad.setAccessible(true);

                

                if (campoEntidad.isAnnotationPresent(ManyToOne.class)) {
                    //java.util.LinkedHashMap<String, Long> keyValue = mapper.convertValue(fieldValue, new TypeReference<java.util.LinkedHashMap<String, Long>>(){});
                    //Object relatedEntity = entidadService.findById(keyValue.get("id"));
                    //campoEntidad.set(entity, relatedEntity);
                }else{
                    //campoEntidad.set(entity, fieldValue);
                    campoEntidad.set(entity, mapper.convertValue(fieldValue, campoEntidad.getType()));
                }

                
            } catch ( IllegalAccessException ex) {
                // maneja la excepción si ocurre algún error al acceder al campo
            }
        }
        return update(entity);
    }
}