package postgres

import (
	"database/sql"

	"github.com/lib/pq"
	"github.com/pkg/errors"
)

const errClassIntegrityConstraintViolation = "integrity_constraint_violation"

type pgErr struct {
	error
	tableName string // used to disambiguate sql.ErrNoRows errors
}

func pgError(err error, tableName string) *pgErr {
	return &pgErr{
		error:     err,
		tableName: tableName,
	}
}

func (e *pgErr) DuplicateIAMRoleARN() bool {
	err, ok := errors.Cause(e.error).(*pq.Error)
	return ok && err.Constraint == "unique_iam_role" && err.Code.Class().Name() == errClassIntegrityConstraintViolation
}

func (e *pgErr) DuplicateIAMRoleLabelForService() bool {
	err, ok := errors.Cause(e.error).(*pq.Error)
	return ok && err.Constraint == "unique_service_id_label" && err.Code.Class().Name() == errClassIntegrityConstraintViolation
}

func (e *pgErr) DuplicateServiceCatalogID() bool {
	err, ok := errors.Cause(e.error).(*pq.Error)
	return ok && err.Constraint == "unique_service_catalog_id" && err.Code.Class().Name() == errClassIntegrityConstraintViolation
}

func (e *pgErr) DuplicateSubscriptionTargetQueueURL() bool {
	err, ok := errors.Cause(e.error).(*pq.Error)
	return ok && err.Constraint == "subscription_target_unique_sqs_queue_url" && err.Code.Class().Name() == errClassIntegrityConstraintViolation
}

func (e *pgErr) AuthorizedFieldNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == AuthorizedFieldsTableName
}

func (e *pgErr) AuthorizedFieldPublisherGrantNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == AuthorizedFieldPublisherGrantsTableName
}

func (e *pgErr) AuthorizedFieldSubscriberGrantNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == AuthorizedFieldSubscriberGrantsTableName
}

func (e *pgErr) EventStreamNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == EventStreamsTableName
}

func (e *pgErr) EventTypeNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == EventTypesTableName
}

func (e *pgErr) ServiceNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == ServicesTableName
}

func (e *pgErr) SubscriptionTargetNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == SubscriptionTargetsTableName
}

func (e *pgErr) IAMRoleNotFound() bool {
	return errors.Cause(e.error) == sql.ErrNoRows && e.tableName == IAMRolesTableName
}

func (e *pgErr) Error() string {
	if e.error == nil {
		return "unknown error"
	}
	return e.error.Error()
}
