package db

type DKIMKeyWithDomain struct {
	DKIMKey
	DomainName string
}

func (d *DB) ListActiveDKIMKeysWithDomain() ([]DKIMKeyWithDomain, error) {
	rows, err := d.Query(`SELECT k.id, k.domain_id, k.selector, k.private_key, k.public_key, k.is_active, k.created_at, k.replaced_at, dm.domain_name
		FROM esrv_dkim_keys k JOIN esrv_domains dm ON dm.id = k.domain_id WHERE k.is_active = 1 ORDER BY dm.domain_name`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanDKIMKeysWithDomain(rows)
}

func (d *DB) ListInactiveDKIMKeysWithDomain() ([]DKIMKeyWithDomain, error) {
	rows, err := d.Query(`SELECT k.id, k.domain_id, k.selector, k.private_key, k.public_key, k.is_active, k.created_at, k.replaced_at, dm.domain_name
		FROM esrv_dkim_keys k JOIN esrv_domains dm ON dm.id = k.domain_id WHERE k.is_active = 0
		ORDER BY dm.domain_name, (k.replaced_at IS NULL), k.replaced_at DESC, k.created_at DESC`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	return scanDKIMKeysWithDomain(rows)
}

func scanDKIMKeysWithDomain(rows interface {
	Next() bool
	Scan(...any) error
	Err() error
}) ([]DKIMKeyWithDomain, error) {
	var out []DKIMKeyWithDomain
	for rows.Next() {
		var k DKIMKeyWithDomain
		var createdAt string
		var replacedAt *string
		if err := rows.Scan(&k.ID, &k.DomainID, &k.Selector, &k.PrivateKey, &k.PublicKey, &k.IsActive, &createdAt, &replacedAt, &k.DomainName); err != nil {
			return nil, err
		}
		k.CreatedAt, _ = parseTime(createdAt)
		if replacedAt != nil {
			t, _ := parseTime(*replacedAt)
			k.ReplacedAt = &t
		}
		out = append(out, k)
	}
	return out, rows.Err()
}

func (d *DB) CountActiveDKIMKeys() (int, error) {
	var n int
	err := d.QueryRow(`SELECT COUNT(*) FROM esrv_dkim_keys WHERE is_active = 1`).Scan(&n)
	return n, err
}

func (d *DB) DeactivateActiveDKIMKeysForDomain(domainID int64, replacedAt any) error {
	_, err := d.Exec(`UPDATE esrv_dkim_keys SET is_active = 0, replaced_at = ? WHERE domain_id = ? AND is_active = 1`, replacedAt, domainID)
	return err
}

func (d *DB) SetDKIMKeyActive(id int64, active bool, replacedAt any) error {
	if active {
		_, err := d.Exec(`UPDATE esrv_dkim_keys SET is_active = 1, replaced_at = NULL WHERE id = ?`, id)
		return err
	}
	_, err := d.Exec(`UPDATE esrv_dkim_keys SET is_active = 0, replaced_at = ? WHERE id = ?`, replacedAt, id)
	return err
}

func (d *DB) UpdateDKIMKeySelector(id int64, selector string) error {
	_, err := d.Exec(`UPDATE esrv_dkim_keys SET selector = ? WHERE id = ?`, selector, id)
	return err
}

func (d *DB) SelectorExistsForDomain(domainID int64, selector string, excludeID int64) (bool, error) {
	var n int
	err := d.QueryRow(`SELECT COUNT(*) FROM esrv_dkim_keys WHERE domain_id = ? AND selector = ? AND is_active = 1 AND id != ?`, domainID, selector, excludeID).Scan(&n)
	return n > 0, err
}

func (d *DB) RemoveDKIMKey(id int64) error {
	_, err := d.Exec(`DELETE FROM esrv_dkim_keys WHERE id = ?`, id)
	return err
}
