package com.aegis.resource.equipment.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.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * 装备实体类 resource_equipment
 * 
 * @author aegis
 */
@Getter
@Setter
@ToString(callSuper = true)
public class Equipment extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /** 装备ID */
    private Long id;

    /** 装备编码 */
    private String equipmentCode;

    /** 装备名称 */
    private String equipmentName;

    /** 装备类型 */
    private String equipmentType;

    /** 品牌 */
    private String brand;

    /** 型号 */
    private String model;

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

    /** 所属仓库ID */
    private Long warehouseId;

    /** 所属队伍名称（关联查询字段，不存储） */
    @TableField(exist = false)
    private String teamName;

    /** 所属仓库名称（关联查询字段，不存储） */
    @TableField(exist = false)
    private String warehouseName;

    /** 状态：available-可用，busy-占用，repair-维修，scrap-报废 */
    private String status;

    /** 能力标签（JSON数组，存储格式） */
    private String capabilities;

    /** 采购日期 */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;

    /** 保修到期日期 */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date warrantyDate;

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

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

    /**
     * 从源对象创建新装备（用于复制）
     * 
     * @param source 源装备
     * @param operator 操作人
     * @return 新装备对象
     */
    public static Equipment createFrom(Equipment source, String operator) {
        Equipment equipment = new Equipment();
        equipment.setEquipmentCode(source.getEquipmentCode());
        equipment.setEquipmentName(source.getEquipmentName());
        equipment.setEquipmentType(source.getEquipmentType());
        equipment.setBrand(source.getBrand());
        equipment.setModel(source.getModel());
        equipment.setTeamId(source.getTeamId());
        equipment.setWarehouseId(source.getWarehouseId());
        equipment.setCapabilities(source.getCapabilities());
        equipment.setPurchaseDate(source.getPurchaseDate());
        equipment.setWarrantyDate(source.getWarrantyDate());
        equipment.setRemark(source.getRemark());
        equipment.setCreateBy(operator);
        equipment.initializeDefaults(operator);
        return equipment;
    }

    /**
     * 分配占用（available → busy）
     * 
     * @param operator 操作人
     */
    public void assign(String operator) {
        this.ensureNotDeleted();
        EquipmentStatus current = this.getStatusEnum();
        if (current != EquipmentStatus.AVAILABLE) {
            throw new ServiceException("只有可用状态的装备才能分配占用");
        }
        this.setStatusEnum(EquipmentStatus.BUSY);
        this.touch(operator);
    }

    /**
     * 解除占用（busy → available）
     * 
     * @param operator 操作人
     */
    public void release(String operator) {
        this.ensureNotDeleted();
        EquipmentStatus current = this.getStatusEnum();
        if (current != EquipmentStatus.BUSY) {
            throw new ServiceException("只有占用状态的装备才能解除占用");
        }
        this.setStatusEnum(EquipmentStatus.AVAILABLE);
        this.touch(operator);
    }

    /**
     * 送修（available/busy → repair）
     * 
     * @param operator 操作人
     */
    public void sendRepair(String operator) {
        this.ensureNotDeleted();
        EquipmentStatus current = this.getStatusEnum();
        if (current == EquipmentStatus.SCRAP) {
            throw new ServiceException("已报废的装备不能送修");
        }
        if (current == EquipmentStatus.REPAIR) {
            return; // 已在维修中，无需重复操作
        }
        if (current == EquipmentStatus.AVAILABLE || current == EquipmentStatus.BUSY) {
            this.setStatusEnum(EquipmentStatus.REPAIR);
            this.touch(operator);
            return;
        }
        throw new ServiceException("当前状态无法送修: " + current);
    }

    /**
     * 修复完成（repair → available）
     * 
     * @param operator 操作人
     */
    public void finishRepair(String operator) {
        this.ensureNotDeleted();
        EquipmentStatus current = this.getStatusEnum();
        if (current != EquipmentStatus.REPAIR) {
            throw new ServiceException("只有维修状态的装备才能完成修复");
        }
        this.setStatusEnum(EquipmentStatus.AVAILABLE);
        this.touch(operator);
    }

    /**
     * 报废（→ scrap，终态）
     * 
     * @param operator 操作人
     */
    public void scrap(String operator) {
        this.ensureNotDeleted();
        EquipmentStatus current = this.getStatusEnum();
        if (current == EquipmentStatus.SCRAP) {
            return; // 已报废，无需重复操作
        }
        this.setStatusEnum(EquipmentStatus.SCRAP);
        this.touch(operator);
    }

    /**
     * 标记为已删除
     * 
     * @param operator 操作人
     */
    public void markDeleted(String operator) {
        if (this.isDeleted()) {
            return;
        }
        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 newName 新名称
     * @param operator 操作人
     */
    public void rename(String newName, String operator) {
        if (StringUtils.isBlank(newName)) {
            throw new ServiceException("装备名称不能为空");
        }
        if (newName.length() > 200) {
            throw new ServiceException("装备名称长度不能超过200个字符");
        }
        this.equipmentName = newName;
        this.touch(operator);
    }

    /**
     * 修改装备编码
     * 
     * @param newCode 新编码
     * @param operator 操作人
     */
    public void changeCode(String newCode, String operator) {
        if (StringUtils.isBlank(newCode)) {
            throw new ServiceException("装备编码不能为空");
        }
        if (newCode.length() > 50) {
            throw new ServiceException("装备编码长度不能超过50个字符");
        }
        this.equipmentCode = newCode;
        this.touch(operator);
    }

    /**
     * 修改所属队伍
     * 
     * @param teamId 队伍ID
     * @param operator 操作人
     */
    public void changeTeam(Long teamId, String operator) {
        this.teamId = teamId;
        this.touch(operator);
    }

    /**
     * 修改所属仓库
     * 
     * @param warehouseId 仓库ID
     * @param operator 操作人
     */
    public void changeWarehouse(Long warehouseId, String operator) {
        this.warehouseId = warehouseId;
        this.touch(operator);
    }

    /**
     * 修改能力标签
     * 
     * @param capability 能力标签值对象
     * @param operator 操作人
     */
    public void changeCapabilities(EquipmentCapability capability, String operator) {
        this.capabilities = capability.toStorageFormat();
        this.touch(operator);
    }

    /**
     * 修改采购日期
     * 
     * @param purchaseDate 采购日期
     * @param operator 操作人
     */
    public void changePurchaseDate(Date purchaseDate, String operator) {
        this.purchaseDate = purchaseDate;
        this.touch(operator);
    }

    /**
     * 修改保修到期日期
     * 
     * @param warrantyDate 保修到期日期
     * @param operator 操作人
     */
    public void changeWarrantyDate(Date warrantyDate, String operator) {
        this.warrantyDate = warrantyDate;
        this.touch(operator);
    }

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

    /**
     * 确保装备未被删除
     */
    private void ensureNotDeleted() {
        if (this.isDeleted()) {
            throw new ServiceException("已删除的装备不允许该操作");
        }
    }

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

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

    /**
     * 设置状态枚举
     * 
     * @param equipmentStatus 状态枚举
     */
    private void setStatusEnum(EquipmentStatus equipmentStatus) {
        this.status = equipmentStatus.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";

    /**
     * 装备状态枚举
     */
    private enum EquipmentStatus {
        AVAILABLE("available"),
        BUSY("busy"),
        REPAIR("repair"),
        SCRAP("scrap");

        private final String code;

        EquipmentStatus(String code) {
            this.code = code;
        }

        public String getCode() {
            return code;
        }

        public static EquipmentStatus fromCode(String code) {
            if (StringUtils.isBlank(code)) {
                return AVAILABLE;
            }
            for (EquipmentStatus value : values()) {
                if (value.code.equalsIgnoreCase(code)) {
                    return value;
                }
            }
            return AVAILABLE;
        }
    }
}
