/*
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.

SPDX-License-Identifier: Apache-2.0
*/

// Package event -
package event

import (
	"context"
	"time"

	"chainweaver.org.cn/chainweaver/ida/registration-service/internal/utils"

	"github.com/zeromicro/go-zero/core/logx"

	"chainmaker.org/chainmaker/common/v2/json"
	"chainmaker.org/chainmaker/pb-go/v2/common"
	_const "chainweaver.org.cn/chainweaver/ida/contract-ida/const"
	"chainweaver.org.cn/chainweaver/ida/contract-ida/types"
	"chainweaver.org.cn/chainweaver/ida/registration-service/internal/model"
	"gorm.io/gorm"
)

// CertificateEventHandler 认证处理
type CertificateEventHandler struct {
	db          *gorm.DB
	logger      logx.Logger
	chainInfoId int32
}

// NewCertificateEventHandler 实例化认证处理处理器
func NewCertificateEventHandler(db *gorm.DB, logger logx.Logger, chainInfoId int32) *CertificateEventHandler {
	return &CertificateEventHandler{
		db:          db,
		logger:      logger,
		chainInfoId: chainInfoId,
	}
}

// eventName 消费者事件
func (h *CertificateEventHandler) eventName() string {
	return _const.EventIDACertified
}

// handleEvent 事件处理
func (h *CertificateEventHandler) handleEvent(e *common.ContractEventInfo) {
	h.logger.Infof("[event] ida certification  event: %v", e)
	// 事件数据异常
	if len(e.EventData) < 2 {
		h.logger.Errorf("[event] len e.EventData error: %d", len(e.EventData))
		return
	}
	certification := &types.CertificationInfo{}
	assetNumber := e.EventData[0]
	if err := json.Unmarshal([]byte(e.EventData[1]), certification); err != nil {
		h.logger.Errorf("[event] unmarshal error: %s", err)
		return
	}
	// 初始化DB
	tx := h.db.WithContext(context.Background()).Begin()

	// 查询资产是否存在
	asset := &model.Asset{}
	if err := tx.Where("asset_number = ? ", assetNumber).First(asset).Error; err != nil {
		h.logger.Errorf("[event] query asset error: %s", err)
		tx.Rollback()
		return
	}

	// 查询认证企业信息
	enterprise := &model.Enterprise{}
	if err := tx.Where("enterprise_address = ?  and chain_info_id = ?",
		certification.RequestAddress, h.chainInfoId).First(enterprise).Error; err != nil {
		h.logger.Errorf("[event] query certification enterprise error: %v", err)
		tx.Rollback()
		return
	}

	// 查询状态认证中是否存在
	assetCertification := &model.AssetCertification{}
	if err := tx.Where("asset_id = ? and enterprise_id = ? and status = ? and chain_info_id = ?", asset.Id,
		enterprise.Id, model.CertificationStatusVerify, h.chainInfoId).First(assetCertification).Error; err != nil {
		h.logger.Errorf("[event] asset certification status error: %v", err)
		tx.Rollback()
		return
	}

	// 更新认证结果
	assetCertification.Result = int32(certification.Result)
	assetCertification.Explains = certification.Explains
	assetCertification.ExpireTime = certification.ExpireTime
	assetCertification.TxId = e.TxId
	assetCertification.Status = model.CertificationStatusFinish

	if err := tx.Where("id = ?", assetCertification.Id).UpdateColumns(assetCertification).Error; err != nil {
		h.logger.Errorf("[event] update asset certification error: %v", err)
		tx.Rollback()
		return
	}

	// 更新认证附件
	if len(certification.Certifications) > 0 {
		for _, attachment := range certification.Certifications {
			file := &model.AssetCertificationFile{
				AssetId:         int32(asset.Id),
				CertificationId: int32(assetCertification.Id),
				FileUrl:         attachment.Url,
				CreatedAt:       time.Now(),
				UpdatedAt:       nil,
				DeletedAt:       nil,
			}

			if err := tx.Create(file).Error; err != nil {
				h.logger.Errorf("[event] create asset file error:  %v", err)
				tx.Rollback()
				return
			}
		}
	}

	// 更新资产状态
	assetChainInfo := utils.GetAssetChainInfo(tx, int32(asset.Id), h.chainInfoId)
	if assetChainInfo != nil {
		switch certification.Category {
		case model.CertificationTypeProf:
			if assetCertification.Result == model.ResultPass {
				assetChainInfo.ProfStatus = model.CertificationStatusFinish
			} else {
				assetChainInfo.ProfStatus = model.CertificationStatusFailed
			}
		case model.CertificationTypeValuation:
			if assetCertification.Result == model.ResultPass {
				assetChainInfo.ValuationStatus = model.CertificationStatusFinish
			} else {
				assetChainInfo.ValuationStatus = model.CertificationStatusFailed
			}
		}

		if err := tx.Updates(assetChainInfo).Error; err != nil {
			h.logger.Errorf("[event] update asset error: %v, e: %v", err, e)
			tx.Rollback()
			return
		}
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		h.logger.Errorf("[event] tx commit error: %s", err)
		return
	}

}