package com.infinite.focus.server.fcm;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import com.infinite.focus.server.auth.Account;
import com.infinite.focus.server.auth.AccountRepository;
import com.infinite.focus.server.auth.Message;
import com.infinite.focus.server.auth.NotFoundException;
import com.infinite.focus.server.auth.SecurityConstants;
import com.infinite.focus.server.auth.Student;
import com.infinite.focus.server.auth.StudentRepository;
import com.infinite.focus.server.fcm.model.PushNotification;
import com.infinite.focus.server.fcm.model.PushNotificationResponse;
import com.infinite.focus.server.fcm.model.ScreenType;
import com.infinite.focus.server.fcm.service.PushNotificationService;

import io.jsonwebtoken.Jwts;

@CrossOrigin(origins = "http://localhost:8383")
@RestController
@RequestMapping("api/fcm")

public class PushNotificationController {

	private AccountRepository accountRepository;
	private PushNotificationService pushNotificationService;

	private PushNotifcationRepository pushNotifcationRepository;
	private StudentPushNotificationRepository studentPushNotificationRepository;

	private StudentRepository studentRepository;

	public PushNotificationController(AccountRepository accountRepository,
			PushNotificationService pushNotificationService, PushNotifcationRepository pushNotifcationRepository,
			StudentPushNotificationRepository studentPushNotificationRepository, StudentRepository studentRepository) {
		this.accountRepository = accountRepository;
		this.pushNotificationService = pushNotificationService;
		this.pushNotifcationRepository = pushNotifcationRepository;
		this.studentPushNotificationRepository = studentPushNotificationRepository;
		this.studentRepository = studentRepository;

	}

	@PostMapping("/notification/topic")
	public ResponseEntity sendNotification(@RequestBody PushNotification request) {
		pushNotificationService.sendPushNotificationWithoutData(request);
		return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Notification has been sent."),
				HttpStatus.OK);
	}

	@PostMapping("/notification/token")
	public ResponseEntity sendTokenNotification(@RequestBody PushNotification request) {
		pushNotificationService.sendPushNotificationToToken(request);
		return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Notification has been sent."),
				HttpStatus.OK);
	}

	@PostMapping("/notification/data")
	public ResponseEntity sendDataNotification(@RequestBody PushNotification request) {
		pushNotificationService.sendPushNotification(request);
		return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Notification has been sent."),
				HttpStatus.OK);
	}

	@PostMapping("/student/send/notification")
	public ResponseEntity<Message> sendDataNotification(@RequestHeader(SecurityConstants.HEADER_STRING) String token,
			@RequestBody SendStudentNotificationRequest request) {

		if (token != null && !token.contains("undefined")) {

			// Parse token
			String user = Jwts.parser().setSigningKey(SecurityConstants.SECRET)
					.parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, "")).getBody().getSubject();

			// If token was successfully parsed
			if (user != null) {

				// System.out.println(user);

				// Find account for parsed user name
				Account a = accountRepository.findByUsername(user);

				// If account is null return error code to client
				if (a == null) {
					a = accountRepository.findByUsername2(user);
					if (a == null) {
						throw new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found!!!");
					}
				}

				List<Student> students;

				if (request.getInstructor_id() != null) {
					students = studentRepository.findByInstructorId(request.getInstructor_id());
				} else if (request.getIds() == null || request.getIds().isEmpty()) {
					students = studentRepository.findAllOrderById();
				} else {
					students = studentRepository.findByStudentIds(request.getIds());
				}

				if (students == null || students.isEmpty()) {
					throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Students are not found!!!");
				}

				/*
				 * for (Student student : students) {
				 * System.out.println(student.getFirst_name()); }
				 */
				
				PushNotification pushNotification = request.getPush_notification();

				for (int i = 0; i < students.size(); i++) {
					switch (pushNotification.getScreen_type()) {
						case SOCIO_EMOTIONAL_TEST: {
							Student student = students.get(i);
							student.setShould_force_socio_emotional_assessment(true);
							studentRepository.save(student);
							break;
						}
					}
				}

				if (request.isSaveToDB()) {

					pushNotification = pushNotifcationRepository.save(request.getPush_notification());

					if (request.getIds() == null || request.getIds().isEmpty()) {
						StudentPushNotification studentNotificationTemplate = new StudentPushNotification();
						studentNotificationTemplate.setStudent_id(0);
						studentNotificationTemplate.setPush_notification_id(pushNotification.getPush_notification_id());
						studentNotificationTemplate.setCreatedAt(new Date());
						studentPushNotificationRepository.save(studentNotificationTemplate);
					} else {

						for (int i = 0; i < students.size(); i++) {
							StudentPushNotification studentNotificationTemplate = new StudentPushNotification();
							studentNotificationTemplate.setStudent_id(students.get(i).getStudent_id());
							studentNotificationTemplate
									.setPush_notification_id(pushNotification.getPush_notification_id());
							studentNotificationTemplate.setCreatedAt(new Date());
							studentPushNotificationRepository.save(studentNotificationTemplate);
						}
					}
				}

				try {

					List<PushNotification> pushNotifications = new ArrayList<>();
					List<String> tokens = new ArrayList<>();
					for (int i = 0; i < students.size(); i++) {

						String fcmToken = students.get(i).getFcm_token();

						if (fcmToken == null || fcmToken.trim().isEmpty() || tokens.contains(fcmToken)) {
							continue;
						}

						PushNotification push_notification = new PushNotification();
						push_notification.setTitle(pushNotification.getTitle());
						push_notification.setMessage(pushNotification.getMessage());
						push_notification.setScreen_type(pushNotification.getScreen_type());
						push_notification.setToken(fcmToken);

						tokens.add(fcmToken);

						pushNotifications.add(push_notification);
					}

					pushNotificationService.sendPushNotifications(pushNotifications);

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

				Message message = new Message();
				message.setMessage("Notification has been sent.");

				return new ResponseEntity<Message>(message, HttpStatus.OK);
			}
		}

		throw new NotFoundException("User not found!!!");

	}
}
