package com.eshore.gringotts.web.domain.controller;

import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport;
import com.eshore.gringotts.web.domain.base.entity.FileInfo;
import com.eshore.gringotts.web.domain.base.entity.SimpleListItem;
import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem;
import com.eshore.gringotts.web.domain.entity.Authentication;
import com.eshore.gringotts.web.domain.service.AuthenticationService;
import com.eshore.gringotts.web.domain.service.DataFileService;
import com.eshore.gringotts.web.domain.service.DataResourceService;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Sets;
import org.eclipse.collections.api.set.ImmutableSet;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lanyuanxiaoyao
 * @date 2024-12-02
 */
@Slf4j
@RestController
@RequestMapping("authentication")
public class AuthenticationController extends SimpleControllerSupport<Authentication, AuthenticationController.SaveItem, AuthenticationController.ListItem, AuthenticationController.DetailItem> {
    private final AuthenticationService authenticationService;
    private final DataResourceService dataResourceService;
    private final DataFileService dataFileService;

    public AuthenticationController(AuthenticationService service, DataResourceService dataResourceService, DataFileService dataFileService) {
        super(service);
        this.authenticationService = service;
        this.dataResourceService = dataResourceService;
        this.dataFileService = dataFileService;
    }

    @GetMapping("/submit/{id}")
    public AmisResponse<Object> submit(@PathVariable Long id) throws JsonProcessingException {
        authenticationService.submit(id);
        return AmisResponse.responseSuccess();
    }

    @GetMapping("/retract/{id}")
    public AmisResponse<Object> retract(@PathVariable Long id) {
        authenticationService.retract(id);
        return AmisResponse.responseSuccess();
    }

    @Override
    protected Authentication fromSaveItem(SaveItem item) throws Exception {
        Authentication authentication = new Authentication();
        authentication.setId(item.getId());
        authentication.setDescription(item.getDescription());
        authentication.setTarget(dataResourceService.detailOrThrow(item.getTargetId()));
        authentication.setEvidences(dataFileService.list(item.getEvidenceFiles().collect(FileInfo::getValue)).toSet());
        authentication.setActiveTime(item.getActiveTime());
        authentication.setExpiredTime(item.getExpiredTime());
        return authentication;
    }

    @Override
    protected ListItem toListItem(Authentication entity) {
        return new ListItem(entity);
    }

    @Override
    protected DetailItem toDetailItem(Authentication entity) {
        return new DetailItem(entity);
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class SaveItem extends SimpleSaveItem<Authentication> {
        private Long targetId;
        private String description;
        private ImmutableSet<FileInfo> evidenceFiles;
        private LocalDateTime activeTime;
        private LocalDateTime expiredTime;
    }

    @Data
    @NoArgsConstructor
    @EqualsAndHashCode(callSuper = true)
    public static final class ListItem extends SimpleListItem<Authentication> {
        private String name;
        private String description;
        private String state;

        public ListItem(Authentication authentication) {
            this.setId(authentication.getId());
            this.setName(authentication.getTarget().getName());
            this.setDescription(authentication.getDescription());
            this.setState(authentication.getState().name());
            this.setCreatedUsername(authentication.getCreatedUser().getUsername());
            this.setCreatedTime(authentication.getCreatedTime());
        }
    }

    @Data
    @NoArgsConstructor
    @EqualsAndHashCode(callSuper = true)
    public static final class DetailItem extends SaveItem {
        private String targetName;
        private LocalDateTime createdTime;
        private String createdUsername;
        private LocalDateTime modifiedTime;
        private String modifiedUsername;

        public DetailItem(Authentication authentication) {
            this.setId(authentication.getId());
            this.setTargetId(authentication.getTarget().getId());
            this.setTargetName(authentication.getTarget().getName());
            this.setDescription(authentication.getDescription());
            this.setEvidenceFiles(Sets.immutable.ofAll(authentication.getEvidences()).collect(FileInfo::new));
            this.setActiveTime(authentication.getActiveTime());
            this.setExpiredTime(authentication.getExpiredTime());
            this.setCreatedTime(authentication.getCreatedTime());
            this.setCreatedUsername(authentication.getCreatedUser().getUsername());
            this.setModifiedTime(authentication.getModifiedTime());
            this.setModifiedUsername(authentication.getModifiedUser().getUsername());
        }
    }
}
