/*
 * File: src/main/java/purchase/controller/PurchaseController.java
 * Description: This controller handles all API requests for managing Purchases and Purchase Items.
 * It provides endpoints to create, retrieve, update, and delete purchases, as well as fetching product
 * and GRN details from external services. This class also includes Swagger documentation for each API endpoint.
*/

package com.nebula.erp.purchase.controller;

import com.nebula.erp.purchase.model.Purchase;
import com.nebula.erp.purchase.model.PurchaseItem;
import com.nebula.erp.purchase.model.Supplier;
import com.nebula.erp.purchase.requestmodel.PurchaseRequest;
import com.nebula.erp.purchase.service.PurchaseService;
import com.nebula.erp.purchase.service.GRNService;
import com.nebula.erp.purchase.service.SupplierService;
import com.nebula.erp.purchase.utility.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import com.nebula.erp.purchase.document.PurchaseSwagger;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/purchases")
@Tag(name = "Purchase APIs", description = "API for managing Purchase and Purchase Items")
@PurchaseSwagger.GlobalErrorResponse
public class PurchaseController {

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private GRNService grnService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${product.api}")
    private String productApiUrl;

    @Value("${grn.api}")
    private String grnApiUrl;

    @Value("${organization.api}")
    private String organizationAPI;

    @Autowired
    private JwtRequestUtils jwtRequestUtils;

    @Autowired
    private PermissionHelper permissionHelper;

    @Autowired
    private CreateLogger createLogger;

    private static final String path = "/purchases";

