package com.nebula.erp.product.controller;

import com.nebula.erp.product.document.CouponSwagger;
import com.nebula.erp.product.model.Coupon;
import com.nebula.erp.product.requestmodel.CouponRequest;
import com.nebula.erp.product.service.CouponService;
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 jakarta.validation.Valid;
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 java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/coupons")
@Tag(name = "Coupon APIs", description = "Endpoints for managing coupons")
@CouponSwagger.GlobalErrorResponse
public class CouponController {

    @Autowired
    private CouponService couponService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private JwtRequestUtils jwtRequestUtils;

    @Autowired
    private PermissionHelper permissionHelper;

    @Autowired
    private CreateLogger createLogger;

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

    private static final String path = "/coupons";

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

    @CouponSwagger.GetAllCouponsOperation
    @GetMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> getAllCoupons(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "coupon_code", required = false) String coupon_code,
            @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<Coupon> couponsPage = couponService.getAllCoupons(page, size, coupon_code,search);

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

            Map<String, String> columns = new LinkedHashMap<>();
            columns.put("id", "ID");
            columns.put("name", "NAME");
            columns.put("code", "CODE");
            columns.put("start_date", "START DATE");
            columns.put("end_date", "END DATE");
            columns.put("percentage", "PERCENTAGE");
            columns.put("created_by", "CREATED BY");
            columns.put("created_at", "CREATED AT");

            List<Map<String, Object>> couponResponses = couponsPage.getContent().stream()
                    .map(this::prepareCouponResponse)
                    .collect(Collectors.toList());

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

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

    @CouponSwagger.CreateCouponOperation
    @PostMapping
    public ResponseEntity<ApiResponse<Coupon>> createCoupon(@Valid @RequestBody CouponRequest couponRequest) {
        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));
            }

            Coupon newCoupon = couponService.createCoupon(couponRequest);
            ApiResponse<Coupon> apiResponse = new ApiResponse<>("success", HttpStatus.CREATED.value(), "Coupon created successfully", newCoupon);
            createLogger.createLogger("application", path, "POST", "Coupon 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));
        }
    }

    @CouponSwagger.GetCouponByIdOperation
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getCouponById(@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<Coupon> couponOptional = couponService.getCoupon(id);
            if (couponOptional.isPresent()) {
                Coupon couponData = couponOptional.get();

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

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

    @CouponSwagger.UpdateCouponOperation
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Coupon>> updateCoupon(@PathVariable Long id, @Valid @RequestBody CouponRequest couponRequest) {
        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));
            }

            Coupon updatedCoupon = couponService.updateCoupon(id, couponRequest);
            ApiResponse<Coupon> apiResponse = new ApiResponse<>("success", HttpStatus.OK.value(), "Coupon updated successfully", updatedCoupon);
            createLogger.createLogger("application", path, "PUT", "Coupon 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));
        }
    }

    @CouponSwagger.DeleteCouponOperation
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteCoupon(@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));
            }

            couponService.deleteCoupon(id);
            ApiResponse<Void> response = new ApiResponse<>("success", HttpStatus.OK.value(), "Coupon deleted successfully", null);
            createLogger.createLogger("application", path, "DELETE", "Coupon 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> prepareCouponResponse(Coupon couponData) {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("id", couponData.getId());
        data.put("name", couponData.getName());
        data.put("code", couponData.getCode());
        data.put("start_date", String.valueOf(couponData.getStart_date()));
        data.put("end_date", String.valueOf(couponData.getEnd_date()));
        data.put("percentage", couponData.getPercentage());
        data.put("created_by", couponData.getCreated_by());
        data.put("created_at", String.valueOf(couponData.getCreated_at()));
        return data;
    }
}