package com.wismna.geoffroy.donext.data.local.repository

import com.wismna.geoffroy.donext.data.local.dao.TaskDao
import com.wismna.geoffroy.donext.data.local.dao.TaskListDao
import com.wismna.geoffroy.donext.data.toDomain
import com.wismna.geoffroy.donext.data.toEntity
import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.domain.model.TaskList
import com.wismna.geoffroy.donext.domain.model.TaskListWithOverdue
import com.wismna.geoffroy.donext.domain.model.TaskWithListName
import com.wismna.geoffroy.donext.domain.repository.TaskRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import kotlin.collections.map

class TaskRepositoryImpl @Inject constructor(
    private val taskDao: TaskDao,
    private val taskListDao: TaskListDao
): TaskRepository {
    override fun getTasksForList(listId: Long): Flow<List<Task>> {
        return taskDao.getTasksForList(listId).map {entity -> entity.map { it.toDomain() }}
    }

    override fun getDueTodayTasks(todayStart: Long, todayEnd: Long): Flow<List<Task>> {
        return taskDao.getDueTodayTasks(todayStart, todayEnd).map {entity -> entity.map { it.toDomain() }}
    }

    override fun getDeletedTasks(): Flow<List<TaskWithListName>> {
        return taskDao.getDeletedTasksWithListName().map {entity -> entity.map { it.toDomain() }}
    }

    override suspend fun getTaskById(taskId: Long): Task? {
        return taskDao.getTaskById(taskId)?.toDomain()
    }

    override suspend fun insertTask(task: Task) {
        taskDao.insertTask(task.toEntity())
    }

    override suspend fun updateTask(task: Task) {
        taskDao.updateTask(task.toEntity())
    }

    override suspend fun toggleTaskDeleted(taskId: Long, isDeleted: Boolean) {
        taskDao.toggleTaskDeleted(taskId, isDeleted)
    }

    override suspend fun toggleTaskDone(taskId: Long, isDone: Boolean) {
        taskDao.toggleTaskDone(taskId, isDone)
    }

    override suspend fun permanentlyDeleteTask(taskId: Long) {
        taskDao.permanentDeleteTask(taskId)
    }

    override suspend fun permanentlyDeleteAllDeletedTask() {
        taskDao.permanentDeleteAllDeletedTasks()
    }

    override fun getTaskLists(): Flow<List<TaskList>> {
        return taskListDao.getTaskLists().map {entities -> entities.map { it.toDomain() }}
    }

    override suspend fun getTaskListById(taskListId: Long): TaskList? {
        return taskListDao.getTaskListById(taskListId)?.toDomain()
    }

    override suspend fun insertTaskList(taskList: TaskList) {
        taskListDao.insertTaskList(taskList.toEntity())
    }

    override suspend fun updateTaskList(taskList: TaskList) {
        taskListDao.updateTaskList(taskList.toEntity())
    }

    override suspend fun deleteTaskList(taskListId: Long, isDeleted: Boolean) {
        taskDao.toggleAllTasksFromListDeleted(taskListId, isDeleted)
        taskListDao.deleteTaskList(taskListId, isDeleted)
    }

    override fun getTaskListsWithOverdue(nowMillis: Long): Flow<List<TaskListWithOverdue>> {
        return taskListDao.getTaskListsWithOverdue(nowMillis).map { it }
    }
}