package com.bcxin.tenant.open.domains.entities;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.bcxin.tenant.open.domains.dtos.PoliceIncidentSuperviseDepartDTO;
import com.bcxin.tenant.open.domains.entities.valueTypes.GeoPointValueType;
import com.bcxin.tenant.open.domains.typeHandlers.GeoPointTypeHandler;
import com.bcxin.tenant.open.infrastructures.components.JsonProvider;
import com.bcxin.tenant.open.infrastructures.TenantEmployeeContext;
import com.bcxin.tenant.open.infrastructures.constants.BusinessConstants;
import com.bcxin.tenant.open.infrastructures.components.JsonProvider;
import com.bcxin.tenant.open.infrastructures.entities.Aggregate;
import com.bcxin.tenant.open.infrastructures.entities.EntityAbstract;
import com.bcxin.tenant.open.infrastructures.enums.PoliceEventCategory;
import com.bcxin.tenant.open.infrastructures.enums.PoliceEventLevel;
import com.bcxin.tenant.open.infrastructures.enums.PoliceEventStatus;
import com.bcxin.tenant.open.infrastructures.enums.ResourceType;
import com.bcxin.tenant.open.infrastructures.exceptions.BadTenantException;
import com.bcxin.tenant.open.infrastructures.utils.PoliceEventCategoryUtils;
import lombok.Data;
import org.apache.ibatis.type.EnumOrdinalTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.Set;

@TableName(value = "police_incidents", autoResultMap = true)
@Data
public class PoliceIncidentsEntity extends EntityAbstract implements Aggregate {

    @TableId(value = "id")
    private Long id;

    @TableField(value = "tenant_user_id")
    private String tenantUserId;

    @TableField(value = "tenant_employee_id")
    private String tenantEmployeeId;

    @TableField(value = "organization_id")
    private String organizationId;

    @TableField(value = "organization_name")
    private String organizationName;

    @TableField(value = "security_station_id")
    private String securityStationId;

    @TableField(value = "security_station_name")
    private String securityStationName;


    @TableField(value = "security_station_address")
    private String securityStationAddress;

    @TableField(value = "supervise_depart_id")
    private String superviseDepartId;

    @TableField(value = "supervise_depart_name")
    private String superviseDepartName;

    @TableField(value = "code")
    private String code;

    @TableField(value = "police_name")
    private String name;

    @TableField(value = "description")
    private String description;

    @TableField(value = "contact")
    private String contact;

    @TableField(value = "police_status", jdbcType = JdbcType.TINYINT, javaType = true, typeHandler = EnumOrdinalTypeHandler.class)
    private PoliceEventStatus policeEventStatus;

    @TableField(value = "category", jdbcType = JdbcType.TINYINT, javaType = true, typeHandler = EnumOrdinalTypeHandler.class)
    private PoliceEventCategory category;

    @TableField(value = "police_level", jdbcType = JdbcType.TINYINT, javaType = true, typeHandler = EnumOrdinalTypeHandler.class)
    private PoliceEventLevel policeEventLevel;

    @TableField(value = "type", jdbcType = JdbcType.TINYINT)
    private int policeEventType;

    @TableField(value = "type_name")
    private String typeName;

    @TableField(value = "address")
    private String address;

    @TableField(value = "reason")
    private String reason;

    @TableField(value = "lon_lat",typeHandler = GeoPointTypeHandler.class)
    private GeoPointValueType lonLat;

    /**
     * 报警地址
     */
    @TableField(value = "location")
    private String location;

    @TableField(value = "action_taken")
    private String actionTaken;

    @TableField(value = "action_tendency")
    private String actionTendency;

    @TableField(value = "processed_suggestion")
    private String processedSuggestion;

    @TableField(value = "processed_locale_guidance")
    private String processedLocaleGuidance;

    @TableField(value = "processed_user_id")
    private String processedUserId;

    @TableField(value = "processed_user_name")
    private String processedUserName;

    @TableField(value = "scene_url")
    private String sceneUrl;

    @TableField(value = "processed_time")
    private Timestamp processedTime;

    @TableField(value = "created_time")
    private Timestamp createdTime;

    @TableField(value = "emp_name")
    private String empName;

    @TableField(value = "emp_id_number")
    private String empIdNumber;

    @TableField(value = "project_id")
    private String projectId;

    @TableField(value = "project_name")
    private String projectName;

    /**
     * 聚合计算的资源信息
     */
    @TableField(value = "calculated_resource_type")
    private int calculatedResourceType;

    @TableField(value = "extend_json_info")
    private String extendJsonInfo;

