package postgres

import (
	"context"
	"database/sql"

	"code.justin.tv/eventbus/controlplane/internal/db"
)

const (
	AuthorizedFieldsTableName = "authorized_fields"

	authorizedFieldCreateQuery = `
INSERT INTO authorized_fields (event_stream_id, message_name, field_name)
VALUES (:event_stream_id, :message_name, :field_name)
RETURNING id
`

	authorizedFieldAllQuery = `
SELECT * FROM authorized_fields
ORDER BY event_stream_id
`

	authorizedFieldByIDQuery = `
SELECT * FROM authorized_fields
WHERE id = $1
`
	authorizedFieldByAuthContextQuery = `
SELECT * FROM authorized_fields
WHERE event_stream_id = $1 AND message_name = $2 AND field_name = $3 
`

	authorizedFieldsByEventStreamIDQuery = `
SELECT * FROM authorized_fields
WHERE event_stream_id = $1	
`

	authorizedFieldDeleteByIDQuery = `
DELETE FROM authorized_fields
WHERE id = $1
`
)

func (pg *PostgresDB) AuthorizedFieldCreate(ctx context.Context, authorizedField *db.AuthorizedField) (int, error) {
	var id int
	namedQuery, err := pg.writer.PrepareNamedContext(ctx, authorizedFieldCreateQuery)
	if err != nil {
		return -1, err
	}

	err = namedQuery.QueryRowxContext(ctx, authorizedField).Scan(&id)
	return id, err
}

func (pg *PostgresDB) AuthorizedFields(ctx context.Context) ([]*db.AuthorizedField, error) {
	var authorizedFields []*db.AuthorizedField
	err := pg.reader.SelectContext(ctx, &authorizedFields, authorizedFieldAllQuery)
	return authorizedFields, err
}

func (pg *PostgresDB) AuthorizedFieldByAuthContext(ctx context.Context, eventStreamID int, messageName, fieldName string) (*db.AuthorizedField, error) {
	var authorizedField db.AuthorizedField
	err := pg.reader.GetContext(ctx, &authorizedField, authorizedFieldByAuthContextQuery, eventStreamID, messageName, fieldName)
	if err == sql.ErrNoRows {
		return nil, pgError(err, AuthorizedFieldsTableName)
	}
	return &authorizedField, err
}

func (pg *PostgresDB) AuthorizedFieldByID(ctx context.Context, id int) (*db.AuthorizedField, error) {
	var authorizedField db.AuthorizedField
	err := pg.reader.GetContext(ctx, &authorizedField, authorizedFieldByIDQuery, id)
	if err == sql.ErrNoRows {
		return nil, pgError(err, AuthorizedFieldsTableName)
	}
	return &authorizedField, err
}

func (pg *PostgresDB) AuthorizedFieldsByEventStreamID(ctx context.Context, eventStreamID int) ([]*db.AuthorizedField, error) {
	var authorizedFields []*db.AuthorizedField
	err := pg.reader.SelectContext(ctx, &authorizedFields, authorizedFieldsByEventStreamIDQuery, eventStreamID)
	if err == sql.ErrNoRows {
		return nil, db.ErrResourceNotFound
	}
	return authorizedFields, err
}

func (pg *PostgresDB) AuthorizedFieldDeleteByID(ctx context.Context, id int) error {
	res, err := pg.writer.ExecContext(ctx, authorizedFieldDeleteByIDQuery, id)
	if err != nil {
		return err
	}

	rowsAffected, err := res.RowsAffected()
	if err != nil {
		return err
	}

	if rowsAffected == 0 {
		return db.ErrResourceNotFound
	}

	return nil
}
