package be.seeseepuff.allowanceplanner.service;

import be.seeseepuff.allowanceplanner.dto.CreateTaskRequest;
import be.seeseepuff.allowanceplanner.dto.TaskDto;
import be.seeseepuff.allowanceplanner.entity.History;
import be.seeseepuff.allowanceplanner.entity.Task;
import be.seeseepuff.allowanceplanner.entity.User;
import be.seeseepuff.allowanceplanner.repository.HistoryRepository;
import be.seeseepuff.allowanceplanner.repository.TaskRepository;
import be.seeseepuff.allowanceplanner.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.Optional;

@Service
public class TaskService {
    private final TaskRepository taskRepository;
    private final UserRepository userRepository;
    private final HistoryRepository historyRepository;
    private final AllowanceService allowanceService;

    public TaskService(TaskRepository taskRepository,
                       UserRepository userRepository,
                       HistoryRepository historyRepository,
                       AllowanceService allowanceService) {
        this.taskRepository = taskRepository;
        this.userRepository = userRepository;
        this.historyRepository = historyRepository;
        this.allowanceService = allowanceService;
    }

    @Transactional
    public int createTask(CreateTaskRequest request) {
        Task task = new Task();
        task.setName(request.name());
        task.setReward(Math.round((request.reward() != null ? request.reward() : 0.0) * 100.0));
        task.setAssigned(request.assigned());
        task = taskRepository.save(task);
        return task.getId();
    }

    public List<TaskDto> getTasks() {
        return taskRepository.findByCompletedIsNull().stream()
                .map(this::toDto)
                .toList();
    }

    public Optional<TaskDto> getTask(int taskId) {
        return taskRepository.findByIdAndCompletedIsNull(taskId)
                .map(this::toDto);
    }

    @Transactional
    public boolean updateTask(int taskId, CreateTaskRequest request) {
        Optional<Task> opt = taskRepository.findByIdAndCompletedIsNull(taskId);
        if (opt.isEmpty()) {
            return false;
        }
        Task task = opt.get();
        task.setName(request.name());
        task.setReward(Math.round((request.reward() != null ? request.reward() : 0.0) * 100.0));
        task.setAssigned(request.assigned());
        taskRepository.save(task);
        return true;
    }

    public boolean hasTask(int taskId) {
        return taskRepository.existsById(taskId);
    }

    @Transactional
    public void deleteTask(int taskId) {
        taskRepository.deleteById(taskId);
    }

    @Transactional
    public boolean completeTask(int taskId) {
        Optional<Task> opt = taskRepository.findById(taskId);
        if (opt.isEmpty()) {
            return false;
        }

        Task task = opt.get();
        long reward = task.getReward();
        String rewardName = task.getName();

        // Give reward to all users
        List<User> users = userRepository.findAll();
        for (User user : users) {
            // Add history entry
            History history = new History();
            history.setUserId(user.getId());
            history.setTimestamp(Instant.now().getEpochSecond());
            history.setAmount(reward);
            history.setDescription("Task completed: " + rewardName);
            historyRepository.save(history);

            // Distribute reward
            allowanceService.addDistributedReward(user.getId(), (int) reward);
        }

        // Mark task as completed
        task.setCompleted(Instant.now().getEpochSecond());
        taskRepository.save(task);

        return true;
    }

    private TaskDto toDto(Task t) {
        return new TaskDto(
                t.getId(),
                t.getName(),
                t.getReward() / 100.0,
                t.getAssigned(),
                t.getSchedule());
    }
}
