package org.octopus.internal.services.impl

import org.octopus.internal.common.enums.EBusinessException
import org.octopus.internal.common.enums.EEntryType
import org.octopus.internal.common.exceptions.OctopusPlanningException
import org.octopus.internal.common.models.Entry
import org.octopus.internal.repositories.EntryRepository
import org.octopus.internal.services.EntryService
import org.octopus.internal.web.dtos.EntryDto
import org.springframework.stereotype.Service
import java.time.Month

@Service
class EntryServiceImpl(val repo: EntryRepository) : EntryService {
    override fun createEntry(entry: EntryDto): Entry {
        if (!verifyDto(entry)) {
            throw OctopusPlanningException.create(EBusinessException.INVALID_REQUEST, entry, "Entry must be either recurring or fixed.")
        }

        return repo.createEntry(Entry(
            id = 0L,
            name = entry.name,
            type = EEntryType.valueOf(entry.type),
            amount = entry.amount,
            fixedDate = entry.fixedDate,
            startDate = entry.startDate,
            endDate = entry.endDate,
            recurrent = entry.recurrent,
            recurrentMonths = entry.recurrentMonths?.map { m -> Month.of(m) }?.toList() ?: emptyList(),
            color = entry.color
        ))
    }

    override fun getAllEntries(): MutableList<Entry> {
        val income = repo.getAllByType(EEntryType.INCOME)
        val outcome = repo.getAllByType(EEntryType.OUTCOME)
        val invest = repo.getAllByType(EEntryType.INVESTMENT)
        return (income + outcome + invest).toMutableList()
    }

    override fun deleteAll(): Boolean {
        return repo.deleteAll()
    }

    override fun deleteById(id: Long): Boolean {
        return repo.deleteById(id)
    }

    override fun editEntry(id: Long, entry: EntryDto): Entry {
        if (!verifyDto(entry)) {
            throw OctopusPlanningException.create(EBusinessException.INVALID_REQUEST, entry, "Entry must be either recurring or fixed.")
        }

        return repo.createEntry(Entry(
            id = id,
            name = entry.name,
            type = EEntryType.valueOf(entry.type),
            amount = entry.amount,
            fixedDate = entry.fixedDate,
            startDate = entry.startDate,
            endDate = entry.endDate,
            recurrent = entry.recurrent,
            recurrentMonths = entry.recurrentMonths?.map { m -> Month.of(m) }?.toList() ?: emptyList(),
            color = entry.color
        ))
    }

    private fun verifyDto(entry: EntryDto): Boolean {
        val eventIsRecurring = entry.fixedDate == null &&
                entry.startDate != null &&
                entry.endDate != null &&
                entry.recurrent == true &&
                entry.recurrentMonths?.isNotEmpty() ?: false
        val eventIsFixed = entry.fixedDate != null &&
                entry.startDate == null &&
                entry.endDate == null &&
                entry.recurrent != true &&
                entry.recurrentMonths?.isEmpty() ?: true
        return eventIsRecurring || eventIsFixed
    }

}