package sklep.soap;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import jakarta.jws.WebParam;
import jakarta.jws.WebResult;
import jakarta.jws.WebService;
import jakarta.xml.ws.soap.MTOM;
import sklep.db.CustomerDAO;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.OrderDAO;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Customer;
import sklep.model.Order;
import sklep.model.Product;

@WebService
@MTOM
public class Sklep {
    // Tutaj nie ma adnotacji @WebParam ani @WebResult, więc argument w XML nazywa się <arg0>, a wynik <return>
    public String hello(String imie) {
        return "Witaj " + imie;
    }
    
    @WebResult(name="dt")
    public String ktoraGodzina() {
        return LocalDateTime.now().toString();
    }
    
    @WebResult(name="wynik")
    public double oblicz(
            @WebParam(name="liczba1") double liczba1,
            @WebParam(name="liczba2") double liczba2,
            @WebParam(name="dzialanie") String operacja) {
        return switch(operacja) {
            case "+" -> liczba1 + liczba2;
            case "-" -> liczba1 - liczba2;
            case "*" -> liczba1 * liczba2;
            case "/" -> liczba1 / liczba2;
            case "%" -> liczba1 % liczba2;
            case "^" -> Math.pow(liczba1, liczba2);
            default -> throw new IllegalArgumentException("Nieznana operacja " + operacja);
        };
    }
    
    @WebResult(name="product")
    public List<Product> wszystkieProdukty() throws DBException {
        try(DBConnection db = DBConnection.open()) {
            ProductDAO productDAO = db.productDAO();
            return productDAO.readAll();
        }
    }
    
    @WebResult(name="product")
    public List<Product> produktyWgCeny(
            @WebParam(name="min") BigDecimal min,
            @WebParam(name="max") BigDecimal max) throws DBException {
        try(DBConnection db = DBConnection.open()) {
            ProductDAO productDAO = db.productDAO();
            return productDAO.findByPrice(min, max);
        }
    }
    
    @WebResult(name="product")
    public Product jedenProdukt(@WebParam(name="id") int productId) throws DBException, RecordNotFound {
        try(DBConnection db = DBConnection.open()) {
            ProductDAO productDAO = db.productDAO();
            return productDAO.findById(productId);
        }
    }
    
    // w tej wersji metoda zwraca uzupełniony obiekt (z dodanym ID, jeśli wcześniej nie było)
    @WebResult(name="product") 
    public Product zapiszProdukt(@WebParam(name="product") Product product) throws DBException {
        try(DBConnection db = DBConnection.open()) {
            ProductDAO productDAO = db.productDAO();
            productDAO.save(product);
            db.commit();
            return product;
        }
    }
    
    @WebResult(name="customer")
    public Customer jedenKlient(@WebParam(name="email") String email) throws DBException, RecordNotFound {
        try(DBConnection db = DBConnection.open()) {
            CustomerDAO customerDAO = db.customerDAO();
            return customerDAO.findByEmail(email);
        }
    }
    
    @WebResult(name="order")
    public Order jednoZamowienia(@WebParam(name="id") int orderId) throws DBException, RecordNotFound {
        try(DBConnection db = DBConnection.open()) {
            OrderDAO orderDAO = db.orderDAO();
            return orderDAO.findById(orderId);
        }
    }
    
    @WebResult(name="bytes")
    public byte[] foto(@WebParam(name="id") int productId) throws DBException, RecordNotFound {
        return PhotoUtil.readBytes(productId);
    }
    
    public void zapiszFoto(@WebParam(name="id") int productId,
            @WebParam(name="bytes") byte[] bytes) {
        PhotoUtil.writeBytes(productId, bytes);
    }
}
