package com.nebula.erp.product.controller;

import com.nebula.erp.product.document.BrandSwagger;
import com.nebula.erp.product.model.Brand;
import com.nebula.erp.product.requestmodel.BrandRequest;
import com.nebula.erp.product.service.BrandService;
import com.nebula.erp.product.utility.ApiResponse;
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/brands")
@Tag(name = "Brand APIs", description = "Endpoints for managing brands")
@BrandSwagger.GlobalErrorResponse
public class BrandController {

    @Autowired
    private BrandService brandService;

    @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 = "/brands";

    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 "";
        }
    }

    @BrandSwagger.CreateBrandOperation
    @PostMapping
    public ResponseEntity<ApiResponse<Brand>> createBrand(
            @ModelAttribute BrandRequest brandRequest,
            @RequestParam(value = "image", required = false) MultipartFile brandImage) {

        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));
            }

            // Call the service with the optional image file
            Brand newBrand = brandService.createBrand(brandRequest, brandImage);
            ApiResponse<Brand> apiResponse = new ApiResponse<>("success", HttpStatus.CREATED.value(), "Brand created successfully", newBrand);
            createLogger.createLogger("application", path, "POST", "Brand created successfully", "");
            return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
        } catch (Exception e) {
            createLogger.createLogger("error", path, "POST", e.getMessage(), "runtime");
            // Generic exception handling in the controller
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiResponse<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    @BrandSwagger.GetAllBrandsOperation
    @GetMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAllBrands(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @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<Brand> brandPage = brandService.getAllBrand(page, size,search);

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

            Map<String, String> columns = new LinkedHashMap<>();
            columns.put("id", "ID");
            columns.put("name", "NAME");
            columns.put("description", "DESCRIPTION");
            columns.put("image", "IMAGE");
            columns.put("created_by", "CREATED BY");
            columns.put("created_at", "CREATED AT");
            columns.put("updated_at", "UPDATED AT");

            List<Map<String, Object>> brandResponses = brandPage.getContent().stream()
                    .map(this::prepareBrandResponse)
                    .collect(Collectors.toList());

            Map<String, Object> data = new LinkedHashMap<>();
            data.put("pagination", pagination);
            data.put("items", brandResponses);
            data.put("columns", columns);

            ApiResponse<Map<String, Object>> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Brands retrieved successfully", data);
            createLogger.createLogger("application", path, "GET", "Brands 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));
        }
    }

    @BrandSwagger.GetBrandByIdOperation
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getBrandById(@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<Brand> brandOptional = brandService.getBrand(id);
            if (brandOptional.isPresent()) {
                Brand brandData = brandOptional.get();

                // Create a map to hold data
                Map<String, Object> data = prepareBrandResponse(brandData);

                // Create response structure
                ApiResponse<Map<String, Object>> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Brand retrieved successfully", data);
                createLogger.createLogger("application", path, "GET", "Brand retrieved successfully", "");
                return ResponseEntity.ok(response);
            } else {
                createLogger.createLogger("error", path, "GET", "Brand not found", "runtime");
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiResponse<>("error", HttpStatus.NOT_FOUND.value(), "Brand 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));
        }
    }

    @BrandSwagger.UpdateBrandOperation
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Brand>> updateBrand(@PathVariable Long id, @ModelAttribute BrandRequest brandRequest, @RequestParam(value = "image", required = false) Object brandImage) {
        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));
            }

            Brand updatedBrand = brandService.updateBrand(id, brandRequest, brandImage);
            ApiResponse<Brand> apiResponse = new ApiResponse<>("success", HttpStatus.OK.value(), "Brand updated successfully", updatedBrand);
            createLogger.createLogger("application", path, "PUT", "Brand updated successfully", "");
            return ResponseEntity.ok(apiResponse);
        } 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));
        }
    }

    @BrandSwagger.DeleteBrandOperation
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteBrand(@PathVariable Long id) {
        try {
            // Check user permissions
            if (!permissionHelper.hasPermission("delete-product")) {
                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 ApiResponse<>("error", HttpStatus.FORBIDDEN.value(), "Forbidden: You do not have the required permission. Please contact the administration.", null));
            }

            brandService.deleteBrand(id);
            ApiResponse<Void> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Brand deleted successfully", null);
            createLogger.createLogger("application", path, "DELETE", "Brand 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 ApiResponse<>("error", HttpStatus.BAD_REQUEST.value(), e.getMessage(), null));
        }
    }

    private Map<String, Object> prepareBrandResponse(Brand brandData) {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("id", brandData.getId());
        data.put("name", brandData.getName());
        data.put("description", brandData.getDescription());
        if("local".equalsIgnoreCase(imageStorageLocation)) {
            if (brandData.getImage() != null && !brandData.getImage().isEmpty()) {
                data.put("image", imagesUrl + "/" + brandData.getImage().substring(brandData.getImage().indexOf("uploads")));
            } else {
                data.put("image", brandData.getImage());
            }
        } else if("aws".equalsIgnoreCase(imageStorageLocation)) {
            data.put("image", brandData.getImage());
        } else {
            data.put("image", brandData.getImage());
        }
        data.put("created_by", brandData.getCreated_by());
        data.put("created_at", String.valueOf(brandData.getCreated_at()));

        return data;
    }
}