package com.aegis.resource.requisition.domain;

import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import com.aegis.common.core.domain.BaseEntity;
import com.aegis.common.exception.ServiceException;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * 征用申请实体类 resource_requisition
 * 
 * @author aegis
 */
@Getter
@Setter
@ToString(callSuper = true)
public class Requisition extends BaseEntity {
    
    private static final long serialVersionUID = 1L;

    /** 征用ID */
    private Long id;

    /** 队伍ID */
    private Long teamId;

    /** 队伍名称（关联查询，不持久化） */
    private transient String teamName;

    /** 征用编号 */
    private String requisitionNo;

    /** 征用原因 */
    private String reason;

    /** 状态：draft-草稿，approved-已审批，active-进行中，ended-已结束，rejected-已驳回 */
    private String status;

    /** 开始时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date startAt;

    /** 结束时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endAt;

    /** 审批人ID */
    private Long approverId;

    /** 审批人姓名 */
    private String approverName;

    /** 审批时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date approvedAt;

    /** 审批意见 */
    private String approvalComment;

    /** 删除标志（0代表存在 2代表删除） */
    private String delFlag;

    /**
     * 初始化默认值
     * 
     * @param operator 操作人
     */
    public void initializeDefaults(String operator) {
        if (StringUtils.isBlank(this.status)) {
            this.status = RequisitionStatus.DRAFT.getCode();
        }
    }

