package db

import (
	"fmt"
	"strings"
	"time"

	"github.com/go-git/go-git/v5/plumbing"
	"github.com/ipfs/go-cid"
	"tangled.org/core/appview/models"
	"tangled.org/core/orm"
)

func AddArtifact(e Execer, artifact models.Artifact) error {
	_, err := e.Exec(
		`insert or ignore into artifacts (
			did,
			rkey,
			repo_did,
			tag,
			created,
			blob_cid,
			name,
			size,
			mimetype
		)
		values (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		artifact.Did,
		artifact.Rkey,
		artifact.RepoDid,
		artifact.Tag[:],
		artifact.CreatedAt.Format(time.RFC3339),
		artifact.BlobCid.String(),
		artifact.Name,
		artifact.Size,
		artifact.MimeType,
	)
	return err
}

func GetArtifact(e Execer, filters ...orm.Filter) ([]models.Artifact, error) {
	var artifacts []models.Artifact

	var conditions []string
	var args []any
	for _, filter := range filters {
		conditions = append(conditions, filter.Condition())
		args = append(args, filter.Arg()...)
	}

	whereClause := ""
	if conditions != nil {
		whereClause = " where " + strings.Join(conditions, " and ")
	}

	query := fmt.Sprintf(`select
			did,
			rkey,
			repo_did,
			tag,
			created,
			blob_cid,
			name,
			size,
			mimetype
		from artifacts %s`,
		whereClause,
	)

	rows, err := e.Query(query, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var artifact models.Artifact
		var createdAt string
		var tag []byte
		var blobCid string

		if err := rows.Scan(
			&artifact.Did,
			&artifact.Rkey,
			&artifact.RepoDid,
			&tag,
			&createdAt,
			&blobCid,
			&artifact.Name,
			&artifact.Size,
			&artifact.MimeType,
		); err != nil {
			return nil, err
		}

		artifact.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
		if err != nil {
			artifact.CreatedAt = time.Now()
		}
		artifact.Tag = plumbing.Hash(tag)
		artifact.BlobCid = cid.MustParse(blobCid)

		artifacts = append(artifacts, artifact)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return artifacts, nil
}

func DeleteArtifact(e Execer, filters ...orm.Filter) error {
	var conditions []string
	var args []any
	for _, filter := range filters {
		conditions = append(conditions, filter.Condition())
		args = append(args, filter.Arg()...)
	}

	whereClause := ""
	if conditions != nil {
		whereClause = " where " + strings.Join(conditions, " and ")
	}

	query := fmt.Sprintf(`delete from artifacts %s`, whereClause)

	_, err := e.Exec(query, args...)
	return err
}
