package com.project.whatsappchatbot.controller;

import static com.project.whatsappchatbot.controller.BotController.WhatsAppBotController.WHATSAPP_API_TOKEN;
import static com.project.whatsappchatbot.controller.BotController.WhatsAppBotController.WHATSAPP_API_URL;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.project.whatsappchatbot.DTO.AssignMechanicRequest;
import com.project.whatsappchatbot.DTO.CustomerDTO;
import com.project.whatsappchatbot.DTO.ForgetPasswordDTO;
import com.project.whatsappchatbot.DTO.InvoiceDTO;
import com.project.whatsappchatbot.DTO.InvoiceResponseDTO;
import com.project.whatsappchatbot.DTO.MechanicDTO;
import com.project.whatsappchatbot.DTO.MechanicDTOD;
import com.project.whatsappchatbot.DTO.MechanicDtoo;
import com.project.whatsappchatbot.DTO.OrderResponseDTO;
import com.project.whatsappchatbot.DTO.PaymentLinkRequest;
import com.project.whatsappchatbot.DTO.RejectOrder;
import com.project.whatsappchatbot.DTO.SaveOrderDTO;
import com.project.whatsappchatbot.DTO.ServiceDTO;
import com.project.whatsappchatbot.DTO.UpdateInvoice;
import com.project.whatsappchatbot.DTO.UpdateOrder;
import com.project.whatsappchatbot.controller.BotController.WhatsAppBotController;
import com.project.whatsappchatbot.model.Account;
import com.project.whatsappchatbot.model.ChatMessage;
import com.project.whatsappchatbot.model.Complaint;
import com.project.whatsappchatbot.model.Customer;
import com.project.whatsappchatbot.model.HelpSupport;
import com.project.whatsappchatbot.model.Invoice;
import com.project.whatsappchatbot.model.Mechanic;
import com.project.whatsappchatbot.model.Order;
import com.project.whatsappchatbot.model.PaymentLink;
import com.project.whatsappchatbot.model.Service;
import com.project.whatsappchatbot.model.Status;
import com.project.whatsappchatbot.repository.AccountRepository;
import com.project.whatsappchatbot.repository.ChatMessageRepository;
import com.project.whatsappchatbot.repository.ComplaintRepository;
import com.project.whatsappchatbot.repository.CustomerRepository;
import com.project.whatsappchatbot.repository.FeedbackRepository;
import com.project.whatsappchatbot.repository.HelpSupportRepository;
import com.project.whatsappchatbot.repository.InvoiceRepository;
import com.project.whatsappchatbot.repository.MechanicRepository;
import com.project.whatsappchatbot.repository.OrderRepository;
import com.project.whatsappchatbot.repository.PaymentLinkRepository;
import com.project.whatsappchatbot.repository.ServiceRepository;
import com.project.whatsappchatbot.repository.StatusRepository;
import com.project.whatsappchatbot.repository.VehicleRepository;
import com.project.whatsappchatbot.response.DashboardResponse;

@RestController
@CrossOrigin(origins = "https://wati.bikefixup.co.in", maxAge = 3600)
@RequestMapping("/api")
public class AdminPanelController {

	@Value("${phone.notification.numbers}")
    private String notificationNumbers;

    private List<String> notificationNumberList;

    @PostConstruct
    public void initPhonesNotificationNumber() {
        if (notificationNumbers != null && !notificationNumbers.isBlank()) {
        	notificationNumberList = Arrays.asList(notificationNumbers.split(","));
        } else {
            notificationNumberList = new ArrayList<>();
        }
    }

	@Autowired
	private InvoiceRepository invoiceRepository;

	@Autowired
	private ComplaintRepository complaintRepository;
	@Autowired
	private StatusRepository statusRepository;
	@Autowired
	private VehicleRepository vehicleRepository;
	@Autowired
	private HelpSupportRepository helpSupportRepository;

	@Autowired
	private PaymentLinkRepository paymentLinkRepository;
	private static final RestTemplate restTemplate = new RestTemplate();
	@Autowired
	private MechanicRepository mechanicRepository;

	@Autowired
	private OrderRepository orderRepository;

	@Autowired
	private ChatMessageRepository chatMessageRepository;

	@Autowired
	private FeedbackRepository feedbackRepository;

	@Autowired
	private AccountRepository accountRepository;

	@Autowired
	private CustomerRepository customerRepository;

	@Autowired
	private ServiceRepository serviceRepository;

	@Autowired
	private JavaMailSender mailSender;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Value("${baseurl}")
	private String baseUrl;

	private static Map<String, Long> status2ToStatusIdMap = new HashMap<>();
	private static final Logger log = LoggerFactory.getLogger(AdminPanelController.class);

	static {
		status2ToStatusIdMap.put("Confirmed", 2L);
		status2ToStatusIdMap.put("Progress", 5L);
		status2ToStatusIdMap.put("Complete", 6L);
		status2ToStatusIdMap.put("Cancelled", 8L);
	}

	@GetMapping("/dashboard")
	public DashboardResponse dashboard() {
		DashboardResponse response = new DashboardResponse();

		response.setInvoiceCount(invoiceRepository.count());
		response.setNewOrderCount(orderRepository.countByStatusId(2L));
		response.setInProgressOrderCount(orderRepository.countByStatusId(5L));
		response.setCompletedOrderCount(orderRepository.countByStatusId(6L));
		response.setMechanicCount(mechanicRepository.count());
		response.setUnAssignedMechanicCount(mechanicRepository.countByJobAssignedCount(null));
		response.setFeedbackCount(feedbackRepository.count());
		response.setAccountCount(accountRepository.count());
		response.setCustomerCount(customerRepository.count());

		return response;
	}