    /**
     * 审批通过（draft → approved）
     * 
     * @param approverId 审批人ID
     * @param approverName 审批人姓名
     * @param comment 审批意见
     * @param operator 操作人
     */
    public void approve(Long approverId, String approverName, String comment, String operator) {
        this.ensureNotDeleted();
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.DRAFT.equals(current)) {
            throw new ServiceException("只有草稿状态的征用申请才能审批");
        }
        this.setStatusEnum(RequisitionStatus.APPROVED);
        this.approverId = approverId;
        this.approverName = approverName;
        this.approvedAt = new Date();
        this.approvalComment = comment;
        this.touch(operator);
    }

    /**
     * 审批驳回（draft → rejected）
     * 
     * @param approverId 审批人ID
     * @param approverName 审批人姓名
     * @param comment 审批意见
     * @param operator 操作人
     */
    public void reject(Long approverId, String approverName, String comment, String operator) {
        this.ensureNotDeleted();
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.DRAFT.equals(current)) {
            throw new ServiceException("只有草稿状态的征用申请才能审批");
        }
        this.setStatusEnum(RequisitionStatus.REJECTED);
        this.approverId = approverId;
        this.approverName = approverName;
        this.approvedAt = new Date();
        this.approvalComment = comment;
        this.touch(operator);
    }

    /**
     * 开始征用（approved → active）
     * 
     * @param operator 操作人
     */
    public void start(String operator) {
        this.ensureNotDeleted();
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.APPROVED.equals(current)) {
            throw new ServiceException("只有已审批状态的征用申请才能开始征用");
        }
        if (this.startAt == null) {
            throw new ServiceException("开始时间不能为空");
        }
        this.setStatusEnum(RequisitionStatus.ACTIVE);
        this.touch(operator);
    }

    /**
     * 结束征用（active → ended）
     * 
     * @param operator 操作人
     */
    public void end(String operator) {
        this.ensureNotDeleted();
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.ACTIVE.equals(current)) {
            throw new ServiceException("只有进行中状态的征用申请才能结束征用");
        }
        if (this.endAt == null) {
            this.endAt = new Date();
        }
        this.setStatusEnum(RequisitionStatus.ENDED);
        this.touch(operator);
    }

    /**
     * 标记为已删除
     * 
     * @param operator 操作人
     */
    public void markDeleted(String operator) {
        if (this.isDeleted()) {
            return;
        }
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.DRAFT.equals(current) && !RequisitionStatus.REJECTED.equals(current)) {
            throw new ServiceException("只有草稿或已驳回状态的征用申请才能删除");
        }
        this.delFlag = DEL_FLAG_DELETED;
        this.touch(operator);
    }

    /**
     * 恢复（取消删除）
     * 
     * @param operator 操作人
     */
    public void restore(String operator) {
        if (this.isDeleted()) {
            this.delFlag = DEL_FLAG_NORMAL;
            this.touch(operator);
        }
    }

    /**
     * 修改征用原因
     * 
     * @param newReason 新原因
     * @param operator 操作人
     */
    public void changeReason(String newReason, String operator) {
        this.ensureNotDeleted();
        this.ensureEditable();
        if (StringUtils.isNotBlank(newReason) && newReason.length() > 500) {
            throw new ServiceException("征用原因长度不能超过500个字符");
        }
        this.reason = newReason;
        this.touch(operator);
    }

    /**
     * 修改备注
     * 
     * @param remark 备注
     * @param operator 操作人
     */
    public void changeRemark(String remark, String operator) {
        this.ensureNotDeleted();
        if (StringUtils.isNotBlank(remark) && remark.length() > 500) {
            throw new ServiceException("备注长度不能超过500个字符");
        }
        this.setRemark(remark);
        this.touch(operator);
    }

    /**
     * 重新提交（rejected → approved）
     * 驳回后修改完成，直接提交为已审批状态
     * 
     * @param operator 操作人
     */
    public void resubmit(String operator) {
        this.ensureNotDeleted();
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.REJECTED.equals(current)) {
            throw new ServiceException("只有已驳回状态的征用申请才能重新提交");
        }
        // 直接提交为已审批状态，跳过审批流程
        this.setStatusEnum(RequisitionStatus.APPROVED);
        // 保留之前的审批信息，或者清空后重新设置（根据业务需求）
        // 这里保留审批信息，表示已经审批过
        this.touch(operator);
    }

    /**
     * 确保征用申请未被删除
     */
    public void ensureNotDeleted() {
        if (this.isDeleted()) {
            throw new ServiceException("已删除的征用申请不允许该操作");
        }
    }

    /**
     * 确保征用申请可编辑（草稿和驳回状态可编辑）
     */
    public void ensureEditable() {
        RequisitionStatus current = this.getStatusEnum();
        if (!RequisitionStatus.DRAFT.equals(current) && !RequisitionStatus.REJECTED.equals(current)) {
            throw new ServiceException("只有草稿或已驳回状态的征用申请才能编辑");
        }
    }

    /**
     * 检查是否已删除
     * 
     * @return 是否已删除
     */
    private boolean isDeleted() {
        return DEL_FLAG_DELETED.equals(delFlag);
    }

    /**
     * 获取状态枚举
     * 
     * @return 状态枚举
     */
    public RequisitionStatus getStatusEnum() {
        return RequisitionStatus.fromCode(status);
    }

    /**
     * 设置状态枚举
     * 
     * @param status 状态枚举
     */
    private void setStatusEnum(RequisitionStatus status) {
        this.status = status.getCode();
    }

    /**
     * 更新操作信息
     * 
     * @param operator 操作人
     */
    private void touch(String operator) {
        this.setUpdateBy(operator);
        this.setUpdateTime(new Date());
    }

    private static final String DEL_FLAG_NORMAL = "0";
    private static final String DEL_FLAG_DELETED = "2";

    /**
     * 征用状态枚举
     */
    public enum RequisitionStatus {
        DRAFT("draft", "草稿"),
        APPROVED("approved", "已审批"),
        ACTIVE("active", "进行中"),
        ENDED("ended", "已结束"),
        REJECTED("rejected", "已驳回");

        private final String code;
        private final String label;

        RequisitionStatus(String code, String label) {
            this.code = code;
            this.label = label;
        }

        public String getCode() {
            return code;
        }

        public String getLabel() {
            return label;
        }

        public static RequisitionStatus fromCode(String code) {
            if (StringUtils.isBlank(code)) {
                return DRAFT;
            }
            for (RequisitionStatus value : values()) {
                if (value.code.equals(code)) {
                    return value;
                }
            }
            return DRAFT;
        }
    }
}