package primary

import (
	"blackforestbytes.com/simplecloudnotifier/db"
	"blackforestbytes.com/simplecloudnotifier/models"
	"gogs.mikescher.com/BlackForestBytes/goext/sq"
)

func (db *Database) CreateSubscription(ctx db.TxContext, subscriberUID models.UserID, channel models.Channel, confirmed bool) (models.Subscription, error) {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return models.Subscription{}, err
	}

	entity := models.Subscription{
		SubscriptionID:      models.NewSubscriptionID(),
		SubscriberUserID:    subscriberUID,
		ChannelOwnerUserID:  channel.OwnerUserID,
		ChannelID:           channel.ChannelID,
		ChannelInternalName: channel.InternalName,
		TimestampCreated:    models.NowSCNTime(),
		Confirmed:           confirmed,
		Active:              true,
		Deleted:             false,
	}

	_, err = sq.InsertSingle(ctx, tx, "subscriptions", entity)
	if err != nil {
		return models.Subscription{}, err
	}

	return entity, nil
}

func (db *Database) ListSubscriptions(ctx db.TxContext, filter models.SubscriptionFilter) ([]models.Subscription, error) {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return nil, err
	}

	filterCond, filterJoin, prepParams, err := filter.SQL()

	orderClause := " ORDER BY subscriptions.timestamp_created DESC, subscriptions.subscription_id DESC "

	sqlQuery := "SELECT " + "subscriptions.*" + " FROM subscriptions " + filterJoin + " WHERE ( " + filterCond + " ) AND subscriptions.deleted=0 " + orderClause

	return sq.QueryAll[models.Subscription](ctx, tx, sqlQuery, prepParams, sq.SModeExtended, sq.Safe)
}

func (db *Database) GetSubscription(ctx db.TxContext, subid models.SubscriptionID) (models.Subscription, error) {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return models.Subscription{}, err
	}

	return sq.QuerySingle[models.Subscription](ctx, tx, "SELECT * FROM subscriptions WHERE subscription_id = :sid AND deleted=0 LIMIT 1", sq.PP{"sid": subid}, sq.SModeExtended, sq.Safe)
}

func (db *Database) GetSubscriptionBySubscriber(ctx db.TxContext, subscriberId models.UserID, channelId models.ChannelID) (*models.Subscription, error) {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return nil, err
	}

	return sq.QuerySingleOpt[models.Subscription](ctx, tx, "SELECT * FROM subscriptions WHERE subscriber_user_id = :suid AND channel_id = :cid AND deleted=0 LIMIT 1", sq.PP{
		"suid": subscriberId,
		"cid":  channelId,
	}, sq.SModeExtended, sq.Safe)
}

func (db *Database) DeleteSubscription(ctx db.TxContext, subid models.SubscriptionID) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET deleted=1 WHERE subscription_id = :sid AND deleted=0", sq.PP{"sid": subid})
	if err != nil {
		return err
	}

	return nil
}

func (db *Database) UpdateSubscriptionConfirmed(ctx db.TxContext, subscriptionID models.SubscriptionID, confirmed bool) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET confirmed = :conf WHERE subscription_id = :sid AND deleted=0", sq.PP{
		"conf": confirmed,
		"sid":  subscriptionID,
	})
	if err != nil {
		return err
	}

	return nil
}

func (db *Database) UpdateSubscriptionActive(ctx db.TxContext, subscriptionID models.SubscriptionID, active bool) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET active = :act WHERE subscription_id = :sid AND deleted=0", sq.PP{
		"act": active,
		"sid": subscriptionID,
	})
	if err != nil {
		return err
	}

	return nil
}

func (db *Database) DeleteSubscriptionsOfUserByChannelOwner(ctx db.TxContext, userid models.UserID) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET deleted=1 WHERE channel_owner_user_id = :uid AND deleted=0", sq.PP{"uid": userid})
	if err != nil {
		return err
	}

	return nil
}

func (db *Database) DeleteSubscriptionsOfUserBySubscriber(ctx db.TxContext, userid models.UserID) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET deleted=1 WHERE subscriber_user_id = :uid AND deleted=0", sq.PP{"uid": userid})
	if err != nil {
		return err
	}

	return nil
}

func (db *Database) DeleteSubscriptionsByChannel(ctx db.TxContext, channelid models.ChannelID) error {
	tx, err := ctx.GetOrCreateTransaction(db)
	if err != nil {
		return err
	}

	_, err = tx.Exec(ctx, "UPDATE subscriptions SET deleted=1 WHERE channel_id = :cid AND deleted=0", sq.PP{"cid": channelid})
	if err != nil {
		return err
	}

	return nil
}