	public void InvoiceService(InvoiceRepository invoiceRepository) {
		this.invoiceRepository = invoiceRepository;
	}

	public long getTotalInvoiceCount() {
		return invoiceRepository.count();
	}

	@GetMapping("/mechanics/{mechanicId}")
	public Mechanic getMechanic(@PathVariable Long mechanicId) {
		return mechanicRepository.findById(mechanicId).orElse(null);
	}

	@PostMapping("/getOrder")
	public ResponseEntity<Order> getOrder(@RequestBody Map<String, Object> requestBody) {
		if (requestBody.containsKey("orderId")) {
			try {
				Long orderId = Long.parseLong(requestBody.get("orderId").toString());
				Optional<Order> optionalOrder = orderRepository.findById(orderId);
				if (optionalOrder.isPresent()) {
					Order order = optionalOrder.get();
					return ResponseEntity.ok(order);
				} else {
					return ResponseEntity.notFound().build();
				}
			} catch (NumberFormatException e) {
				return ResponseEntity.badRequest().build();
			}
		} else {
			return ResponseEntity.badRequest().build();
		}
	}
	
	

	@GetMapping("/getInvoices")
	public ResponseEntity<?> getInvoice(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String searchQuery) {
		Logger logger = LoggerFactory.getLogger(getClass());
		try {
			Pageable pagingInvoice = PageRequest.of(page, size, Sort.by("id").descending());
			Pageable pagingOrder = PageRequest.of(page, size, Sort.by("id").descending());
			Page<Invoice> invoices = null;

			if (searchQuery != null && !searchQuery.isEmpty()) {
				searchQuery = searchQuery.trim();
				logger.debug("Received search query: {}", searchQuery);

				logger.debug("Searching for invoices by invoice ID or order ID containing: {}", searchQuery);
				invoices = invoiceRepository.findByIdContaining(searchQuery, pagingInvoice);

				if (!invoices.hasContent()) {
					logger.warn("No invoices found for the search query: {}", searchQuery);
					return ResponseEntity.notFound().build();
				}
			} else {
				logger.debug("No search query provided. Fetching all invoices.");
				invoices = invoiceRepository.findAll(pagingInvoice);
			}

			if (invoices != null && invoices.hasContent()) {
				Page<InvoiceResponseDTO> dtoPage = invoices.map(this::convertToDto);
				return ResponseEntity.ok(dtoPage);
			} else {
				logger.warn("No invoices found.");
				return ResponseEntity.notFound().build();
			}
		} catch (Exception e) {
			logger.error("Error occurred while fetching invoices: ", e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An error occurred while fetching invoices.");
		}
	}

	@GetMapping("/allOrders")
	public ResponseEntity<Page<OrderResponseDTO>> getOrders(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String status2,
			@RequestParam(required = false) String searchQuery) {

		Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
		Page<Order> orders = null;

		if (searchQuery != null && !searchQuery.isEmpty()) {
			searchQuery = searchQuery.trim();

			orders = orderRepository.findByIdContaining(searchQuery, paging);
			if (!orders.hasContent()) {

				if (!searchQuery.isEmpty()) {
					searchQuery = searchQuery.trim();

					List<Order> orderList = orderRepository.findAllByUserPhoneContaining(searchQuery);
					orders = new PageImpl<>(orderList, paging, orderList.size());
				}

			}
		} else if (status2 != null && !status2.isEmpty()) {
			orders = orderRepository.findAllByStatusId(status2ToStatusIdMap.get(status2), paging);
		} else {
			orders = orderRepository.findAll(paging);
		}

		if (orders != null && orders.hasContent()) {
			Page<OrderResponseDTO> orderResponseDTOPage = orders.map(order -> {

				CustomerDTO customerDTO = null;

				Customer customer = Optional.of(order.getUser()).orElse(null);
				customerDTO = new CustomerDTO();
				customerDTO.setId(customer.getId());
				customerDTO.setRoleId(customer.getRoleId());
				customerDTO.setName(customer.getName());
				customerDTO.setEmail(customer.getEmail());
				customerDTO.setAvatar(customer.getAvatar());
				customerDTO.setEmailVerifiedAt(customer.getEmailVerifiedAt());
				customerDTO.setPassword(customer.getPassword());
				customerDTO.setRememberToken(customer.getRememberToken());
				customerDTO.setSettings(customer.getSettings());
				customerDTO.setDob(customer.getDob());
				customerDTO.setPhoneNumber(customer.getPhone());
				customerDTO.setStateId(customer.getStateId());

				customerDTO.setCityId(customer.getCityId());
				customerDTO.setGender(customer.getGender());
				customerDTO.setOtp(customer.getOtp());
				customerDTO.setDeviceKey(customer.getDeviceKey());
				customerDTO.setCreatedAt(customer.getCreatedAt());
				customerDTO.setUpdatedAt(customer.getUpdatedAt());
				customerDTO.setLastReminder(customer.getLastReminder());
				customerDTO.setStatus(customer.getStatus());
				customerDTO.setDevicePlatform(customer.getDevicePlatform());
				log.info("CustomerDTO");

				MechanicDTO mechanicDTO = new MechanicDTO();

				if (Objects.nonNull(order.getMechanicId())) {
					Mechanic mechanic = mechanicRepository.findById(order.getMechanicId()).orElse(null);
					mechanicDTO.setId(mechanic.getId());
					mechanicDTO.setName(mechanic.getName());
					mechanicDTO.setPhoneNumber(mechanic.getPhone());

					mechanicDTO.setPhoneNumber(mechanic.getPhone());

				}
				log.info("Mechanic DTO");

				InvoiceDTO invoiceDTO = new InvoiceDTO();

				if (order.getInvoice() != null) {
					invoiceDTO.setId(order.getInvoice().getId());
				}
				ServiceDTO serviceDTO = null;

				if (order.getServiceId() != null) {
					Service service = serviceRepository.findById(order.getServiceId()).orElse(null);
					serviceDTO = new ServiceDTO();
					serviceDTO.setId(service.getId());
					serviceDTO.setServiceType(service.getServiceTypeId().getName());
					serviceDTO.setServiceName(service.getName());
					serviceDTO.setServiceDescription(service.getDescription());
					serviceDTO.setServiceProvide(service.getWhatWeProvide());
					serviceDTO.setPrice(service.getPrice());
					serviceDTO.setImage(service.getImage());
				}
				log.info("ServiceDto");

				OrderResponseDTO orderResponseDTO = new OrderResponseDTO();
				orderResponseDTO.setOrderId(order.getId());
				orderResponseDTO.setServiceId(order.getServiceId());
				orderResponseDTO.setDateAndTime(order.getDateAndTime());
				orderResponseDTO.setRequirePickup(order.getRequirePickup());
				if (order.getVehicle() != null) {
					orderResponseDTO.setVehicleId(order.getVehicle().getId());
					orderResponseDTO.setBrand(order.getVehicle().getBrand().getName());
				}

				orderResponseDTO.setUserId(order.getUser().getId());
				orderResponseDTO.setCouponId(order.getCouponId());
				if (order.getAddress() != null) {
					orderResponseDTO.setAddressId(order.getAddress().getId());
					orderResponseDTO.setLocation(String.format("Latitude: %s, Longtitude: %s",
							order.getAddress().getLatitude(), order.getAddress().getLongitude()));
					orderResponseDTO.setCites(order.getAddress().getCity().getName());
					orderResponseDTO.setAddress(String.format("City: %s, Street: %s",
							order.getAddress().getCity().getName(), order.getAddress().getStreet()));
				}
				orderResponseDTO.setCreatedAt(order.getCreatedAt());
				orderResponseDTO.setUpdatedAt(order.getUpdatedAt());
				if (order.getStatus() != null) {
					orderResponseDTO.setStatus2(order.getStatus().getTitle());
				}

				orderResponseDTO.setTotalPrice(order.getTotalPrice());

				orderResponseDTO.setPhoneNumber(order.getUser().getPhone());

				if (order.getInvoice() != null) {
					orderResponseDTO.setPaymentStatus(order.getInvoice().getPaymentStatus());
				}
				if (order.getOrderCancellationReason() != null) {
					orderResponseDTO.setCancellationReason(order.getOrderCancellationReason().getTitle());
				}
				orderResponseDTO.setPaymentIdentifier(order.getPaymentIdentifier());
				orderResponseDTO.setPaymentMethod(order.getPaymentMethod());
				orderResponseDTO.setPaymentMode(order.getPaymentMode());

				orderResponseDTO.setDevicePlatform(String.valueOf(order.getDevicePlatform()));
				orderResponseDTO.setCustomer(customerDTO);
				orderResponseDTO.setService(serviceDTO);
				orderResponseDTO.setInvoice(invoiceDTO);
				orderResponseDTO.setMechanic(mechanicDTO);
				return orderResponseDTO;
			});

			return ResponseEntity.ok(orderResponseDTOPage);
		} else {
			return ResponseEntity.notFound().build();
		}

	}

	@GetMapping("/feedbacks/{feedbackId}")
	public Complaint getFeedback(@PathVariable Long feedbackId) {
		return feedbackRepository.findById(feedbackId).orElse(null);
	}

	@PostMapping("/invoices")
	public Invoice createInvoice(@RequestBody Invoice invoice) {
		return invoiceRepository.save(invoice);
	}

	@PostMapping("/feedbacks")
	public Complaint createFeedback(@RequestBody Complaint feedback) {
		return feedbackRepository.save(feedback);
	}

	private InvoiceResponseDTO convertToDto(Invoice invoice) {
		Optional<Order> optionalOrder = Optional.of(invoice.getOrder());

		if (optionalOrder.isPresent()) {
			Order order = optionalOrder.get();
			Optional<Customer> optionalCustomer = Optional.of(order.getUser());

			if (optionalCustomer.isPresent()) {
				Customer customer = optionalCustomer.get();
				String customerPhoneNumber = customer.getPhone();

				return new InvoiceResponseDTO(invoice.getId(), invoice.getOrder().getId(), invoice.getUrl(),
						invoice.getStatus(), invoice.getCreatedAt(), invoice.getUpdatedAt(), customerPhoneNumber);
			} else {
				System.out.println("Customer not found for order ID: " + order.getId());
			}
		} else {
			System.out.println("Order not found for invoice ID: " + invoice.getId());
		}

		return null;
	}

	@PutMapping("/mechanics/{mechanicId}")
	public Mechanic updateMechanic(@PathVariable Long mechanicId, @RequestBody Mechanic updatedMechanic) {
		Mechanic mechanic = mechanicRepository.findById(mechanicId).orElse(null);
		if (mechanic != null) {
			mechanic.setName(updatedMechanic.getName());

			mechanic.setPhone(updatedMechanic.getPhone());
			mechanic.setSpeciality(updatedMechanic.getSpeciality());
			return mechanicRepository.save(mechanic);
		}
		return null;
	}

	@GetMapping("/getMechanics")
	public ResponseEntity<Page<MechanicDTOD>> getMechanics(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String searchQuery) {
		try {
			Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
			Page<Mechanic> mechanics;

			if (searchQuery != null && !searchQuery.isEmpty()) {
				searchQuery = searchQuery.trim();
				mechanics = mechanicRepository.findByPhoneContaining(searchQuery, paging);
			} else {
				mechanics = mechanicRepository.findAll(paging);
			}

			if (mechanics.hasContent()) {
				Page<MechanicDTOD> mechanicDTOs = mechanics.map(MechanicDTOD::new);
				return ResponseEntity.ok(mechanicDTOs);
			} else {
				return ResponseEntity.notFound().build();
			}
		} catch (Exception e) {
			return ResponseEntity.badRequest().build();
		}
	}

	@GetMapping("/getMechanicss")
	public ResponseEntity<Page<MechanicDTOD>> getMechanicss(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "230") int size, @RequestParam(required = false) String searchQuery) {
		try {
			Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
			Page<Mechanic> mechanics;

			if (searchQuery != null && !searchQuery.isEmpty()) {
				searchQuery = searchQuery.trim();
				mechanics = mechanicRepository.findByPhoneContaining(searchQuery, paging);
			} else {
				mechanics = mechanicRepository.findAll(paging);
			}

			Page<MechanicDTOD> mechanicDTOs = mechanics.map(MechanicDTOD::new);
			return ResponseEntity.ok(mechanicDTOs);
		} catch (Exception e) {
			return ResponseEntity.badRequest().build();
		}
	}

