package model

import (
	"time"

	"github.com/pingcap/log"
	"go.uber.org/zap"
	"gorm.io/gorm"

	"github.com/pingcap-inc/clinic/pkg/db"
)

func AssociateJiraIssueWithFile(fileUUID string, issue *db.JiraIssue) error {
	return db.Transaction(func(tx *gorm.DB) error {
		var uf db.UploadFile
		err := tx.Where("file_uuid=?", fileUUID).First(&uf).Error
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				log.Error("file not found", zap.String("uuid", fileUUID))
				return err
			}
			log.Error("fetch file info", zap.String("fileUUID", fileUUID), zap.Error(err))
			return err
		}

		rel := &db.NodeAssociation{
			SourceNodeID:     issue.ID,
			SourceNodeEntity: db.AssociationEntityJiraIssue,
			SinkNodeID:       uf.ID,
			SinkNodeEntity:   db.AssociationEntityClinicFile,
		}
		err = tx.Where(rel).FirstOrCreate(rel).Error
		if err != nil {
			return err
		}

		return tx.Where(&db.JiraIssue{ID: issue.ID}).FirstOrCreate(issue).Error
	})
}

func ListAssociateBySink(sinkType string, sinkID uint) ([]db.NodeAssociation, error) {
	assocs := []db.NodeAssociation{}
	err := db.Transaction(func(tx *gorm.DB) error {
		return tx.Where(&db.NodeAssociation{
			SinkNodeID:     sinkID,
			SinkNodeEntity: sinkType,
		}).Find(&assocs).Error
	})
	return assocs, err
}

func CreateJiraAssociateRequest(fileUUID string, issueNum uint) error {
	req := &db.JiraIssueBindRequest{
		FileUUID:    fileUUID,
		Project:     "ONCALL",
		IssueNumber: issueNum,
	}
	return db.Transaction(func(tx *gorm.DB) error {
		return tx.Where(req).FirstOrCreate(req).Error
	})
}

func ListRencentJiraAssociateRequest(recent time.Duration) ([]db.JiraIssueBindRequest, error) {
	requests := []db.JiraIssueBindRequest{}
	err := db.Transaction(func(txn *gorm.DB) error {
		err := txn.Where("created_at > ?", time.Now().Add(-recent)).Find(&requests).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return requests, nil
}
