package com.zcloud.personnel.positioning.command;

import com.alibaba.cola.exception.BizException;
import com.zcloud.personnel.positioning.command.query.TerminalCardQueryExe;
import com.zcloud.personnel.positioning.domain.model.TerminalE;
import com.zcloud.personnel.positioning.dto.TerminalCardUpdateCmd;
import com.zcloud.personnel.positioning.dto.clientobject.TerminalCardCO;
import com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO;
import com.zcloud.personnel.positioning.persistence.dataobject.TerminalPersonSnapshotDO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

@Component
@AllArgsConstructor
public class TerminalCardUpdateExe {
    private static final String DEVICE_TYPE_CARD = "CARD";

    private final TerminalBindingService terminalBindingService;
    private final FindsPendingSyncService findsPendingSyncService;
    private final TerminalCardQueryExe terminalCardQueryExe;

    @Transactional(rollbackFor = Exception.class)
    public TerminalCardCO execute(TerminalCardUpdateCmd cmd) {
        if (cmd == null || cmd.getId() == null) {
            throw new BizException("Terminal card id is required");
        }
        TerminalE terminal = terminalBindingService.findTerminalById(cmd.getId());
        if (terminal == null || !DEVICE_TYPE_CARD.equalsIgnoreCase(terminal.getDeviceType())) {
            throw new BizException("Terminal card does not exist");
        }
        String oldTerminalNo = terminal.getTerminalNo();
        if (StringUtils.hasText(cmd.getTerminalNo()) && !cmd.getTerminalNo().trim().equals(oldTerminalNo)) {
            TerminalE duplicate = terminalBindingService.findTerminalByNo(cmd.getTerminalNo());
            if (duplicate != null && !duplicate.getId().equals(terminal.getId())) {
                throw new BizException("Terminal card no already exists");
            }
        }
        CorpInfoSnapshotDO corpInfo = terminalBindingService.resolveCorpInfo(cmd.getCorpinfoId(),
                cmd.getCorpinfoName(), cmd.getOrgCode(), cmd.getOrgName());
        applyUpdate(cmd, terminal, corpInfo);
        terminal.setSyncStatus(FindsPendingSyncService.STATUS_WAIT);
        terminal.setSyncToken(FindsSyncToken.next());
        terminalBindingService.updateTerminal(terminal);
        if (!oldTerminalNo.equals(terminal.getTerminalNo())) {
            terminalBindingService.moveActiveBindingTerminalNo(oldTerminalNo, terminal);
        }
        if (Boolean.TRUE.equals(cmd.getClearBind())) {
            terminalBindingService.unbindActiveBinding(terminal, true, LocalDateTime.now());
        } else {
            TerminalPersonSnapshotDO person = terminalBindingService.resolvePerson(cmd.getBindIdCardNo(),
                    cmd.getStaffNo(), cmd.getStaffName());
            if (person != null) {
                terminalBindingService.upsertActiveBinding(terminal, person, true, LocalDateTime.now());
            }
        }
        findsPendingSyncService.scheduleTerminal(terminal.getId());
        return terminalCardQueryExe.queryCardById(terminal.getId());
    }

    private void applyUpdate(TerminalCardUpdateCmd cmd, TerminalE terminal, CorpInfoSnapshotDO corpInfo) {
        if (StringUtils.hasText(cmd.getTerminalNo())) terminal.setTerminalNo(cmd.getTerminalNo().trim());
        if (cmd.getTerminalName() != null) terminal.setTerminalName(cmd.getTerminalName());
        if (cmd.getTerminalModel() != null) terminal.setTerminalModel(cmd.getTerminalModel());
        if (cmd.getSimCardNo() != null) terminal.setSimCardNo(cmd.getSimCardNo());
        if (cmd.getCheckCode() != null) terminal.setCheckCode(cmd.getCheckCode());
        if (cmd.getCorpinfoId() != null || corpInfo != null) {
            terminal.setCorpinfoId(corpInfo == null ? cmd.getCorpinfoId() : corpInfo.getCorpinfoId());
        }
        if (cmd.getCorpinfoName() != null || corpInfo != null) {
            terminal.setCorpinfoName(firstText(cmd.getCorpinfoName(), corpInfo == null ? null : corpInfo.getCorpName()));
        }
        if (cmd.getOrgCode() != null || corpInfo != null) {
            terminal.setOrgCode(firstText(cmd.getOrgCode(), corpInfo == null ? null : corpInfo.getCreditCode()));
        }
        if (cmd.getOrgName() != null || cmd.getCorpinfoName() != null || corpInfo != null) {
            terminal.setOrgName(firstText(cmd.getOrgName(), cmd.getCorpinfoName(),
                    corpInfo == null ? null : corpInfo.getCorpName()));
        }
        if (cmd.getEnable() != null) terminal.setEnable(cmd.getEnable());
        if (cmd.getRemarks() != null) terminal.setRemarks(cmd.getRemarks());
    }

    private String firstText(String... values) {
        for (String value : values) {
            if (StringUtils.hasText(value)) return value;
        }
        return null;
    }
}