	private static final Logger logger = LoggerFactory.getLogger(AdminPanelController.class);

	@PutMapping("/assignMechanic")
	public ResponseEntity<?> assignMechanic(@RequestBody AssignMechanicRequest request) {
		WhatsAppBotController wm = new WhatsAppBotController();

		try {
			if (request.getOrderId() == null || request.getMechanicId() == null) {
				logger.error("Missing required fields: orderId={}, mechanicId={}, status={}", request.getOrderId(),
						request.getMechanicId());
				return ResponseEntity.badRequest().body("Missing required fields: orderId, mechanicId, status");
			}

			String orderIdStr = request.getOrderId();
			String mechanicIdStr = request.getMechanicId();

			Long orderId;
			Long mechanicId;

			try {
				orderId = Long.parseLong(orderIdStr);
			} catch (NumberFormatException e) {
				logger.error("Invalid orderId format: {}", orderIdStr, e);
				return ResponseEntity.badRequest().body("Invalid orderId format: " + orderIdStr);
			}

			try {
				mechanicId = Long.parseLong(mechanicIdStr);
			} catch (NumberFormatException e) {
				logger.error("Invalid mechanicId format: {}", mechanicIdStr, e);
				return ResponseEntity.badRequest().body("Invalid mechanicId format: " + mechanicIdStr);
			}

			Optional<Order> optionalOrder = orderRepository.findById(orderId);
			if (optionalOrder.isPresent()) {
				Optional<Mechanic> optionalMechanic = mechanicRepository.findById(mechanicId);
				if (optionalMechanic.isPresent()) {
					Order order = optionalOrder.get();
					Mechanic mechanic = optionalMechanic.get();
					order.setStatus(statusRepository.findById(5L).get());

					if (mechanic.getJobAssignedCount() == null) {
						mechanic.setJobAssignedCount("0");
						;
					}
					int count = Integer.parseInt(mechanic.getJobAssignedCount());
					count += 1;
					mechanic.setJobAssignedCount(String.valueOf(count));
					order.setMechanicId(mechanic.getId());
					orderRepository.save(order);
					mechanicRepository.save(mechanic);

					String message = String.format(
							"Hello %s,\n\nYou have been assigned a new order. Here are the details:\n\n"
									+ "Order Description: %s\n" + "Customer Contact: %s\n\n"
									+ "Please contact the customer as soon as possible to get started.\n\nThank you!",
							mechanic.getName(), order.getDescription(), order.getUser().getId());

					wm.sendTextMessage("+" + mechanic.getPhone(), message);

					return ResponseEntity.ok("Mechanic assigned successfully!");
				} else {
					logger.error("Mechanic not found: mechanicId={}", mechanicId);
					return ResponseEntity.badRequest().body("Mechanic not found");
				}
			} else {
				logger.error("Order not found: orderId={}", orderId);
				return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Order not found");
			}
		} catch (Exception e) {
			logger.error("An unexpected error occurred", e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An unexpected error occurred: " + e.getMessage());
		}
	}

	@PostMapping("/saveOrder")
	public Order saveOrder(@RequestBody SaveOrderDTO saveOrderDTO) {

		Customer customer = customerRepository.findByPhone(saveOrderDTO.getUserPhoneNumber());
		if (customer == null) {
			throw new RuntimeException("Customer not found with phone number: " + saveOrderDTO.getUserPhoneNumber());
		}

		Order order = new Order();
		order.setCreatedByBot(1);
		order.setServiceId(saveOrderDTO.getServiceId());
		order.setDateAndTime(saveOrderDTO.getDateTime());
		order.setVehicle(vehicleRepository.findById(saveOrderDTO.getVehicleId()).get());
		if (statusRepository.findByTitle(saveOrderDTO.getStatus2()).isPresent()) {
			order.setStatus(statusRepository.findByTitle(saveOrderDTO.getStatus2()).get());
		}
		order.setTotalPrice(saveOrderDTO.getTotalPrice());
		order.setIsPaid(saveOrderDTO.getPaymentStatus());
		order.setDevicePlatform(String.valueOf(saveOrderDTO.getDevicePlatform()));
		order.setUser(customer);
		order.setRequirePickup(saveOrderDTO.getRequirePickup());

		return orderRepository.save(order);

	}

	@GetMapping("/getAllChats")
	public ResponseEntity<Page<ChatMessage>> getAllChats(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size) {
		try {
			Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "id")); // Assuming you want to
																								// sort by 'id'
			Page<ChatMessage> chatMessages = chatMessageRepository.findAll(pageable);
			return ResponseEntity.ok(chatMessages);
		} catch (NumberFormatException e) {
			return ResponseEntity.badRequest().build();
		}
	}

	@PostMapping("/getCustomerOrder")
	public ResponseEntity<Page<Order>> getCustomerOrder(@RequestBody Map<String, Object> requestBody) {
		if (requestBody.containsKey("phoneNumber")) {
			String phoneNumber = requestBody.get("phoneNumber").toString();
			try {

				int page = 0;
				int size = 10;
				if (requestBody.containsKey("page")) {
					page = Integer.parseInt(requestBody.get("page").toString());
				}
				if (requestBody.containsKey("size")) {
					size = Integer.parseInt(requestBody.get("size").toString());
				}

				Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
				Optional<Customer> optionalCustomer = Optional.ofNullable(customerRepository.findByPhone(phoneNumber));

				if (optionalCustomer.isPresent()) {
					Customer customer = optionalCustomer.get();

					Page<Order> orders = orderRepository.findByUserId(String.valueOf(customer.getId()), paging);
					if (!orders.isEmpty()) {
						return ResponseEntity.ok(orders);
					} else {
						return ResponseEntity.notFound().build();
					}
				} else {
					return ResponseEntity.notFound().build();
				}
			} catch (NumberFormatException e) {
				return ResponseEntity.badRequest().build();
			}
		} else {
			return ResponseEntity.badRequest().build();
		}
	}

	@Value("${upload.directory}")
	private String uploadDirectory;

	@GetMapping("/upload")
	public String displayUploadForm() {
		return "upload";
	}

	@PostMapping("/completeOrder")
	public ResponseEntity<String> completeOrder(@RequestParam("orderId") String orderId,
			@RequestParam("pdfInvoice") MultipartFile pdfInvoice) throws IOException {

		Optional<Order> optionalOrder = orderRepository.findById(Long.valueOf(orderId));
		Order order = null;
		if (optionalOrder.isPresent()) {
			order = optionalOrder.get();

		}
		if (pdfInvoice.isEmpty() || !pdfInvoice.getContentType().equals("application/pdf")) {

			return ResponseEntity.badRequest().body("Please upload a PDF invoice file.");
		}

		try {

			String currentDate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
			String originalFilename = pdfInvoice.getOriginalFilename();
			String invoiceFilename = currentDate + "_" + originalFilename;
			invoiceFilename = invoiceFilename.replace(" ", "_");

			Files.createDirectories(Paths.get(uploadDirectory));

			String filePath = uploadDirectory + File.separator + invoiceFilename;
			Files.write(Paths.get(filePath), pdfInvoice.getBytes());

			System.out.println("Invoice saved to: " + filePath);

			Optional<Invoice> existingInvoiceOptional = invoiceRepository.findByOrderId(Long.valueOf(orderId));
			Invoice invoice;
			if (existingInvoiceOptional.isPresent()) {

				invoice = existingInvoiceOptional.get();
				invoice.setUrl("/invoices/" + invoiceFilename);
				order.setStatus(statusRepository.findById(6L).get());

				invoice.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
				order.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
				order.setInvoice(invoice);
			} else {

				invoice = new Invoice();
				invoice.setOrder(order);
				invoice.setUrl("/invoices/" + invoiceFilename);
				invoice.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
				invoice.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
				order.setStatus(statusRepository.findById(6L).get());
				order.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
				order.setInvoice(invoice);
				invoice.setAmount("Logic for amount is missing");

				if (order.getMechanicId() != null) {
					Optional<Mechanic> optionalMechanic = mechanicRepository
							.findById(Long.valueOf(order.getMechanicId()));
					if (optionalMechanic.isPresent()) {

						Mechanic mechanic = optionalMechanic.get();
						int count = Integer.parseInt(mechanic.getJobAssignedCount());
						count -= 1;
						mechanic.setJobAssignedCount(String.valueOf(count));
						mechanicRepository.save(mechanic);
					}

				}
			}

			invoiceRepository.save(invoice);

			return ResponseEntity.ok("Order completed and invoice uploaded successfully.");

		} catch (Exception e) {
			throw e;
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to upload invoice: " + e.getMessage());
		}

	}

	@PostMapping("/bulkMessage")
	public ResponseEntity<String> bulkMessage(@RequestParam("messageType") String messageType,
			@RequestParam("excelFile") MultipartFile excel) {

		if (excel.isEmpty() || !excel.getContentType()
				.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
			logger.error("Invalid file or content type: " + excel.getContentType());
			return ResponseEntity.badRequest().body("Please upload a valid Excel file.");
		}

		try (InputStream is = excel.getInputStream(); Workbook workbook = new XSSFWorkbook(is)) {
			Sheet sheet = workbook.getSheetAt(0);
			Iterator<Row> rowIterator = sheet.iterator();
			DecimalFormat df = new DecimalFormat("0");

			if (!rowIterator.hasNext()) {
				logger.error("Excel file is empty");
				return ResponseEntity.badRequest().body("The uploaded Excel file is empty.");
			}

			int messageCount = 0;
			int maxMessages = 800;

			while (rowIterator.hasNext() && messageCount < maxMessages) {
				Row row = rowIterator.next();
				if (row.getCell(0) != null) {
					String recipientNumber = null;
					if (row.getCell(0).getCellType() == CellType.STRING) {
						recipientNumber = row.getCell(0).getStringCellValue();
					} else if (row.getCell(0).getCellType() == CellType.NUMERIC) {
						recipientNumber = df.format(row.getCell(0).getNumericCellValue());
					} else {
						logger.error("Invalid cell type at row " + row.getRowNum() + ", cell type: "
								+ row.getCell(0).getCellType());
						continue;
					}
					if (recipientNumber != null) {
						sendTemplateMessageFORALL("+" + recipientNumber, messageType);
						logger.info("Message sent to: " + recipientNumber);
						messageCount++;
					} else {
						logger.error("Recipient number is null at row " + row.getRowNum());
					}
				} else {
					logger.error("Cell is null at row " + row.getRowNum());
				}
			}

			if (messageCount >= maxMessages) {
				logger.info("Reached the maximum limit of 800 messages.");
			}

		} catch (Exception e) {
			logger.error("An error occurred while processing the Excel file: ", e);
			return ResponseEntity.status(500).body("An error occurred while processing the Excel file.");
		}

		return ResponseEntity.ok("Bulk messages sent successfully.");
	}

	@Async
	public void sendTextMessage1(String recipientNumber, String text) {
		try {
			Map<String, Object> payload = new HashMap<>();
			payload.put("messaging_product", "whatsapp");
			payload.put("recipient_type", "individual");
			payload.put("to", recipientNumber);
			payload.put("type", "text");
			payload.put("text", Map.of("body", text));

			sendMessage(payload);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sendTextMessage(String recipientNumber, String text) {
		try {
			Map<String, Object> payload = new HashMap<>();
			payload.put("messaging_product", "whatsapp");
			payload.put("to", recipientNumber);
			payload.put("type", "template");
			Map<String, Object> template = new HashMap<>();
			template.put("name", "hello_world");
			Map<String, String> language = new HashMap<>();
			language.put("code", "en_US");
			template.put("language", language);
			payload.put("template", template);

			sendMessage(payload);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	void sendMessage(Map<String, Object> payload) {
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.setBearerAuth(WhatsAppBotController.WHATSAPP_API_TOKEN);

			HttpEntity<Map<String, Object>> entity = new HttpEntity<>(payload, headers);

			ResponseEntity<String> response = restTemplate.exchange(WHATSAPP_API_URL, HttpMethod.POST, entity,
					String.class);

			if (!response.getStatusCode().is2xxSuccessful()) {
				throw new HttpClientErrorException(response.getStatusCode(),
						"Failed to send message: " + response.getBody());
			}

			System.out.println("Message sent successfully: " + response.getBody());
		} catch (HttpClientErrorException e) {
			System.err.println("HTTP Error: " + e.getStatusCode() + " - " + e.getResponseBodyAsString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@GetMapping("/getComplaints")
	public ResponseEntity<?> getComplaints(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size) {
		Logger logger = LoggerFactory.getLogger(getClass());
		try {
			Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
			Page<Complaint> complaintsPage = complaintRepository.findAll(paging);
			return ResponseEntity.ok(complaintsPage);
		} catch (Exception e) {
			logger.error("Error occurred while fetching complaints: ", e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An error occurred while fetching complaints.");
		}
	}

	@PutMapping("/updateOrderStatus")
	public ResponseEntity<Order> updateOrderStatus(@RequestBody UpdateOrder updateOrder) {
		Optional<Order> optionalOrder = orderRepository.findById(updateOrder.getOrderId());
		if (optionalOrder.isPresent()) {
			Order order = optionalOrder.get();
			Optional<Status> statusOptional = statusRepository.findByTitle(updateOrder.getStatus());
			if (statusOptional.isPresent()) {
				order.setStatus(statusOptional.get());
			}
			orderRepository.save(order);
			return ResponseEntity.ok(order);
		} else {
			return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
		}
	}

	@GetMapping("/getHelpSupport")
	public ResponseEntity<?> getHelpSupport(@RequestParam(defaultValue = "0") int page,
			@RequestParam(defaultValue = "10") int size) {
		Logger logger = LoggerFactory.getLogger(getClass());
		try {
			Pageable paging = PageRequest.of(page, size, Sort.by("id").descending());
			Page<HelpSupport> helpSupportPage = helpSupportRepository.findAll(paging);
			return ResponseEntity.ok(helpSupportPage);
		} catch (Exception e) {
			logger.error("Error occurred while fetching complaints: ", e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An error occurred while fetching complaints.");
		}
	}

	@Transactional
	@PutMapping("/forget")
	public ResponseEntity<String> forgetPassword(@RequestBody ForgetPasswordDTO forgetPasswordDTO) {

		Optional<Account> optionalAccount = accountRepository.findByEmail(forgetPasswordDTO.getEmail());

		if (optionalAccount.isPresent()) {
			Account account = optionalAccount.get();

			String newPassword = generateRandomPassword(6);

			account.setPassword(passwordEncoder.encode(newPassword));
			accountRepository.save(account);

			new Thread(() -> {
				try {
					sendEmail(forgetPasswordDTO.getEmail(), newPassword);
				} catch (MessagingException e) {
					e.printStackTrace();
				}
			}).start();

			return ResponseEntity.ok("Password reset successfully. Please check your email for the new password.");
		} else {
			return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Email not found");
		}
	}

	private String generateRandomPassword(int length) {
		String allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		StringBuilder newPassword = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			int randomIndex = random.nextInt(allowedChars.length());
			newPassword.append(allowedChars.charAt(randomIndex));
		}
		return newPassword.toString();
	}

	private void sendEmail(String recipientEmail, String newPassword) throws MessagingException {
		String fromEmail = "your-email@gmail.com";
		String subject = "Request For Password Reset";
		String messageText = "Hello, here is your new password: " + newPassword + ".\n\nThank you for trusting us!";

		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);

		helper.setFrom(fromEmail);
		helper.setTo(recipientEmail);
		helper.setSubject(subject);
		helper.setText(messageText, true);

		mailSender.send(message);
	}

	@PostMapping("/rejectOrder")
	public ResponseEntity<Order> rejectOrder(@RequestBody RejectOrder rejectOrder) {
		try {
			Optional<Order> optionalOrder = orderRepository.findById(Long.valueOf(rejectOrder.getOrderId()));
			if (optionalOrder.isPresent()) {
				Order order = optionalOrder.get();
				order.setStatus(statusRepository.findById(8L).get());
				orderRepository.save(order);
				return ResponseEntity.ok(order);
			} else {
				return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
			}
		} catch (NumberFormatException e) {
			return ResponseEntity.badRequest().body(null);
		}
	}

	@PutMapping("/updateInvoiceStatus")
	public ResponseEntity<Invoice> updateInvoiceStatus(@RequestBody UpdateInvoice updateInvoice) {
		Optional<Invoice> optionalInvoice = invoiceRepository.findByOrderId(updateInvoice.getOrderId());
		if (optionalInvoice.isPresent()) {
			Invoice invoice = optionalInvoice.get();
			invoice.setStatus(updateInvoice.getStatus());
			invoiceRepository.save(invoice);
			return ResponseEntity.ok(invoice);
		} else {
			return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
		}
	}

	@PostMapping("/addMechanic")
	public ResponseEntity<String> addMechanic(@RequestBody MechanicDtoo mechanicDto) {
		try {

			Optional<Mechanic> existingMechanic = mechanicRepository.findByPhone(mechanicDto.getPhone());
			if (existingMechanic.isPresent()) {
				return ResponseEntity.status(HttpStatus.CONFLICT)
						.body("A mechanic with this phone number already exists.");
			}

			Mechanic mechanic = new Mechanic();
			mechanic.setName(mechanicDto.getName());
			mechanic.setPhone(mechanicDto.getPhone());
			mechanic.setState(mechanicDto.getState());
			mechanic.setCity(mechanicDto.getCity());
			mechanic.setAddress(mechanicDto.getAddress());
			mechanic.setExperience(mechanicDto.getExperience());
			mechanic.setCoverageArea(mechanicDto.getCoverageArea());

			mechanic.setProvideHomeService(mechanicDto.getProvideHomeService());

			mechanic.setSpeciality(mechanicDto.getSpeciality());
			Timestamp now = new Timestamp(System.currentTimeMillis());
			mechanic.setCreatedAt(now);
			mechanic.setUpdatedAt(now);

			Mechanic savedMechanic = mechanicRepository.save(mechanic);
			return ResponseEntity.ok("Mechanic added successfully.");
		} catch (DataIntegrityViolationException e) {
			logger.error("Data integrity violation while adding mechanic: {}", e.getMessage());
			return ResponseEntity.status(HttpStatus.CONFLICT).body("A mechanic with this phone number already exists.");
		} catch (Exception e) {
			logger.error("Unexpected error while adding mechanic: {}", e.getMessage(), e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An error occurred while adding the mechanic.");
		}
	}

	@PutMapping("/editMechanic")
	public ResponseEntity<String> editMechanic(@RequestBody MechanicDtoo mechanicDto) {
		try {

			Optional<Mechanic> existingMechanicOptional = mechanicRepository.findById(mechanicDto.getId());
			if (!existingMechanicOptional.isPresent()) {
				return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Mechanic not found.");
			}

			Mechanic existingMechanic = existingMechanicOptional.get();

			Optional<Mechanic> phoneMechanicOptional = mechanicRepository.findByPhone(mechanicDto.getPhone());
			if (phoneMechanicOptional.isPresent()
					&& !phoneMechanicOptional.get().getId().equals(existingMechanic.getId())) {
				return ResponseEntity.status(HttpStatus.CONFLICT)
						.body("A mechanic with this phone number already exists.");
			}

			existingMechanic.setName(mechanicDto.getName());
			existingMechanic.setPhone(mechanicDto.getPhone());
			existingMechanic.setState(mechanicDto.getState());
			existingMechanic.setCity(mechanicDto.getCity());
			existingMechanic.setAddress(mechanicDto.getAddress());
			existingMechanic.setExperience(mechanicDto.getExperience());
			existingMechanic.setCoverageArea(mechanicDto.getCoverageArea());
			existingMechanic.setProvideHomeService(mechanicDto.getProvideHomeService());
			existingMechanic.setSpeciality(mechanicDto.getSpeciality());
			existingMechanic.setUpdatedAt(new Timestamp(System.currentTimeMillis()));

			mechanicRepository.save(existingMechanic);
			return ResponseEntity.ok("Mechanic updated successfully.");
		} catch (DataIntegrityViolationException e) {
			logger.error("Data integrity violation while updating mechanic: {}", e.getMessage());
			return ResponseEntity.status(HttpStatus.CONFLICT).body("A mechanic with this phone number already exists.");
		} catch (Exception e) {
			logger.error("Unexpected error while updating mechanic: {}", e.getMessage(), e);
			return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
					.body("An error occurred while updating the mechanic.");
		}
	}

	@Autowired
	private RazorpayService razorpayService;

	@PostMapping("/send-payment-message")
	public ResponseEntity<String> sendPaymentMessage(@RequestBody PaymentLinkRequest paymentLinkRequest) {

		String transactionId = generateTransactionId();
		String serviceDescription = "Description not available", serviceName = null;
		Timestamp orderCreationDate = null;
		String orderId = paymentLinkRequest.getOrderId().trim();
		double billAmount = paymentLinkRequest.getAmount();

		System.out.println("Received PaymentLinkRequest: " + paymentLinkRequest);
		Optional<Order> optionalOrder = orderRepository.findById(Long.valueOf(orderId));
		if (optionalOrder.isPresent()) {
			Order order = optionalOrder.get();
			orderCreationDate = order.getCreatedAt();
			Optional<Service> optionalService = serviceRepository.findById(order.getServiceId());
			if (optionalService.isPresent()) {
				Service service = optionalService.get();
				serviceDescription = service.getDescription();
				serviceName = service.getName();
			}
			order.setIsPaid(0);

			Optional<Customer> optionalCustomer = Optional.of(order.getUser());
			Customer customer = null;

			if (optionalCustomer.isPresent()) {
				customer = optionalCustomer.get();
			}

			// Generate the payment link
			String paymentLink = razorpayService.createPaymentLink(paymentLinkRequest.getAmount(),
					paymentLinkRequest.getCurrency(), transactionId.trim(), customer.getName(), customer.getEmail(),
					customer.getPhone());

			// Store or update the payment link in the database
			PaymentLink paymentLinkEntity = paymentLinkRepository.findByContactNumber(customer.getPhone())
					.orElse(new PaymentLink());

			paymentLinkEntity.setOrderId(orderId);
			paymentLinkEntity.setPaymentLink(paymentLink);
			paymentLinkEntity.setAmount(billAmount);
			paymentLinkEntity.setContactNumber(customer.getPhone());
			paymentLinkEntity.setDescription(transactionId.trim());
			paymentLinkRepository.save(paymentLinkEntity);

			// Retrieve the saved payment link to ensure consistency
			String storedPaymentLink = paymentLinkEntity.getPaymentLink();
			String paymentLinkSuffix = storedPaymentLink.substring(storedPaymentLink.lastIndexOf("/") + 1);

			// Prepare the WhatsApp template message
			Map<String, Object> payload = new HashMap<>();
			payload.put("messaging_product", "whatsapp");
			payload.put("to", customer.getPhone());
			payload.put("type", "template");

			Map<String, Object> template = new HashMap<>();
			template.put("namespace", "your_actual_namespace");
			template.put("name", "payment_msg");

			Map<String, Object> language = new HashMap<>();
			language.put("code", "en_US");

			template.put("language", language);

			List<Map<String, Object>> components = new ArrayList<>();

			Map<String, Object> header = new HashMap<>();
			header.put("type", "header");
			List<Map<String, Object>> headerParams = new ArrayList<>();
			Map<String, Object> headerParam = new HashMap<>();
			headerParam.put("type", "image");
			headerParam.put("image", Map.of("link", baseUrl + "/images/paynow.jpg"));
			headerParams.add(headerParam);
			header.put("parameters", headerParams);
			components.add(header);

			Map<String, Object> body = new HashMap<>();
			body.put("type", "body");
			List<Map<String, Object>> parameters = new ArrayList<>();

			Map<String, Object> paramOrderId = new HashMap<>();
			paramOrderId.put("type", "text");
			paramOrderId.put("text", orderId);
			parameters.add(paramOrderId);

			Map<String, Object> paramServiceName = new HashMap<>();
			paramServiceName.put("type", "text");
			paramServiceName.put("text", serviceName);
			parameters.add(paramServiceName);

			Map<String, Object> paramBillAmount = new HashMap<>();
			paramBillAmount.put("type", "text");
			paramBillAmount.put("text", String.valueOf(billAmount + "0"));
			parameters.add(paramBillAmount);

			Map<String, Object> paramDateTime = new HashMap<>();
			paramDateTime.put("type", "text");
			paramDateTime.put("text", orderCreationDate != null ? orderCreationDate.toString() : "N/A");
			parameters.add(paramDateTime);

			body.put("parameters", parameters);
			components.add(body);

			Map<String, Object> button = new HashMap<>();
			button.put("type", "button");
			button.put("sub_type", "url");
			button.put("index", "0");
			List<Map<String, Object>> buttonParameters = new ArrayList<>();

			Map<String, Object> buttonParam = new HashMap<>();
			buttonParam.put("type", "text");
			buttonParam.put("text", paymentLinkSuffix);
			buttonParameters.add(buttonParam);

			button.put("parameters", buttonParameters);
			components.add(button);

			template.put("components", components);
			payload.put("template", template);

			// Send the message with the consistent payment link
			sendMessage(payload);
		}

		return ResponseEntity.ok("Payment message sent successfully.");
	}

	public void sendTemplateMessageFORALL(String recipientNumber, String messageType) {
		try {
			Map<String, String> templateNames = Map.of("Service reminder", "service_reminder1", "Welcome message",
					"welcome_message", "Promotional", "promotional");

			String templateName = templateNames.getOrDefault(messageType, "default_template");

			Map<String, Object> payload = new HashMap<>();
			payload.put("messaging_product", "whatsapp");
			payload.put("to", recipientNumber);
			payload.put("type", "template");
			payload.put("template", Map.of("name", templateName, "language", Map.of("code", "en_US")

			));

			sendMessageFORALL(payload);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void sendMessageFORALL(Map<String, Object> payload) {
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			headers.setBearerAuth(WHATSAPP_API_TOKEN);

			HttpEntity<Map<String, Object>> entity = new HttpEntity<>(payload, headers);

			ResponseEntity<String> response = restTemplate.exchange(WHATSAPP_API_URL, HttpMethod.POST, entity,
					String.class);

			if (!response.getStatusCode().is2xxSuccessful()) {
				throw new HttpClientErrorException(response.getStatusCode(),
						"Failed to send message: " + response.getBody());
			}

			System.out.println("Message sent successfully: " + response.getBody());
		} catch (HttpClientErrorException e) {
			System.err.println("HTTP Error: " + e.getStatusCode() + " - " + e.getResponseBodyAsString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String generateTransactionId() {
		String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		SecureRandom random = new SecureRandom();
		StringBuilder sb = new StringBuilder(12);
		for (int i = 0; i < 12; i++) {
			sb.append(characters.charAt(random.nextInt(characters.length())));
		}
		return sb.toString();
	}

}
