@RestResource(urlMapping='/api/products/*')
global with sharing class ProductApi {

    // GET: Recuperar productos por External_ID__c
    @HttpGet
    global static List<Product2> getProducts() {
        RestRequest req = RestContext.request;
        String externalId = req.requestURI.substringAfterLast('/');

        if (String.isNotBlank(externalId)) {
            // Recuperar producto por External_ID__c
            return [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c 
                    FROM Product2 WHERE External_ID__c = :externalId];
        } else {
            // Si no se proporciona External_ID__c, lanzar excepción
            throw new CustomException('Debe proporcionar el External_ID__c para la búsqueda.');
        }
    }

    // PATCH: Crear o actualizar un producto y establecer su precio usando solo External_ID__c
    @HttpPatch
    global static Product2 upsertProduct(
        String externalId, 
        String name, 
        String productCode, 
        String description, 
        Boolean isActive, 
        Decimal price
    ) {
        if (String.isBlank(externalId)) {
            throw new CustomException('El campo External_ID__c es obligatorio para realizar un upsert.');
        }

        if (price == null || price < 0) {
            throw new CustomException('El precio debe ser un valor positivo.');
        }

        // Crear o actualizar el producto basado en External_ID__c
        Product2 product = [SELECT Id FROM Product2 WHERE External_ID__c = :externalId LIMIT 1];

        if (product == null) {
            product = new Product2(
                External_ID__c = externalId,
                Name = name,
                ProductCode = productCode,
                Description = description,
                IsActive = isActive
            );
            insert product;
        } else {
            product.Name = name;
            product.ProductCode = productCode;
            product.Description = description;
            product.IsActive = isActive;
            update product;
        }

        // Buscar el Standard Pricebook
        List<Pricebook2> standardPricebookList = [SELECT Id FROM Pricebook2 WHERE IsStandard = true LIMIT 1];
        if (standardPricebookList.isEmpty()) {
            throw new CustomException('No se encontró el Standard Pricebook.');
        }
        Pricebook2 standardPricebook = standardPricebookList[0];

        // Verificar si ya existe un PricebookEntry para este producto
        List<PricebookEntry> existingEntries = [
            SELECT Id, UnitPrice 
            FROM PricebookEntry 
            WHERE Product2Id = :product.Id AND Pricebook2Id = :standardPricebook.Id
        ];

        if (existingEntries.isEmpty()) {
            // Crear un nuevo PricebookEntry si no existe
            PricebookEntry newEntry = new PricebookEntry(
                Pricebook2Id = standardPricebook.Id,
                Product2Id = product.Id,
                UnitPrice = price,
                IsActive = true
            );
            insert newEntry;
        } else {
            // Actualizar el PricebookEntry existente
            PricebookEntry existingEntry = existingEntries[0];
            existingEntry.UnitPrice = price;
            update existingEntry;
        }

        return product;
    }

    // DELETE: Eliminar un producto por External_ID__c
    @HttpDelete
    global static void deleteProduct() {
        RestRequest req = RestContext.request;
        String externalId = req.requestURI.substringAfterLast('/');

        if (String.isBlank(externalId)) {
            throw new CustomException('Debe proporcionar el External_ID__c para eliminar.');
        }

        Product2 productToDelete = [SELECT Id FROM Product2 WHERE External_ID__c = :externalId LIMIT 1];

        if (productToDelete == null) {
            throw new CustomException('No se encontró el producto con el External_ID__c proporcionado.');
        }

        // Eliminar cualquier PricebookEntry relacionado en el Standard Pricebook
        List<Pricebook2> standardPricebookList = [SELECT Id FROM Pricebook2 WHERE IsStandard = true LIMIT 1];
        if (!standardPricebookList.isEmpty()) {
            Pricebook2 standardPricebook = standardPricebookList[0];
            List<PricebookEntry> entriesToDelete = [
                SELECT Id 
                FROM PricebookEntry 
                WHERE Product2Id = :productToDelete.Id AND Pricebook2Id = :standardPricebook.Id
            ];
            delete entriesToDelete;
        }

        delete productToDelete;
    }

    // Clase de excepción personalizada
    global class CustomException extends Exception {}
}