package ignore

import (
	"fmt"
	"net/url"
	"sync"
	"time"

	"go.skia.org/infra/go/sklog"

	"go.skia.org/infra/go/database"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/go/expstorage"
	"go.skia.org/infra/golden/go/types"
)

type SQLIgnoreStore struct {
	vdb          *database.VersionedDB
	mutex        sync.Mutex
	revision     int64
	tileStream   <-chan *types.TilePair
	lastTilePair *types.TilePair
	expStore     expstorage.ExpectationsStore
}

// NewSQLIgnoreStore creates a new SQL based IgnoreStore.
//   vdb - database to connect to.
//   expStore - expectations store needed to cound the untriaged digests per rule.
//   tileStream - continously provides an updated copy of the current tile.
func NewSQLIgnoreStore(vdb *database.VersionedDB, expStore expstorage.ExpectationsStore, tileStream <-chan *types.TilePair) IgnoreStore {
	ret := &SQLIgnoreStore{
		vdb:        vdb,
		tileStream: tileStream,
		expStore:   expStore,
	}

	return ret
}

func (m *SQLIgnoreStore) inc() {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	m.revision += 1
}

// Create, see IgnoreStore interface.
func (m *SQLIgnoreStore) Create(rule *IgnoreRule) error {
	stmt := `INSERT INTO ignorerule (userid, updated_by, expires, query, note)
	         VALUES(?,?,?,?,?)`

	ret, err := m.vdb.DB.Exec(stmt, rule.Name, rule.Name, rule.Expires.Unix(), rule.Query, rule.Note)
	if err != nil {
		return err
	}
	createdId, err := ret.LastInsertId()
	if err != nil {
		return err
	}
	rule.ID = int(createdId)
	m.inc()
	return nil
}

// Update, see IgnoreStore interface.
func (m *SQLIgnoreStore) Update(id int, rule *IgnoreRule) error {
	stmt := `UPDATE ignorerule SET updated_by=?, expires=?, query=?, note=? WHERE id=?`

	res, err := m.vdb.DB.Exec(stmt, rule.UpdatedBy, rule.Expires.Unix(), rule.Query, rule.Note, rule.ID)
	if err != nil {
		return err
	}
	n, err := res.RowsAffected()
	if err == nil && n == 0 {
		return fmt.Errorf("Did not find an IgnoreRule with id: %d", id)
	}
	m.inc()
	return nil
}

// List, see IgnoreStore interface.
func (m *SQLIgnoreStore) List(addCounts bool) ([]*IgnoreRule, error) {
	stmt := `SELECT id, userid, updated_by, expires, query, note
	         FROM ignorerule
	         ORDER BY expires ASC`
	rows, err := m.vdb.DB.Query(stmt)
	if err != nil {
		return nil, err
	}
	defer util.Close(rows)

	result := []*IgnoreRule{}
	for rows.Next() {
		target := &IgnoreRule{}
		var expiresTS int64
		err := rows.Scan(&target.ID, &target.Name, &target.UpdatedBy, &expiresTS, &target.Query, &target.Note)
		if err != nil {
			return nil, err
		}
		target.Expires = time.Unix(expiresTS, 0)
		result = append(result, target)
	}

	if addCounts {
		if err := m.addIgnoreCounts(result); err != nil {
			sklog.Errorf("Unable to add counts to ignore list result: %s", err)
		}
	}

	return result, nil
}

// TODO(stephana): Add unit tests to addIgnoreCounts once we have a framework ready to
// easily test against live (vs synthetic) data.

// addIgnoreCounts counts the number of traces in the current tile that match the given
// ignore rules. It sets the corresponding field in each instance of IgnoreRule.
func (m *SQLIgnoreStore) addIgnoreCounts(rules []*IgnoreRule) error {
	if (m.expStore == nil) || (m.tileStream == nil) {
		return fmt.Errorf("Either expStore or tileStream is nil. Cannot count ignores.")
	}

	exp, err := m.expStore.Get()
	if err != nil {
		return err
	}

	ignoreMatcher, err := m.BuildRuleMatcher()
	if err != nil {
		return err
	}

	// Get the next tile.
	var tilePair *types.TilePair = nil
	select {
	case tilePair = <-m.tileStream:
	default:
		tilePair = m.lastTilePair
	}
	if tilePair == nil {
		return fmt.Errorf("No tile available to count ignores")
	}
	m.lastTilePair = tilePair

	// Count the untriaged digests in HEAD.
	// matchingDigests[rule.ID]map[digest]bool
	matchingDigests := make(map[int]map[string]bool, len(rules))
	rulesByDigest := map[string]map[int]bool{}
	for _, trace := range tilePair.TileWithIgnores.Traces {
		gTrace := trace.(*types.GoldenTrace)
		if matchRules, ok := ignoreMatcher(gTrace.Params_); ok {
			testName := gTrace.Params_[types.PRIMARY_KEY_FIELD]
			if digest := gTrace.LastDigest(); digest != types.MISSING_DIGEST && (exp.Classification(testName, digest) == types.UNTRIAGED) {
				k := testName + ":" + digest
				for _, r := range matchRules {
					// Add the digest to all matching rules.
					if t, ok := matchingDigests[r.ID]; ok {
						t[k] = true
					} else {
						matchingDigests[r.ID] = map[string]bool{k: true}
					}

					// Add the rule to the test-digest.
					if t, ok := rulesByDigest[k]; ok {
						t[r.ID] = true
					} else {
						rulesByDigest[k] = map[int]bool{r.ID: true}
					}
				}
			}
		}
	}

	for _, r := range rules {
		r.Count = len(matchingDigests[r.ID])
		r.ExclusiveCount = 0
		for testDigestKey := range matchingDigests[r.ID] {
			// If exactly this one rule matches then account for it.
			if len(rulesByDigest[testDigestKey]) == 1 {
				r.ExclusiveCount++
			}
		}
	}
	return nil
}

// Delete, see IgnoreStore interface.
func (m *SQLIgnoreStore) Delete(id int, userId string) (int, error) {
	stmt := "DELETE FROM ignorerule WHERE id=?"
	ret, err := m.vdb.DB.Exec(stmt, id)
	if err != nil {
		return 0, err
	}
	rowsAffected, err := ret.RowsAffected()
	if err != nil {
		return 0, err
	}
	if rowsAffected > 0 {
		m.inc()
	}
	return int(rowsAffected), nil
}

// Revisison, see IngoreStore interface.
func (m *SQLIgnoreStore) Revision() int64 {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	return m.revision
}

// BuildRuleMatcher, see IgnoreStore interface.
func (m *SQLIgnoreStore) BuildRuleMatcher() (RuleMatcher, error) {
	return buildRuleMatcher(m)
}

func buildRuleMatcher(store IgnoreStore) (RuleMatcher, error) {
	rulesList, err := store.List(false)
	if err != nil {
		return noopRuleMatcher, err
	}

	ignoreRules := make([]QueryRule, len(rulesList))
	for idx, rawRule := range rulesList {
		parsedQuery, err := url.ParseQuery(rawRule.Query)
		if err != nil {
			return noopRuleMatcher, err
		}
		ignoreRules[idx] = NewQueryRule(parsedQuery)
	}

	return func(params map[string]string) ([]*IgnoreRule, bool) {
		result := []*IgnoreRule{}

		for ruleIdx, rule := range ignoreRules {
			if rule.IsMatch(params) {
				result = append(result, rulesList[ruleIdx])
			}
		}

		return result, len(result) > 0
	}, nil
}
