package com.infinite.focus.server.instructor;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import com.infinite.focus.server.auth.AccessCodeRepository;
import com.infinite.focus.server.auth.Account;
import com.infinite.focus.server.auth.AccessCode;
import com.infinite.focus.server.auth.AccountRepository;
import com.infinite.focus.server.auth.AvatarRepository;
import com.infinite.focus.server.auth.ChangePasswordRequest;
import com.infinite.focus.server.auth.EmailSenderService;
import com.infinite.focus.server.auth.Instructor;
import com.infinite.focus.server.auth.InstructorRepository;
import com.infinite.focus.server.auth.Message;
import com.infinite.focus.server.auth.SecurityConstants;
import com.infinite.focus.server.auth.Status;
import com.infinite.focus.server.auth.Student;
import com.infinite.focus.server.auth.StudentRepository;
import com.infinite.focus.server.auth.service.AuthService;
import com.infinite.focus.server.dashboard.userstats.UserStatsService;
import com.infinite.focus.server.home.DailyAppreciationRepository;
import com.infinite.focus.server.home.MoodUpdateRepository;
import com.infinite.focus.server.home.QuoteRepository;
import com.infinite.focus.server.students.ClassRepository;
import com.infinite.focus.server.utils.AppUtils;
import com.infinite.focus.server.wall.WallPostAttachmentRepository;
import com.infinite.focus.server.wall.WallPostRepository;
import com.infinite.focus.server.wall.WallPostRequestRepository;

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

public class InstructorController {
	
	 	private AccountRepository accountRepository;
		private StudentRepository studentRepository;
		private InstructorRepository instructorRepository;
		private AvatarRepository avatarRepository;
	    private BCryptPasswordEncoder bCryptPasswordEncoder;
	    private WallPostRepository wallPostRepository;
	    private WallPostAttachmentRepository wallPostAttachmentRepository;
	    private WallPostRequestRepository wallPostRequestRepository;
	    private QuoteRepository qouteRepository;
	    private MoodUpdateRepository moodUpdateRepository;
	    private DailyAppreciationRepository dailyAppreciationRepository;
	    private ClassRepository classRepository;
	    private AccessCodeRepository accessCodeRepository;
	    private EmailSenderService emailSenderService;
	    
	    @Autowired
		AuthService authService;
	    
	    public InstructorController(ClassRepository classRepository, DailyAppreciationRepository dailyAppreciationRepository, MoodUpdateRepository moodUpdateRepository, QuoteRepository qouteRepository, WallPostRepository wallPostRepository, WallPostAttachmentRepository wallPostAttachmentRepository, WallPostRequestRepository wallPostRequestRepository, AvatarRepository avatarRepository,
	    		InstructorRepository instructorRepository, StudentRepository studentRepository,AccountRepository accountRepository, BCryptPasswordEncoder bCryptPasswordEncoder,AccessCodeRepository accessCodeRepository, EmailSenderService emailSenderService) {
	    	
	    	this.classRepository = classRepository;
	    	this.qouteRepository = qouteRepository;
	    	this.wallPostRepository = wallPostRepository;
	    	this.wallPostAttachmentRepository = wallPostAttachmentRepository;
	    	this.wallPostRequestRepository = wallPostRequestRepository;
	    	this.avatarRepository = avatarRepository;
	    	this.bCryptPasswordEncoder= bCryptPasswordEncoder;
	    	this.instructorRepository = instructorRepository;
	    	this.studentRepository = studentRepository;
	    	this.accountRepository = accountRepository;
	    	this.moodUpdateRepository = moodUpdateRepository;
			this.dailyAppreciationRepository = dailyAppreciationRepository;
			this.accessCodeRepository = accessCodeRepository;
			this.emailSenderService = emailSenderService;

		}
	    
	    @GetMapping("/get/getAccessCodesByInstructorId")   
	    public ResponseEntity<Page<AccessCode>> getAccessCodesByInstructorId(
	    		 @RequestParam(value="instructor_id", defaultValue="aEn24") Long instructor_id,
	    		 @RequestParam(value="pageNo", defaultValue = "0") Integer pageNo, 
                 @RequestParam(value="pageSize", defaultValue = "10") Integer pageSize,
                 @RequestParam(value="sortBy", defaultValue = "access_code_id") String sortBy,
                 @RequestParam(value="status", defaultValue = "PENDING") String status){
	    	
	    	 Pageable paging = PageRequest.of(pageNo, pageSize, Sort.by(sortBy).ascending());
			 
		     Page<AccessCode> pagedResult = (Page<AccessCode>) accessCodeRepository.findByInstructorIdAndStatus(instructor_id,status.toString(),paging);
		         
		     return new ResponseEntity<Page<AccessCode>>(pagedResult,new HttpHeaders(), HttpStatus.OK);
	    }
	    
