package com.realnet.scheduler.services;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
//import org.springframework.scheduling.support.CronExpression;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.realnet.DataLake.Entity.Data_lake;
import com.realnet.DataLake.Services.DataLakeActionService;
import com.realnet.DataLake.Services.Data_lakeService;
import com.realnet.scheduler.Entity.JobEntity;
import com.realnet.scheduler.Repository.JobRepository;

@Service
public class SmartSchedulerService {

	private final TaskScheduler scheduler;
	private final Map<Long, ScheduledFuture<?>> runningTasks = new ConcurrentHashMap<>();

	@Autowired
	private JobRepository jobRepository;

	public SmartSchedulerService() {
		ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
		taskScheduler.setPoolSize(5);
		taskScheduler.initialize();
		this.scheduler = taskScheduler;
	}

	// 🔹 Load jobs from DB on startup
//	@PostConstruct
//	public void init() {
//		System.out.println("🔁 Loading jobs from DB...");
//		jobRepository.findAll().forEach(job -> {
//			if ("RUNNING".equalsIgnoreCase(job.getStatus()) && job.getCronExpression() != null) {
//				startJob(job);
//			}
//		});
//	}

//	@EventListener(ApplicationReadyEvent.class)
//	public void onApplicationReady() {
//		System.out.println("🚀 Application started! Loading jobs from DB...");
//		jobRepository.findAll().forEach(job -> {
//			if ("RUNNING".equalsIgnoreCase(job.getStatus()) && job.getCronExpression() != null) {
//				startJob(job);
//			}
//		});
//	}

	// 🔹 Start or schedule a job
	public JobEntity createAndStartJob(JobEntity job) {

		JobEntity existingjob = jobRepository.getBylakeId(job.getLakeid());
		if (existingjob != null) {
			job = existingjob;
			if (existingjob.getCronExpression() == null) {
				Integer lakeid = job.getLakeid();
				Data_lake data_lake = lakeService.getdetailsbyId(lakeid);
				String cron_job = data_lake.getCron_job();
				job.setCronExpression(cron_job);
//				job = jobRepository.save(job);
			}

		} else {
			Integer lakeid = job.getLakeid();
			Data_lake data_lake = lakeService.getdetailsbyId(lakeid);
			String cron_job = data_lake.getCron_job();
			job.setCronExpression(cron_job);
//			job = jobRepository.save(job);
		}

//		JobEntity job = new JobEntity(name, cron, "RUNNING", description);
		job.setStatus("RUNNING");
		job = jobRepository.save(job); // Auto-generated ID
		startJob(job);
		return job;
	}

//	private void startJob(JobEntity job) {
//		ScheduledFuture<?> future = scheduler.schedule(
//				
//				() -> System.out.println(
//						"Running job: " + job.getName() + " [" + job.getId() + "] at " + java.time.LocalDateTime.now()),
//				new CronTrigger(job.getCronExpression()));
//		runningTasks.put(job.getId(), future);
//		System.out.println("✅ Job started: " + job.getName() + " | ID: " + job.getId());
//	}

	// 🔹 Pause job
	public void pauseJob(Long id) {
		ScheduledFuture<?> future = runningTasks.get(id);
		if (future != null) {
			future.cancel(true);
			runningTasks.remove(id);
		}
		jobRepository.findById(id).ifPresent(job -> {
			job.setStatus("PAUSED");
			jobRepository.save(job);
			System.out.println("⏸️ Job paused: " + job.getName());
		});
	}

	// 🔹 Resume job
	public void resumeJob(Long id) {
		jobRepository.findById(id).ifPresent(job -> {
			if ("PAUSED".equalsIgnoreCase(job.getStatus())) {
				startJob(job);
				job.setStatus("RUNNING");
				jobRepository.save(job);
				System.out.println("▶️ Job resumed: " + job.getName());
			}
		});
	}

	// 🔹 Stop job completely
	public void stopJob(Long id) {
		pauseJob(id);
		jobRepository.findById(id).ifPresent(job -> {
			job.setStatus("STOPPED");
			jobRepository.save(job);
			System.out.println("🛑 Job stopped: " + job.getName());
		});
	}

	public void listJobs() {
		jobRepository.findAll().forEach(job -> System.out.println(
				job.getId() + " | " + job.getName() + " | " + job.getStatus() + " | " + job.getCronExpression()));
	}

	private void startJob(JobEntity job) {
		// Step 1: Validate cron expression before scheduling
//		if (job.getCronExpression() == null || !isValidCron(job.getCronExpression())) {
//			System.err.println("❌ Invalid or missing cron expression for job: " + job.getName());
//			job.setStatus("FAILED");
//			jobRepository.save(job);
//			return;
//		}
		Runnable task;

		switch (job.getJobType()) {
		case "DATALAKE":
			task = () -> {
				try {
					setdatalake(job);
				} catch (JsonProcessingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			};
			break;
		case "EMAIL":
			task = () -> sendEmailJob(job);
			break;
		case "REPORT":
			task = () -> generateReport(job);
			break;
		case "SYNC":
			task = () -> {
				try {
					setdatalake(job);
				} catch (JsonProcessingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			};
			break;
		default:
			task = () -> System.out.println("⚙️ Running generic job: " + job.getName());
		}

//		ScheduledFuture<?> future = scheduler.schedule(task, new CronTrigger(job.getCronExpression()));
//		runningTasks.put(job.getId(), future);
//		System.out.println("✅ Job started: " + job.getName() + " | ID: " + job.getId());

		try {
			ScheduledFuture<?> future = scheduler.schedule(task, new CronTrigger(job.getCronExpression()));
			runningTasks.put(job.getId(), future);
			System.out.println("✅ Job started: " + job.getName() + " | ID: " + job.getId());
			job.setStatus("RUNNING");
			jobRepository.save(job);
		} catch (Exception e) {
			System.err.println("🚨 Failed to schedule job: " + job.getName());
			e.printStackTrace();
			job.setStatus("FAILED");
			jobRepository.save(job);
		}
	}

//	private boolean isValidCron(String cron) {
//		try {
//			CronExpression.parse(cron);
//			return true;
//		} catch (Exception e) {
//			return false;
//		}
//	}

	@Autowired
	private Data_lakeService lakeService;

	@Autowired
	private DataLakeActionService lakeActionService;

	// Sample tasks
	private void setdatalake(JobEntity job) throws JsonProcessingException {

		Integer lakeid = job.getLakeid();
//		Data_lake data_lake = lakeService.getdetailsbyId(lakeid);
//		String cron_job = data_lake.getCron_job();
//		job.setCronExpression(cron_job);
//		jobRepository.save(job);
		Data_lake update = lakeActionService.applyCalculation(lakeid);

		System.out.println("📧 Start Data Lake..." + update.getName() + " [" + job.getName() + "]");
		// your email service logic here
	}

	private void sendEmailJob(JobEntity job) {
		System.out.println("📧 Sending emails... [" + job.getName() + "]");
		// your email service logic here
	}

	private void generateReport(JobEntity job) {
		System.out.println("📊 Generating report... [" + job.getName() + "]");
		// call report service, save file, etc.
	}

	private void syncData(JobEntity job) {
		System.out.println("🔄 Syncing data from API... [" + job.getName() + "]");
		// hit API, update DB, etc.
	}

	public JobEntity getByLakeId(Integer lakeId) {
		JobEntity job = jobRepository.getBylakeId(lakeId);
		return job;

	}

}
