package com.infoclinika.pdx.controller;

import com.infoclinika.pdx.domain.user.SharedView;
import com.infoclinika.pdx.projection.SharedViewDto;
import com.infoclinika.pdx.service.exception.ApplicationException;
import com.infoclinika.pdx.service.user.SharedViewService;
import com.infoclinika.pdx.service.user.UserAccountService;
import com.infoclinika.pdx.specification.SharedViewListRequestDTO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

/**
 * Handles requests to get SharedView data.
 */
@RestController
@RequestMapping("/api/sharedview")
public class SharedViewController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final UserAccountService userAccountService;

    private final SharedViewService sharedViewService;

    /**
     * Constructor to provide required services.
     */
    @Autowired
    public SharedViewController(UserAccountService userAccountService, SharedViewService sharedViewService) {
        this.userAccountService = userAccountService;
        this.sharedViewService = sharedViewService;
    }

    /**
     * Creates new.
     */
    @PostMapping("/uritoken")
    public String createUriToken() {
        return UUID.randomUUID().toString();
    }

    /**
     * Creates new.
     */
    @PostMapping("/email/{sharedviewId}")
    public String sendEmail(@PathVariable("sharedviewId") long sharedViewId) throws ApplicationException {

        sharedViewService.sendEmail(sharedViewId);

        return "OK";
    }

    /**
     * Creates new.
     */
    @PostMapping
    public String create(@RequestBody CreateSharedViewRequest createViewReq) throws ApplicationException {

        SharedView view = new SharedView();

        view.setName(createViewReq.getName());
        view.setDescription(createViewReq.getDescription());
        view.setLink(createViewReq.getLink());
        view.setViewPayload(createViewReq.getPayload());
        view.setToken(createViewReq.getToken());

        long newSharedViewId = sharedViewService.create(view, createViewReq.getViewersIds()).getId();

        sharedViewService.sendEmail(newSharedViewId);

        return "OK";
    }

    /**
     * Updates.
     */
    @PutMapping
    public String update(@RequestBody CreateSharedViewRequest createViewReq) throws ApplicationException {
        SharedView view = new SharedView();

        view.setId(createViewReq.getId());
        view.setName(createViewReq.getName());
        view.setDescription(createViewReq.getDescription());

        List<Long> newViewersIds = sharedViewService.update(view, createViewReq.getViewersIds());

        sharedViewService.sendEmail(createViewReq.getId(), newViewersIds);

        return "OK";
    }

    /**
     * Returns by token.
     */
    @GetMapping("/{token}")
    public SharedViewDto getByToken(@PathVariable("token") String token) {
        return SharedViewDto.valueOf(sharedViewService.findByToken(token));
    }

    /**
     * Returns list for owner (as Spring data Page object).
     */
    @PostMapping("/list/owner")
    public Page<SharedViewDto> getListForOwner(@RequestBody SharedViewListRequestDTO pageRequest) {
        Page<SharedView> page = sharedViewService.getAllByOwner(PageRequest.of(pageRequest.getPage(), pageRequest.getPageSize(), StringUtils.isBlank(pageRequest.getSortBy()) ? Sort.unsorted() : Sort.by(pageRequest.isSortAsc() ? Sort.Direction.ASC : Sort.Direction.DESC, pageRequest.getSortBy())));
        return new PageImpl<SharedViewDto>(SharedViewDto.valueOf(page.getContent()), page.getPageable(), page.getTotalElements());
    }

    /**
     * Returns list for viewer (as Spring data Page object).
     */
    @PostMapping("/list/viewer")
    public Page<SharedViewDto> getListForViewer(@RequestBody SharedViewListRequestDTO pageRequest) {
        Page<SharedView> page = sharedViewService.getAllByViewer(PageRequest.of(pageRequest.getPage(), pageRequest.getPageSize(), StringUtils.isBlank(pageRequest.getSortBy()) ? Sort.unsorted() : Sort.by(pageRequest.isSortAsc() ? Sort.Direction.ASC : Sort.Direction.DESC, pageRequest.getSortBy())));
        return new PageImpl<SharedViewDto>(SharedViewDto.valueOf(page.getContent()), page.getPageable(), page.getTotalElements());
    }

    /**
     * Returns list for owner plus for viewer (as Spring data Page object).
     */
    @PostMapping("/list")
    public Page<SharedViewDto> getList(@RequestBody SharedViewListRequestDTO pageRequest) {

        switch (pageRequest.getFilterMode()) {

            case VIEWER:
                return getListForViewer(pageRequest);
            case ALL:
                Page<SharedView> page = sharedViewService.getAll(PageRequest.of(pageRequest.getPage(), pageRequest.getPageSize(), StringUtils.isBlank(pageRequest.getSortBy()) ? Sort.unsorted() : Sort.by(pageRequest.isSortAsc() ? Sort.Direction.ASC : Sort.Direction.DESC, pageRequest.getSortBy())));
                return new PageImpl<SharedViewDto>(SharedViewDto.valueOf(page.getContent()), page.getPageable(), page.getTotalElements());
            case OWNER_SHARED_ONLY:
                Page<SharedView> pageShared = sharedViewService.getAllByOwnerShared(PageRequest.of(pageRequest.getPage(), pageRequest.getPageSize(), StringUtils.isBlank(pageRequest.getSortBy()) ? Sort.unsorted() : Sort.by(pageRequest.isSortAsc() ? Sort.Direction.ASC : Sort.Direction.DESC, pageRequest.getSortBy())));
                return new PageImpl<SharedViewDto>(SharedViewDto.valueOf(pageShared.getContent()), pageShared.getPageable(), pageShared.getTotalElements());
            default:
                return getListForOwner(pageRequest);
        }

    }

    @DeleteMapping("/{sharedviewId}")
    public String delete(@PathVariable("sharedviewId") long sharedViewId) throws ApplicationException {
        sharedViewService.delete(sharedViewService.findById(sharedViewId));

        return "OK";
    }

    public static class CreateSharedViewRequest {
        private long id;
        private String name;
        private String description;
        private String payload;
        private String link;
        private String token;

        private List<Long> viewersIds;

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String getPayload() {
            return payload;
        }

        public void setPayload(String payload) {
            this.payload = payload;
        }

        public String getLink() {
            return link;
        }

        public void setLink(String link) {
            this.link = link;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public List<Long> getViewersIds() {
            return viewersIds;
        }

        public void setViewersIds(List<Long> viewersIds) {
            this.viewersIds = viewersIds;
        }
    }
}