	    @PostMapping(value="/approve-access-code")
	  	public ResponseEntity<AccessCode> approveAccessCode(@RequestParam(value="instructor_id") long instructor_id, @RequestParam(value="access_code_id") Long access_code_id, @RequestParam(value="status") Status isApproved) {
	  	    	AccessCode accessCode = accessCodeRepository.findById(access_code_id).orElse(null);
	  			if(accessCode != null) {
	  				if(accessCode.getStudent().getInstructor_id() == instructor_id) {
	  					  						
	  					accessCode.setStatus(isApproved);
  				        accessCodeRepository.save(accessCode);
  				        
  						Account account = accountRepository.findByAccountId(accessCode.getStudent().getAccount_id());
  						
  						if(accessCode.getStatus() == Status.ACCEPTED) {
  							// create the email
  							SimpleMailMessage mailMessage = new SimpleMailMessage();
  							mailMessage.setTo(account.getUsername());
  							mailMessage.setSubject("Access code");
  							mailMessage.setText("To complete the registration process, please use this otp to verify your account "
  							+ accessCode.getAccessCode());
  							
  							emailSenderService.sendEmail(mailMessage);
  						}else {
  							
  						}
  						return new ResponseEntity<AccessCode>(accessCode,HttpStatus.OK);
	  				}
	  				return new ResponseEntity<AccessCode>(HttpStatus.NOT_FOUND);
	  			} else {	
	  				return new ResponseEntity<AccessCode>(HttpStatus.NOT_FOUND);
	  			}
	  }
	    
	@PostMapping("/send/email/to/all/instructors")
	public ResponseEntity<Message> sendEmailToAllInstructors(
			@RequestHeader(SecurityConstants.HEADER_STRING) String token,
			@RequestBody SendEmailRequest sendEmailRequest) {

		authService.isAdmin(token);

		if (AppUtils.isNullOrEmpty(sendEmailRequest.getSubject())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The subject is required.");
		}

		if (AppUtils.isNullOrEmpty(sendEmailRequest.getBody())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The body is required.");
		}

		List<String> instructorsEmails = instructorRepository.getAllInstructorsEmailAddresses();
		
		for (int i = 0; i < instructorsEmails.size(); i++) {
			String email = instructorsEmails.get(i);
			// System.out.println(i + " " + email);
            if (AppUtils.isNotNullOrEmpty(email)
                    && (email.contains("@mailinator.com") || email.contains("@yopmail.com"))) {
				System.out.println(email);
				// create the email
				try {
					SimpleMailMessage mailMessage = new SimpleMailMessage();
					mailMessage.setTo(email);
					mailMessage.setSubject(sendEmailRequest.getSubject());
					mailMessage.setText(sendEmailRequest.getBody() + "\n\nThanks,\r\n" + "Infinite Focus Schools");
					emailSenderService.sendEmail(mailMessage);
				} catch(Exception e) {
					e.printStackTrace();
				}
			}
		}

		Message message = new Message("Email has been sent to all Instructors.");

		return new ResponseEntity<Message>(message, HttpStatus.OK);
	}
	
	@PostMapping("/edit/profile")
	public ResponseEntity<Instructor> editProfile(
			@RequestHeader(SecurityConstants.HEADER_STRING) String token,
			@RequestBody Instructor instructor) {

		Instructor i = authService.isInstructor(token);

		if(i == null) {
			throw new ResponseStatusException(HttpStatus.NOT_FOUND, "The instructor is not found.");
		}
		
		if (AppUtils.isNullOrEmpty(instructor.getFirst_name())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The first name is required.");
		}

		if (AppUtils.isNullOrEmpty(instructor.getLast_name())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The last name is required.");
		}
		
		if (AppUtils.isNullOrEmpty(instructor.getState())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The state is required.");
		}
		
		if (AppUtils.isNullOrEmpty(instructor.getCity())) {
			throw new ResponseStatusException(HttpStatus.CONFLICT, "The city is required.");
		}
		
		i.setFirst_name(instructor.getFirst_name());
		i.setLast_name(instructor.getLast_name());
		i.setGrade_id(instructor.getGrade_id());
    	i.setStandard_id(instructor.getStandard_id());
    	i.setState(instructor.getState());
    	i.setCity(instructor.getCity());
		
		Instructor instru = instructorRepository.save(i); //Write to Table
        
        return new ResponseEntity<Instructor>(instru, HttpStatus.OK);
	}
}