package model

import (
	"context"
	"fmt"
	"time"

	"gorm.io/gorm"
)

type ResultRecord struct {
	ID                   uint64    `gorm:"primaryKey;autoIncrement"`
	SwaggerCommitID      string    `gorm:"type:VARCHAR(64);not null"`
	TestCaseSpecHash     string    `gorm:"type:VARCHAR(64);not null"`
	CaseID               string    `gorm:"type:VARCHAR(64);not null"`
	Service              string    `gorm:"type:VARCHAR(64);not null"`
	Operation            string    `gorm:"type:VARCHAR(64);not null"`
	Body                 string    `gorm:"type:TEXT;not null"`
	Path                 string    `gorm:"type:VARCHAR(256);not null"`
	Method               string    `gorm:"type:VARCHAR(16);not null"`
	ExpectedStatus       int       `gorm:"not null"`
	ResponseStatus       int       `gorm:"not null"`
	ResponseBody         string    `gorm:"type:TEXT;not null"` // may be html and json
	Expected             bool      `gorm:"not null"`
	Ignored              bool      `gorm:"not null"`
	WorkflowStartAt      time.Time `gorm:"type:TIMESTAMP;not null"`
	WorkflowFinishAt     time.Time `gorm:"type:TIMESTAMP;not null"`
	DurationMilliSeconds int64     `gorm:"not null"`
	RunID                string    `gorm:"type:VARCHAR(64);not null"`
	ExecutionID          string    `gorm:"type:VARCHAR(64);not null"`
	CloudProvider        string    `gorm:"type:VARCHAR(16);not null"`
	Env                  string    `gorm:"type:VARCHAR(16);not null"`
	XDebugTraceID        string    `gorm:"type:VARCHAR(64);not null"`
	GenerationID         string    `gorm:"type:VARCHAR(64);not null;default:''"`
}

func (rr *ResultRecord) String() string {
	conclude := "failed"
	if rr.ExpectedStatus == rr.ResponseStatus {
		conclude = "passed"
	}
	return fmt.Sprintf(
		"case %s %s, method:%s, path:%s, body:%v, expected status:%v, got status:%v, got resp:%v, traceid: %v",
		rr.CaseID,
		conclude,
		rr.Method,
		rr.Path,
		rr.Body,
		rr.ExpectedStatus,
		rr.ResponseStatus,
		rr.ResponseBody,
		rr.XDebugTraceID,
	)
}

type ResultRecordDAO struct {
	db *gorm.DB
}

func NewResultRecordDAO(db *gorm.DB) (*ResultRecordDAO, error) {
	dao := &ResultRecordDAO{
		db: db,
	}
	return dao, nil
}

func (dao *ResultRecordDAO) CreateResultRecord(ctx context.Context, r *ResultRecord) error {
	return dao.db.WithContext(ctx).Transaction(func(txn *gorm.DB) error {
		return txn.Create(r).Error
	})
}
