package com.nebula.erp.product.controller;

import com.nebula.erp.product.document.ProductSwagger;
import com.nebula.erp.product.model.Image;
import com.nebula.erp.product.utility.ApiResponse;
import com.nebula.erp.product.model.Product;
import com.nebula.erp.product.requestmodel.ProductRequest;
import com.nebula.erp.product.service.ProductService;
import com.nebula.erp.product.utility.CreateLogger;
import com.nebula.erp.product.utility.JwtRequestUtils;
import com.nebula.erp.product.utility.PermissionHelper;
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.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/products")
@Tag(name = "Product APIs", description = "Endpoints for managing products")
@ProductSwagger.GlobalErrorResponse
public class ProductController {
    @Autowired
    private ProductService productService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${users.api}")
    private String userApiUrl;

    @Value("${images.url}")
    private String imagesUrl;

    @Value("${image.storage.location}")
    private String imageStorageLocation;

    @Autowired
    private JwtRequestUtils jwtRequestUtils;

    @Autowired
    private PermissionHelper permissionHelper;

    @Autowired
    private CreateLogger createLogger;

    private static final String path = "/products";

    public String fetchUserDetails(String userId) {
        HttpHeaders headers = jwtRequestUtils.getAuthorizationHeaders();

        // Create HttpEntity with headers
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);

        try {
            String create_by = "";
            ResponseEntity<Map> response = restTemplate.exchange(userApiUrl + userId, HttpMethod.GET, requestEntity, Map.class);
            Map<String, Object> userDetails = response.getBody();

            // Extract user information from the response structure
            if (userDetails != null && "Success".equals(userDetails.get("status"))) {
                Map<String, Object> userItem = (Map<String, Object>) userDetails.get("data");
                create_by = userItem.get("firstName") + " " + userItem.get("lastName");
            } else {
                throw new IllegalArgumentException("Error getting user details!!");
            }
            return create_by;
        } catch (Exception e) {
            return "";
        }
    }

    // Get products count
    @GetMapping("/count")
    public ResponseEntity<ApiResponse<Integer>> getProductsCount(
            @RequestParam(value = "tenant", required = true) String tenant_name) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }
            Integer productsCount = productService.getProductsCount(tenant_name);
            ApiResponse<Integer> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Products count retrieved successfully", productsCount);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @ProductSwagger.GetAllProductsOperation
    @GetMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAllProducts(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "product_id", required = false) Integer productId,
            @RequestParam(value = "brand_id", required = false) Integer brandId,
            @RequestParam(value = "category_id", required = false) Integer categoryId,
        @RequestParam(value = "search", required = false) String search) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Page<Product> productPage = productService.getAllProducts(page, size, name, productId, brandId, categoryId,search);

            // Convert each Product entity to ProductResponse
            List<Map<String, Object>> products = productPage.getContent().stream()
                    .map(this::prepareProductResponse)
                    .collect(Collectors.toList());

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

            // Columns information
            Map<String, String> columns = new LinkedHashMap<>();
            columns.put("id", "PRODUCT ID");
            columns.put("code", "PRODUCT CODE");
            columns.put("name", "PRODUCT NAME");
            columns.put("brand_id", "BRAND ID");
            columns.put("brand_name", "BRAND NAME");
            columns.put("category_id", "CATEGORY ID");
            columns.put("category_name", "CATEGORY NAME");
            columns.put("hsn_code", "HSN CODE");
            columns.put("created_at", "CREATED AT");
            columns.put("updated_at", "UPDATED AT");

            // Data including pagination and product list
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("pagination", pagination);
            data.put("items", products); // Use ProductResponse DTOs
            data.put("columns", columns);

            // API response
            ApiResponse<Map<String, Object>> response = new ApiResponse<>("Success", HttpStatus.OK.value(), "Medications retrieved successfully.", data);
            createLogger.createLogger("application", path, "GET", "Medications 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 ApiResponse<>("Error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @ProductSwagger.CreateProductOperation
    @PostMapping
    public ResponseEntity<ApiResponse<Product>> createProduct(
            @ModelAttribute ProductRequest productRequest,
            @RequestParam(value = "images", required = false) List<MultipartFile> productImages) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("create-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Product product = productService.createProductWithImages(productRequest, productImages);
            ApiResponse<Product> apiResponse = new ApiResponse<>("success", HttpStatus.OK.value(), "Medication created successfully", product);
            createLogger.createLogger("application", path, "POST", "Medication created successfully", "");
            return ResponseEntity.ok(apiResponse);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "POST", e.getMessage(), "runtime");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponse<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @ProductSwagger.GetProductOperation
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getProduct(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("view-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            Optional<Product> productOptional = productService.getProduct(id);
            if (productOptional.isPresent()) {
                Product productData = productOptional.get();

                // Create a map to hold prescription data
                Map<String, Object> data = prepareProductResponse(productData);

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

    @ProductSwagger.UpdateProductOperation
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Product>> updateProduct(@PathVariable Long id, @ModelAttribute ProductRequest productRequest, @RequestParam(value = "images", required = false) List<MultipartFile> productImages) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("update-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            // Update the product and handle image upload
            Product updatedProduct = productService.updateProduct(id, productRequest, productImages);

            // Create and return a successful response
            ApiResponse<Product> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Medication updated successfully", updatedProduct);
            createLogger.createLogger("application", path, "PUT", "Medication 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 ApiResponse<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    private Map<String, Object> prepareProductResponse(Product productData) {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("id", productData.getId());
        data.put("code", productData.getCode());
        data.put("name", productData.getName());
        data.put("description", productData.getDescription());
        data.put("form", productData.getForm());
        data.put("dosage", productData.getDosage());
        data.put("unit_of_measurement", productData.getUnit_of_measurement());
        data.put("quantity", productData.getQuantity());
        data.put("purchase_price", productData.getPurchase_price());
        data.put("selling_price", productData.getSelling_price());
        data.put("mrp", productData.getMrp());
        data.put("min_stock", productData.getMin_stock());
        data.put("hsn_code", productData.getHsn_code());

        // Tax
        if (productData.getTax() != null) {
            data.put("tax_id", productData.getTax().getId());
            data.put("tax_type", productData.getTax().getType());
            data.put("tax_rate", productData.getTax().getRate());
        }
        // Brand
        if (productData.getBrand() != null) {
            data.put("brand_id", productData.getBrand().getId());
            data.put("brand_name", productData.getBrand().getName());
        }

        // Category
        if (productData.getCategory() != null) {
            data.put("category_id", productData.getCategory().getId());
            data.put("category_name", productData.getCategory().getName());
        }

        // Prepare images if available
        List<Map<String, Object>> imageList = new ArrayList<>();
        if (productData.getImages() != null && !productData.getImages().isEmpty()) {
            for (Image image : productData.getImages()) {
                Map<String, Object> imageData = new LinkedHashMap<>();
                imageData.put("id", image.getId());
                if("local".equalsIgnoreCase(imageStorageLocation)) {
                    imageData.put("url", imagesUrl + "/"  + image.getImage().substring(image.getImage().indexOf("uploads")));
                } else if("aws".equalsIgnoreCase(imageStorageLocation)) {
                    imageData.put("url", image.getImage());
                } else {
                    imageData.put("url", image.getImage());
                }
                imageList.add(imageData);
            }
        }
        // Add the images list to the response if not empty
        data.put("images", imageList);
        data.put("remarks", productData.getRemarks());
        data.put("created_by", productData.getCreated_by());
        data.put("created_at", String.valueOf(productData.getCreated_at()));

        return data;
    }
}