package db

import (
	"context"
	"database/sql"
	"log/slog"
)

type BotAccessRequest struct {
	db      *sql.DB
	log     *slog.Logger
	ID      int64  `json:"id"`
	TgbID   int64  `json:"tgb_id"`
	BotName string `json:"bot_name"`
	BotID   int64  `json:"bot_id"`
	Created int64  `json:"edited"`
}

type BotBannedAccess struct {
	db      *sql.DB
	log     *slog.Logger
	ID      int64  `json:"id"`
	TgbID   int64  `json:"tgb_id"`
	BotName string `json:"bot_name"`
	Until   int64  `json:"until"`
	Created int64  `json:"edited"`
}

func NewBotAccessRequest(db *sql.DB, log *slog.Logger) *BotAccessRequest {
	return &BotAccessRequest{
		db:  db,
		log: log,
	}
}

func NewBotBannedAccess(db *sql.DB, log *slog.Logger) *BotBannedAccess {
	return &BotBannedAccess{
		db:  db,
		log: log,
	}
}

func (bar *BotAccessRequest) Add(ctx context.Context, tgbID int64, botName string) (bool, error) {

	stmt, err := bar.db.PrepareContext(ctx,
		`
INSERT INTO bot_access_requests
    (tgb_id, bot_id, created)
VALUES(?,(SELECT id FROM bots WHERE bot_name = ?),strftime('%s', 'now'));`)

	if err != nil {
		bar.log.Error("prepare stmt add bot access request", "error", err)
		return false, err
	}
	defer stmt.Close()
	_, err = stmt.ExecContext(ctx, tgbID, botName)
	if err != nil {
		bar.log.Error("exec add bot access requests", "error", err)
		return false, err
	}
	return true, nil
}

// Get
// Get access request pending for bots
func (bar *BotAccessRequest) Get(ctx context.Context, tgbID int64) ([]*BotAccessRequest, error) {
	stmt, err := bar.db.PrepareContext(ctx,
		`SELECT bar.id, b.bot_name, bar.created FROM bot_access_requests AS bar
                  JOIN bots AS b ON bar.bot_id = b.id
                     WHERE bar.tgb_id = ?;`)
	if err != nil {
		bar.log.Error("prepare stmt getBots", "error", err)
		return nil, err
	}
	defer stmt.Close()
	rows, err := stmt.QueryContext(ctx, tgbID)
	if err != nil {
		bar.log.Error("query get bot_access_request", "error", err)
		return nil, err
	}
	defer rows.Close()
	bl := []*BotAccessRequest{}
	for rows.Next() {
		ba := &BotAccessRequest{}
		err := rows.Scan(&ba.ID, &ba.BotName, &ba.Created)
		if err != nil {
			bar.log.Error("scanning get bots_access_requests", "error", err)
			return nil, err
		}
		bl = append(bl, ba)

	}
	return bl, nil
}

// GetAll
// GetAll access request pending for bots
func (bar *BotAccessRequest) GetAll(ctx context.Context, botName string) ([]*BotAccessRequest, error) {
	stmt, err := bar.db.PrepareContext(ctx,
		`SELECT bar.id, b.bot_name, bar.tgb_id, bar.created FROM bot_access_requests AS bar
                  JOIN bots AS b ON bar.bot_id = b.id
                     WHERE b.bot_name = ?;`)
	if err != nil {
		bar.log.Error("prepare stmt getBots", "error", err)
		return nil, err
	}
	defer stmt.Close()
	rows, err := stmt.QueryContext(ctx, botName)
	if err != nil {
		bar.log.Error("query get bot_access_request", "error", err)
		return nil, err
	}
	defer rows.Close()
	bl := []*BotAccessRequest{}
	for rows.Next() {
		ba := &BotAccessRequest{}
		err := rows.Scan(&ba.ID, &ba.BotName, &ba.TgbID, &ba.Created)
		if err != nil {
			bar.log.Error("scanning get bots_access_requests", "error", err)
			return nil, err
		}
		bl = append(bl, ba)

	}
	return bl, nil
}

