package de.thpeetz.kontor.comics.services;

import java.util.List;

import de.thpeetz.kontor.comics.data.*;
import de.thpeetz.kontor.comics.repository.*;
import de.thpeetz.kontor.common.views.FilterOption;
import de.thpeetz.kontor.common.views.SearchFilter;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ComicService {

    private final PublisherRepository publisherRepository;
    private final ComicRepository comicRepository;
    private final ArtistRepository artistRepository;
    private final IssueRepository issueRepository;
    private final StoryArcRepository storyArcRepository;
    private final TradePaperbackRepository tradePaperbackRepository;
    private final ComicWorkRepository comicWorkRepository;
    private final IssueWorkRepository issueWorkRepository;
    private final VolumeRepository volumeRepository;
    private final WorktypeRepository worktypeRepository;

    public ComicService(PublisherRepository publisherRepository, ComicRepository comicRepository,
            ArtistRepository artistRepository, IssueRepository issueRepository, StoryArcRepository storyArcRepository,
            TradePaperbackRepository tradePaperbackRepository, ComicWorkRepository comicWorkRepository, IssueWorkRepository issueWorkRepository,
            VolumeRepository volumeRepository, WorktypeRepository worktypeRepository) {

        this.publisherRepository = publisherRepository;
        this.comicRepository = comicRepository;
        this.artistRepository = artistRepository;
        this.issueRepository = issueRepository;
        this.storyArcRepository = storyArcRepository;
        this.tradePaperbackRepository = tradePaperbackRepository;
        this.comicWorkRepository = comicWorkRepository;
        this.issueWorkRepository = issueWorkRepository;
        this.volumeRepository = volumeRepository;
        this.worktypeRepository = worktypeRepository;
    }

    public List<Publisher> findAllPublishers(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return publisherRepository.findAll();
        } else {
            return publisherRepository.search(stringFilter);
        }
    }

    public Publisher findPublisherByName(String publisherName) {
        return publisherRepository.findByName(publisherName);
    }

    public void deletePublisher(Publisher publisher) {
        publisherRepository.delete(publisher);
    }

    public void savePublisher(Publisher publisher) {
        if (publisher == null) {
            log.warn("Publisher is null. Are you sure you have connected your form to the application?");
            return;
        }
        publisherRepository.save(publisher);
    }

    public List<Comic> findAllComics(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return comicRepository.findAll();
        } else {
            return comicRepository.search(stringFilter);
        }
    }
    public List<Comic> findAllComicsByFilter(SearchFilter searchFilter) {
        if (searchFilter == null) return comicRepository.findAll();
        if (searchFilter.getFilterOptions().isEmpty()) return comicRepository.search(searchFilter.getSearchTerm());
        if (searchFilter.getFilterOptions().size() == 1) {
            FilterOption option = searchFilter.getFilterOptions().getFirst();
            if (searchFilter.getSearchTerm() != null && !searchFilter.getSearchTerm().isEmpty()) {
                switch (option.getName()) {
                    case "Bestellung":
                        return comicRepository.searchAndFilterByCurrentOrder(searchFilter.getSearchTerm(), option.getValue());
                    case "Abgeschlossen":
                        return comicRepository.searchAndFilterByCompleted(searchFilter.getSearchTerm(), option.getValue());
                }
            }
            switch (option.getName()) {
                case "Bestellung":
                    return comicRepository.findByCurrentOrder(option.getValue());
                case "Abgeschlossen":
                    return comicRepository.findByCompleted(option.getValue());
            }
        }
        if (searchFilter.getFilterOptions().size() == 2) {
            if (searchFilter.getSearchTerm() != null && !searchFilter.getSearchTerm().isEmpty()) {
                return comicRepository.search(searchFilter.getSearchTerm(),
                        searchFilter.getFilter("Bestellung").getValue(),
                        searchFilter.getFilter("Abgeschlossen").getValue());
            }
            return comicRepository.findByCurrentOrderAndCompleted(searchFilter.getFilter("Bestellung").getValue(),
                    searchFilter.getFilter("Abgeschlossen").getValue());
        }
        return comicRepository.findAll();
    }


    public Comic findComicByTitle(String title) {
        List<Comic> comics = comicRepository.findByTitle(title);
        if (comics.size() == 1) {
            return comics.get(0);
        }
        return null;
    }

    public void deleteComic(Comic comic) {
        Publisher publisher = comic.getPublisher();
        publisher.getComics().remove(comic);
        publisherRepository.save(publisher);
        comicRepository.delete(comic);
    }

    public void saveComic(Comic comic) {
        if (comic == null) {
            log.warn("Comic is null. Are you sure you have connected your form to the application?");
            return;
        }
        comicRepository.save(comic);
    }

    public List<Artist> findAllArtists(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return artistRepository.findAll();
        } else {
            return artistRepository.search(stringFilter);
        }
    }

    public Artist findArtistByName(String artistName) {
        if (artistName == null || artistName.isEmpty()) {
            return null;
        } else {
            return artistRepository.findByName(artistName);
        }
    }

    public void deleteArtist(Artist artist) {
        artistRepository.delete(artist);
    }

    public void saveArtist(Artist artist) {
        if (artist == null) {
            log.warn("Artist is null. Are you sure you have connected your form to the application?");
            return;
        }
        artistRepository.save(artist);
    }

    public List<Issue> findAllIssues() {
        return issueRepository.findAll();
    }

    public List<Issue> findAllIssuesForComic(Comic comic) {
        if (comic == null) {
            return issueRepository.findAll();
        } else {
            log.info("Find issues for Comic: {}", comic);
            return issueRepository.findByComic(comic);
        }
    }

    public void saveIssue(Issue issue) {
        if (issue == null) {
            log.warn("Issue is null. Are you sure you have connected your form to the application?");
            return;
        }
        issueRepository.save(issue);
    }

    public void deleteIssue(Issue issue) {
        issueRepository.delete(issue);
    }

    public List<StoryArc> findAllStoryArcs() {
        return storyArcRepository.findAll();
    }

    public List<StoryArc> findAllStoryArcsForComic(Comic comic) {
        if (comic == null) {
            return storyArcRepository.findAll();
        } else {
            log.info("Find Story Arc for Comic: {}", comic);
            return storyArcRepository.findByComic(comic);
        }
    }

    public void saveStoryArc(StoryArc storyArc) {
        storyArcRepository.save(storyArc);
    }

    public void deleteStoryArc(StoryArc storyArc) {
        Comic comic = storyArc.getComic();
        comic.getStoryArcs().remove(storyArc);
        comicRepository.save(comic);
        storyArcRepository.delete(storyArc);
    }

    public List<TradePaperback> findAllTradePaperbacks(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return tradePaperbackRepository.findAll();
        } else {
            return tradePaperbackRepository.search(stringFilter);
        }
    }

    public void deleteTradePaperBack(TradePaperback tradepaperback) {
        tradePaperbackRepository.delete(tradepaperback);
    }

    public void saveTradePaperBack(TradePaperback tradepaperback) {
        if (tradepaperback == null) {
            log.warn("TradePaperBack is null. Are you sure you have connected your form to the application?");
            return;
        }
        tradePaperbackRepository.save(tradepaperback);
    }

    public List<ComicWork> findAllComicWorks() {
        return comicWorkRepository.findAll();
    }

    public void saveComicWork(ComicWork comicWork) {
        if (comicWork == null) {
            log.warn("ComicWork is null. Are you sure you have connected your form to the application?");
            return;
        }
        comicWorkRepository.save(comicWork);
    }

    public void deleteComicWork(ComicWork comicWork) {
        Comic comic = comicWork.getComic();
        comic.getComicWorks().remove(comicWork);
        comicRepository.save(comic);
        Artist artist = comicWork.getArtist();
        artist.getComicWorks().remove(comicWork);
        artistRepository.save(artist);
        Worktype worktype = comicWork.getWorkType();
        worktype.getComicWorks().remove(comicWork);
        worktypeRepository.save(worktype);
        comicWorkRepository.delete(comicWork);
    }

    public List<IssueWork> findAllIssueWorks() {
        return issueWorkRepository.findAll();
    }

    public void saveIssueWork(IssueWork issueWork) {
        if (issueWork == null) {
            log.warn("IssueWork is null. Are you sure you have connected your form to the application?");
            return;
        }
        issueWorkRepository.save(issueWork);
    }

    public void deleteIssueWork(IssueWork issueWork) {
        Issue issue = issueWork.getIssue();
        issue.getIssueWorks().remove(issueWork);
        issueRepository.save(issue);
        Artist artist = issueWork.getArtist();
        artist.getIssueWorks().remove(issueWork);
        artistRepository.save(artist);
        Worktype worktype = issueWork.getWorkType();
        worktype.getIssueWorks().remove(issueWork);
        worktypeRepository.save(worktype);
        issueWorkRepository.delete(issueWork);
    }

    public List<Volume> findAllVolumes() {
        return volumeRepository.findAll();
    }

    public List<Volume> findAllVolumesForComic(Comic comic) {
        if (comic == null) {
            return volumeRepository.findAll();
        } else {
            log.info("Find Volume for Comic: {}", comic);
            return volumeRepository.findByComic(comic);
        }
    }

    public void saveVolume(Volume volume) {
        if (volume == null) {
            log.warn("Volume is null. Are you sure you have connected your form to the application?");
            return;
        }
        volumeRepository.save(volume);
    }

    public void deleteVolume(Volume volume) {
        Comic comic = volume.getComic();
        comic.getVolumes().remove(volume);
        comicRepository.save(comic);
        volumeRepository.delete(volume);
    }

    public List<Worktype> findAllWorktypes(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return worktypeRepository.findAll();
        } else {
            return worktypeRepository.search(stringFilter);
        }
    }

    public Worktype findWorktypeByName(String worktypeName) {
        if (worktypeName == null || worktypeName.isEmpty()) {
            return null;
        } else {
            return worktypeRepository.findByName(worktypeName);
        }
    }

    public void saveWorktype(Worktype worktype) {
        if (worktype == null) {
            log.warn("Worktype is null. Are you sure you have connected your form to the application?");
            return;
        }
        worktypeRepository.save(worktype);
    }

    public void deleteWorktype(Worktype worktype) {
        List<ComicWork> comicWorks = worktype.getComicWorks();
        List<IssueWork> issueWorks = worktype.getIssueWorks();
        if (comicWorks == null) {
            log.warn("reference to ComicWork is null");
        } else {
            log.info("found {} references to ComicWork", comicWorks.size());
            comicWorks.forEach(comicWork -> {
                comicWork.setWorkType(null);
            });
        }
        if (issueWorks == null) {
            log.warn("reference to ComicWork is null");
        } else {
            log.info("found {} references to IssueWork", issueWorks.size());
            issueWorks.forEach(issueWork -> {
                issueWork.setWorkType(null);
            });
        }
        log.info("delete Worktype: {}", worktype);
        worktypeRepository.delete(worktype);
    }
}