    /**
     * 积分
     */
    @TableField(value = "points")
    private int points;

    public void changeExtends(JsonProvider jsonProvider, Map<String,Object> items) {
        this.setExtendJsonInfo(jsonProvider.getJson(items));
    }

    public PoliceIncidentsEntity() {
        this.setCreatedTime(Timestamp.from(Instant.now()));
        this.setPoliceEventStatus(PoliceEventStatus.None);
        this.setPoints(0);
    }

    public void makeAsOverStatus(String processUserId,
                                 String processUserName,
                                 PoliceEventStatus status) {
        this.setProcessedUserId(processUserId);
        this.setProcessedUserName(processUserName);
        this.setPoliceEventStatus(status);
        this.setProcessedTime(Timestamp.from(Instant.now()));
    }

    public void change(String sceneUrl,String description)
    {
        this.setSceneUrl(sceneUrl);
        this.setDescription(description);
    }

    public void process(
            String processUserId,
            String processUserName,
                        PoliceEventStatus status,String actionTaken,
                        String actionTendency,
                        String suggestion,
                        String localeGuidance,
            int points)
    {
        if(status==PoliceEventStatus.None) {
            throw new BadTenantException("禁止将警情上报状态更改回待处理");
        }

        this.setPoliceEventStatus(status);
        this.setActionTaken(actionTaken);
        this.setActionTendency(actionTendency);
        this.setProcessedSuggestion(suggestion);
        this.setPoints(points);

        this.setProcessedLocaleGuidance(localeGuidance);
        this.setProcessedUserId(processUserId);
        this.setProcessedUserName(processUserName);
        this.setProcessedTime(Timestamp.from(Instant.now()));
    }

    public static PoliceIncidentsEntity createSos(
            JsonProvider jsonProvider,
            String code,
            String tenantUserId, String tenantEmployeeId,
            String organizationId, String organizationName,
            String securityStationId,
            String securityStationName,
            String projectId,
            String projectName,
            String securityStationAddress,
            String superviseDepartId,
            String superviseDepartName,
            String empIdNumber,
            String empName,
            double latitude, double longitude,
            String address,
            Set<ResourceType> resourceTypes) {
        PoliceIncidentsEntity entity = new PoliceIncidentsEntity();

        entity.setCode(code);
        entity.setCategory(PoliceEventCategory.Sos);
        entity.setSecurityStationAddress(securityStationAddress);
        entity.setOrganizationName(organizationName);
        entity.setSecurityStationName(securityStationName);

        entity.setEmpIdNumber(empIdNumber);
        entity.setEmpName(empName);

        entity.setTenantUserId(tenantUserId);
        entity.setTenantEmployeeId(tenantEmployeeId);
        entity.setOrganizationId(organizationId);

        entity.setProjectId(projectId);
        entity.setProjectName(projectName);
        entity.setSecurityStationId(securityStationId);

        entity.setSuperviseDepartId(superviseDepartId);
        entity.setSuperviseDepartName(superviseDepartName);

        entity.setLonLat(GeoPointValueType.create(latitude, longitude));
        if (StringUtils.hasLength(address)) {
            entity.setAddress(address);
        } else {
            entity.setAddress("-");
        }

        entity.setPoliceEventType(6);
        entity.setPoliceEventLevel(PoliceEventLevel.Greats);
        entity.setName("一键报警");

        /**
         * changed at: 2023-10-13 17:25
         * 在消息队列中; 通过经纬度搜索周边5公里内的最近监管归属;
         * 从中获取距离最近的作为监管归属
         entity.setSuperviseDepartId(superviseDepartId);
         entity.setSuperviseDepartName(superviseDepartName);
         */
        entity.setReason(
                jsonProvider.getJson(PoliceIncidentSuperviseDepartDTO.create(superviseDepartId, superviseDepartName))
        );

        if (BusinessConstants.DefaultEmptyValue.equalsIgnoreCase(entity.getSuperviseDepartName())) {
            entity.setSuperviseDepartName(" ");
        }
        if (BusinessConstants.DefaultEmptyValue.equalsIgnoreCase(entity.getSecurityStationName())) {
            entity.setSecurityStationName(" ");
        }

        Timestamp now = Timestamp.from(Instant.now());
        entity.setCreatedTime(now);
        entity.setLocation(address);
        entity.setCalculatedResourceType(ResourceType.getCalculatedResourceValue(resourceTypes));
        entity.setTypeName(PoliceEventCategoryUtils.getEventTypeName(
                entity.getCategory(),
                entity.getPoliceEventType()
        ));

        return entity;
    }
}