func (bar BotAccessRequest) Delete(ctx context.Context, tgbID int64, botName string) (bool, error) {
	stmt, err := bar.db.PrepareContext(ctx,
		`
DELETE FROM bot_access_requests as bar
WHERE bar.bot_id = (SELECT id FROM bots WHERE bot_name = ?) AND bar.tgb_id = ?
`)
	if err != nil {
		bar.log.Error("prepare stmt delete", "error", err)
		return false, err
	}
	defer stmt.Close()
	_, err = stmt.ExecContext(ctx, botName, tgbID)
	if err != nil {
		bar.log.Error("exec delete", "error", err)
		return false, err
	}
	return true, nil
}

func (bba *BotBannedAccess) Add(ctx context.Context, tgbID, until int64, botName string) (bool, error) {

	stmt, err := bba.db.PrepareContext(ctx,
		`
INSERT INTO banned_bot_access
    (tgb_id, until, bot_id, created)
VALUES(?,?,(SELECT id FROM bots WHERE bot_name = ?),strftime('%s', 'now'));`)

	if err != nil {
		bba.log.Error("prepare stmt add bot banned access", "error", err)
		return false, err
	}
	defer stmt.Close()
	_, err = stmt.ExecContext(ctx, tgbID, until, botName)
	if err != nil {
		bba.log.Error("exec add bot banned Access", "error", err)
		return false, err
	}
	return true, nil
}

func (bba *BotBannedAccess) Get(ctx context.Context, tgbID int64) ([]*BotBannedAccess, error) {
	stmt, err := bba.db.PrepareContext(ctx,
		`SELECT bba.id, b.bot_name, bba.until, bba.created FROM  banned_bot_access AS bba
                  JOIN bots AS b ON bba.bot_id = b.id
                     WHERE bba.tgb_id = ?;`)
	if err != nil {
		bba.log.Error("prepare stmt bots banned access", "error", err)
		return nil, err
	}
	defer stmt.Close()
	rows, err := stmt.QueryContext(ctx, tgbID)
	if err != nil {
		bba.log.Error("query get bot banned access", "error", err)
		return nil, err
	}
	defer rows.Close()
	bl := []*BotBannedAccess{}
	for rows.Next() {
		ba := &BotBannedAccess{}
		err := rows.Scan(&ba.ID, &ba.BotName, &ba.Until, &ba.Created)
		if err != nil {
			bba.log.Error("scanning get bots banned access", "error", err)
			return nil, err
		}
		bl = append(bl, ba)

	}
	return bl, nil
}

func (bba *BotBannedAccess) GetAll(ctx context.Context, botName string) ([]*BotBannedAccess, error) {
	stmt, err := bba.db.PrepareContext(ctx,
		`SELECT bba.id, b.bot_name, bba.tgb_id, bba.until, bba.created FROM  banned_bot_access AS bba
                  JOIN bots AS b ON bba.bot_id = b.id
                     WHERE b.bot_name = ?;`)
	if err != nil {
		bba.log.Error("prepare stmt bots banned access", "error", err)
		return nil, err
	}
	defer stmt.Close()
	rows, err := stmt.QueryContext(ctx, botName)
	if err != nil {
		bba.log.Error("query get bot banned access", "error", err)
		return nil, err
	}
	defer rows.Close()
	bl := []*BotBannedAccess{}
	for rows.Next() {
		ba := &BotBannedAccess{}
		err := rows.Scan(&ba.ID, &ba.BotName, &ba.TgbID, &ba.Until, &ba.Created)
		if err != nil {
			bba.log.Error("scanning get bots banned access", "error", err)
			return nil, err
		}
		bl = append(bl, ba)

	}
	return bl, nil
}

func (bba *BotBannedAccess) Delete(ctx context.Context, tgbID int64, botName string) (bool, error) {
	stmt, err := bba.db.PrepareContext(ctx,
		`
DELETE FROM banned_bot_access as bar
WHERE bar.bot_id = (SELECT id FROM bots WHERE bot_name = ?) AND bar.tgb_id = ?
`)
	if err != nil {
		bba.log.Error("prepare stmt delete bot banned access", "error", err)
		return false, err
	}
	defer stmt.Close()
	_, err = stmt.ExecContext(ctx, botName, tgbID)
	if err != nil {
		bba.log.Error("exec delete bot banned access", "error", err)
		return false, err
	}
	return true, nil
}
