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

    // GET: Recuperar productos o un producto específico por External_ID__c o por Id
    @HttpGet
    global static List<Product2> getProducts() {
        RestRequest req = RestContext.request;
        String productIdOrExternalId = req.requestURI.substringAfterLast('/');

        if (String.isNotBlank(productIdOrExternalId)) {
            // Intentar recuperar por External_ID__c si no es un Id estándar
            if (productIdOrExternalId.startsWith('a') && productIdOrExternalId.length() == 18) {
                // Recuperar por Salesforce Id estándar
                return [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c 
                        FROM Product2 WHERE Id = :productIdOrExternalId];
            } else {
                // Recuperar por External_ID__c
                return [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c 
                        FROM Product2 WHERE External_ID__c = :productIdOrExternalId];
            }
        } else {
            // Recuperar todos los productos activos
            return [SELECT Id, Name, ProductCode, Description, IsActive, External_ID__c 
                    FROM Product2 WHERE IsActive = true];
        }
    }

    // PATCH: Crear o actualizar un producto y establecer su precio
    @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 = new Product2(
            External_ID__c = externalId,
            Name = name,
            ProductCode = productCode,
            Description = description,
            IsActive = isActive
        );

        upsert product External_ID__c;

        // 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 o Id
    @HttpDelete
    global static void deleteProduct() {
        RestRequest req = RestContext.request;
        String productIdOrExternalId = req.requestURI.substringAfterLast('/');

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

        Product2 productToDelete;

        if (productIdOrExternalId.startsWith('a') && productIdOrExternalId.length() == 18) {
            // Buscar por Id estándar
            productToDelete = [SELECT Id FROM Product2 WHERE Id = :productIdOrExternalId LIMIT 1];
        } else {
            // Buscar por External_ID__c
            productToDelete = [SELECT Id FROM Product2 WHERE External_ID__c = :productIdOrExternalId LIMIT 1];
        }

        // 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 {}
}