    @PurchaseSwagger.CreatePurchaseOperation
    @PostMapping
    public ResponseEntity<ApiResponseStructure<Purchase>> createPurchase(@RequestBody PurchaseRequest purchaseRequest) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("create-purchase")) {
                createLogger.createLogger("error", path, "POST", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Purchase createdPurchase = purchaseService.createPurchase(purchaseRequest);
            ApiResponseStructure<Purchase> response = new ApiResponseStructure<>("success", HttpStatus.CREATED.value(), "Purchase created successfully", createdPurchase);
            createLogger.createLogger("application", path, "POST", "Purchase created successfully", "");
            return ResponseEntity.status(HttpStatus.CREATED).body(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "POST", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @PurchaseSwagger.GetPurchaseByIdOperation
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponseStructure<Map<String, Object>>> getPurchaseById(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-purchase")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            String tenantName = jwtRequestUtils.getTenantName();

            Optional<Purchase> purchaseOptional = purchaseService.getPurchase(id);
            if (purchaseOptional.isPresent()) {
                Purchase purchaseData = purchaseOptional.get();

                // Check if the tenant name matches
                if (!purchaseData.getTenant().equals(tenantName)) {
                    createLogger.createLogger("error", path, "GET", "Unauthorized to view this purchase; tenant mismatch", "validation");
                    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Unauthorized to view this purchase; tenant mismatch", null));
                }

                Map<String, Object> data = preparePurchaseResponse(purchaseData);

                // Columns for purchase_items
                Map<String, String> purchaseItemsColumns = new LinkedHashMap<>();
                purchaseItemsColumns.put("id", "ID");
                purchaseItemsColumns.put("product_id", "PRODUCT ID");
                purchaseItemsColumns.put("product_name", "PRODUCT NAME");
                purchaseItemsColumns.put("brand_id", "BRAND ID");
                purchaseItemsColumns.put("brand_name", "BRAND NAME");
                purchaseItemsColumns.put("category_id", "CATEGORY ID");
                purchaseItemsColumns.put("category_name", "CATEGORY NAME");
                purchaseItemsColumns.put("quantity", "QUANTITY");
                purchaseItemsColumns.put("hsn_code", "HSN CODE");
                purchaseItemsColumns.put("created_by", "CREATED BY");
                purchaseItemsColumns.put("created_at", "CREATED AT");
                data.put("columns", purchaseItemsColumns);

                ApiResponseStructure<Map<String, Object>> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchase retrieved successfully", data);
                createLogger.createLogger("application", path, "GET", "Purchase retrieved successfully", "");
                return ResponseEntity.ok(response);
            } else {
                createLogger.createLogger("error", path, "GET", "Purchase not found", "runtime");
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponseStructure<>("error", HttpStatus.NOT_FOUND.value(), "Purchase not found", null));
            }
        } catch (Exception e) {
            createLogger.createLogger("error", path, "GET", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    // Get purchases count
    @GetMapping("/count")
    public ResponseEntity<ApiResponseStructure<Integer>> getPurchasesCount(
            @RequestParam(value = "tenant", required = true) String tenant_name) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-sales")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }
            Integer purchasesCount = purchaseService.getPurchasesCount(tenant_name);
            ApiResponseStructure<Integer> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchases count retrieved successfully", purchasesCount);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @PurchaseSwagger.GetAllPurchasesOperation
    @GetMapping
    public ResponseEntity<ApiResponseStructure<Map<String, Object>>> getAllPurchases(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "grn", required = false) Boolean grn,
            @RequestParam(value = "search", required = false) String search){
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-purchase")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Page<Purchase> purchasePage = purchaseService.getAllPurchases(page, size, grn ,search);

            // Prepare pagination data
            Map<String, Object> pagination = new LinkedHashMap<>();
            pagination.put("current_page", purchasePage.getNumber() + 1);
            pagination.put("per_page", purchasePage.getSize());
            pagination.put("total", purchasePage.getTotalElements());
            pagination.put("last_page", purchasePage.getTotalPages());
            pagination.put("next_page_url", purchasePage.hasNext() ? "/api/purchases?page=" + (page + 1) + "&size=" + size : null);
            pagination.put("prev_page_url", purchasePage.hasPrevious() ? "/api/purchases?page=" + (page - 1) + "&size=" + size : null);

            // Define colummns for purchase
            Map<String, String> columns = new LinkedHashMap<>();
            columns.put("id", "ID");
            columns.put("supplier_id", "SUPPLIER ID");
            columns.put("supplier_name", "SUPPLIER NAME");
            columns.put("date", "DATE");
            columns.put("status", "STATUS");
            columns.put("remarks", "REMARKS");
            columns.put("created_by", "CREATED BY");
            columns.put("created_at", "CREATED AT");

            // Prepare data for response
            List<Map<String, Object>> purchaseItems = purchasePage.getContent().stream()
                    .map(this::preparePurchaseResponse)
                    .filter(Objects::nonNull)  // Exclude prescriptions with no items
                    .collect(Collectors.toList());

            // Prepare data for response
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("pagination", pagination);
            data.put("items", purchaseItems);
            data.put("columns", columns);

            // Create and return ApiResponseStructure object
            ApiResponseStructure<Map<String, Object>> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchases retrieved successfully", data);
            createLogger.createLogger("application", path, "GET", "Purchases retrieved successfully", "");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "GET", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @PurchaseSwagger.UpdatePurchaseOperation
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponseStructure<Purchase>> updatePurchase(@PathVariable Long id, @RequestBody PurchaseRequest purchaseRequest) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("update-purchase")) {
                createLogger.createLogger("error", path, "PUT", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Purchase updatedPurchase = purchaseService.updatePurchase(id, purchaseRequest);
            ApiResponseStructure<Purchase> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchase updated successfully", updatedPurchase);
            createLogger.createLogger("application", path, "PUT", "Purchase updated successfully", "");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "PUT", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @PurchaseSwagger.DeletePurchaseOperation
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponseStructure<Void>> deletePurchase(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("delete-purchase")) {
                createLogger.createLogger("error", path, "DELETE", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            // Check if the purchase exists
            Optional<Purchase> purchaseOptional = purchaseService.getPurchase(id);
            if (!purchaseOptional.isPresent()) {
                createLogger.createLogger("error", path, "DELETE", "Purchase not found", "not found");
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponseStructure<>("error", HttpStatus.NOT_FOUND.value(), "Purchase not found", null));
            }

            // Extract the Authorization token from the request
            HttpHeaders authHeader = jwtRequestUtils.getAuthorizationHeaders();
            HttpEntity<Void> entity = new HttpEntity<>(authHeader);

            // Check if the purchase exists in GRN by purchase_order_id
            String grnUrl = grnApiUrl + id;
            ResponseEntity<Map> grnApiResponse = restTemplate.exchange(grnUrl, HttpMethod.GET, entity, Map.class);

            // If GRN exists for the purchase_order_id, throw error
            if (grnApiResponse.getBody() != null && grnApiResponse.getBody().containsKey("data")) {
                Map<String, Object> grnData = (Map<String, Object>) grnApiResponse.getBody().get("data");

                // Extract only 'items' field from GRN response
                List<Map<String, Object>> grnItems = (List<Map<String, Object>>) grnData.get("items");

                if (grnItems != null && !grnItems.isEmpty()) {
                    createLogger.createLogger("error", path, "DELETE", "Unable to delete. Purchase is associated to a GRN.", "bad request");
                    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), "Unable to delete. Purchase is associated to a GRN.", null));
                }
            }

            purchaseService.deletePurchase(id);
            ApiResponseStructure<Void> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchase deleted successfully", null);
            createLogger.createLogger("application", path, "DELETE", "Purchase deleted successfully", "");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "DELETE", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @PurchaseSwagger.ExportPurchaseByIdOperation
    @GetMapping("/export/{id}")
    public ResponseEntity<ApiResponseStructure<Map<String, Object>>> exportById(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-purchase")) {
                createLogger.createLogger("error", path, "GET", "Forbidden: You do not have the required permission. Please contact the administration.", "validation");
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }
            String tenantName = jwtRequestUtils.getTenantName();

            Optional<Purchase> purchaseOptional = purchaseService.getPurchase(id);
            if (purchaseOptional.isPresent()) {
                Purchase purchaseData = purchaseOptional.get();

                // Check if the tenant name matches
                if (!purchaseData.getTenant().equals(tenantName)) {
                    createLogger.createLogger("error", path, "GET", "Unauthorized to view this purchase; tenant mismatch", "validation");
                    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ApiResponseStructure<>("error", HttpStatus.FORBIDDEN.value(), "Unauthorized to view this purchase; tenant mismatch", null));
                }

                Map<String, Object> data = prepareExportResponse(purchaseData);

                // Columns for purchase_items
                Map<String, String> purchaseItemsColumns = new LinkedHashMap<>();
                purchaseItemsColumns.put("id", "ID");
                purchaseItemsColumns.put("product_id", "PRODUCT ID");
                purchaseItemsColumns.put("product_name", "PRODUCT NAME");
                purchaseItemsColumns.put("brand_id", "BRAND ID");
                purchaseItemsColumns.put("brand_name", "BRAND NAME");
                purchaseItemsColumns.put("category_id", "CATEGORY ID");
                purchaseItemsColumns.put("category_name", "CATEGORY NAME");
                purchaseItemsColumns.put("quantity", "QUANTITY");
                purchaseItemsColumns.put("hsn_code", "HSN CODE");
                purchaseItemsColumns.put("created_by", "CREATED BY");
                purchaseItemsColumns.put("created_at", "CREATED AT");
                data.put("columns", purchaseItemsColumns);

                ApiResponseStructure<Map<String, Object>> response = new ApiResponseStructure<>("success", HttpStatus.OK.value(), "Purchase retrieved successfully", data);
                createLogger.createLogger("application", path, "GET", "Purchase retrieved successfully", "");
                return ResponseEntity.ok(response);
            } else {
                createLogger.createLogger("error", path, "GET", "Purchase not found", "runtime");
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponseStructure<>("error", HttpStatus.NOT_FOUND.value(), "Purchase not found", null));
            }
        } catch (Exception e) {
            createLogger.createLogger("error", path, "GET", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponseStructure<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    // Helper method to prepare response data for a purchase
    private Map<String, Object> preparePurchaseResponse(Purchase purchaseData) {
        // Extract Authorization headers from the request
        HttpHeaders headers = jwtRequestUtils.getAuthorizationHeaders();

        // Create an HttpEntity with the extracted headers
        HttpEntity<String> entity = new HttpEntity<>(headers);
        Map<String, Object> data = new LinkedHashMap<>();

        // Map purchase fields to data
        data.put("id", purchaseData.getId());
        data.put("supplier_id", purchaseData.getSupplier().getId());
        data.put("supplier_name", purchaseData.getSupplier().getSupplier_name());
        data.put("date", String.valueOf(purchaseData.getDate()));
        data.put("status", purchaseData.getStatus());
        data.put("remarks", purchaseData.getRemarks());
        data.put("created_by", purchaseData.getCreated_by());
        data.put("created_at", String.valueOf(purchaseData.getCreated_at()));

        // Map purchase items
        List<Map<String, Object>> purchaseItemsData = new ArrayList<>();
        for (PurchaseItem item : purchaseData.getPurchase_items()) {
            Map<String, Object> itemData = new LinkedHashMap<>();
            itemData.put("id", item.getId());
            itemData.put("product_id", item.getProduct_id());

            // Execute the request with headers
            ResponseEntity<Map> productApiResponse = restTemplate.exchange(productApiUrl  + item.getProduct_id(), HttpMethod.GET, entity, Map.class);

            // Extract product items from the product API response
            Map<String, Object> productData = productApiResponse.getBody();
            List<Map<String, Object>> items = (List<Map<String, Object>>) ((Map<String, Object>) productData.get("data")).get("items");

            if (items != null && !items.isEmpty()) {
                // Extract the first product's details
                Map<String, Object> product = items.get(0);

                // Add brand and category details if available
                itemData.put("product_name", product.get("name"));
                itemData.put("brand_id", product.get("brand_id"));
                itemData.put("brand_name", product.get("brand_name"));
                itemData.put("category_id", product.get("category_id"));
                itemData.put("category_name", product.get("category_name"));
                itemData.put("tax_id", product.get("tax_id"));
                itemData.put("tax_type", product.get("tax_type"));
                itemData.put("tax_rate", product.get("tax_rate"));
                itemData.put("hsn_code", product.get("hsn_code"));
            }
            itemData.put("quantity", item.getQuantity());
            itemData.put("is_grn", item.getIs_grn());
            itemData.put("created_by", item.getCreated_by());
            itemData.put("created_at", String.valueOf(item.getCreated_at()));
            purchaseItemsData.add(itemData);
        }

        // Add purchase items to data
        data.put("purchase_items", purchaseItemsData);

        return data;
    }

    private Map<String, Object> prepareExportResponse(Purchase purchaseData) {
        // Extract Authorization headers from the request
        HttpHeaders headers = jwtRequestUtils.getAuthorizationHeaders();

        // Create an HttpEntity with the extracted headers
        HttpEntity<String> entity = new HttpEntity<>(headers);
        Map<String, Object> data = new LinkedHashMap<>();

        // Map purchase fields to data
        data.put("id", purchaseData.getId());
        data.put("supplier_id", purchaseData.getSupplier().getId());
        data.put("supplier_name", purchaseData.getSupplier().getSupplier_name());
        data.put("date", String.valueOf(purchaseData.getDate()));
        data.put("status", purchaseData.getStatus());
        data.put("remarks", purchaseData.getRemarks());
        data.put("created_by", purchaseData.getCreated_by());
        data.put("created_at", String.valueOf(purchaseData.getCreated_at()));

        // Initialize total tax amount
        final double[] totalTaxAmount = {0};
        final double[] totalPriceAmount = {0};

        // Map purchase items
        List<Map<String, Object>> purchaseItemsData = new ArrayList<>();
        for (PurchaseItem item : purchaseData.getPurchase_items()) {
            Map<String, Object> itemData = new LinkedHashMap<>();
            itemData.put("id", item.getId());
            itemData.put("product_id", item.getProduct_id());

            // Execute the request with headers
            ResponseEntity<Map> productApiResponse = restTemplate.exchange(productApiUrl  + item.getProduct_id(), HttpMethod.GET, entity, Map.class);

            // Extract product items from the product API response
            Map<String, Object> productData = productApiResponse.getBody();
            List<Map<String, Object>> items = (List<Map<String, Object>>) ((Map<String, Object>) productData.get("data")).get("items");

            if (items != null && !items.isEmpty()) {
                // Extract the first product's details
                Map<String, Object> product = items.get(0);

                // Add brand and category details if available
                itemData.put("product_name", product.get("name"));
                itemData.put("brand_id", product.get("brand_id"));
                itemData.put("brand_name", product.get("brand_name"));
                itemData.put("category_id", product.get("category_id"));
                itemData.put("category_name", product.get("category_name"));
                itemData.put("tax_id", product.get("tax_id"));
                itemData.put("tax_type", product.get("tax_type"));
                itemData.put("tax_rate", product.get("tax_rate"));
                itemData.put("hsn_code", product.get("hsn_code"));
                itemData.put("purchase_price", product.get("purchase_price"));
                double unitPrice = (double) product.get("purchase_price");
                double totalPrice = unitPrice * item.getQuantity();
                double taxAmount = totalPrice * (double) product.get("tax_rate") / 100;
                itemData.put("total_price", MoneyUtils.truncateToTwoDecimals(totalPrice + taxAmount));
                itemData.put("tax_amount", MoneyUtils.truncateToTwoDecimals(taxAmount));
                // Add to the total tax amount
                totalTaxAmount[0] = totalTaxAmount[0] + taxAmount;
                totalPriceAmount[0] = totalPriceAmount[0] + totalPrice;
            }
            itemData.put("quantity", item.getQuantity());
            itemData.put("created_by", item.getCreated_by());
            itemData.put("created_at", String.valueOf(item.getCreated_at()));
            purchaseItemsData.add(itemData);
        }

        data.put("total_tax_amount", totalTaxAmount[0]);
        data.put("total_amount", totalPriceAmount[0]);
        // Add purchase items to data
        data.put("purchase_items", purchaseItemsData);

        try {
            Map<String, Object> organizationData = restTemplate.exchange(organizationAPI, HttpMethod.GET, entity, Map.class).getBody();
            Map<String, Object> organizationItem = (Map<String, Object>) organizationData.get("data");

            if (organizationItem != null) {
                data.put("organization", organizationItem);
            }
        } catch (HttpClientErrorException | HttpServerErrorException ex) {
            throw ex;
        }

        data.put("supplier", purchaseData.getSupplier());

        return data;
    }

}