package postgres

import (
	"backend-agenter/internal/config"
	"backend-agenter/internal/models"
	"context"
	"encoding/json"
	"errors"
	"fmt"

	"github.com/jackc/pgx/v4"
	"github.com/jackc/pgx/v4/pgxpool"
	"go.uber.org/zap"
)

type PostgresRepository struct {
	db             *pgxpool.Pool
	config         *config.Postgres
	avObjectsTable string
	urlsTable      string
}

func New(db *pgxpool.Pool, config *config.Postgres) *PostgresRepository {
	return &PostgresRepository{
		db:             db,
		config:         config,
		avObjectsTable: config.AvObjectsTable,
		urlsTable:      config.UrlsTable,
	}
}

func (c *PostgresRepository) GetAvObject(cid int64) (*models.AvObject, error) {
	ctx, cancel := context.WithTimeout(context.Background(), c.config.Timeout)
	defer cancel()

	query := fmt.Sprintf("SELECT object_id, config FROM %s WHERE cid = %d", c.config.AvObjectsTable, cid)
	zap.S().Infof("Query string: %v", query)

	config := ""
	avObject := new(models.AvObject)

	err := c.db.QueryRow(ctx, query).Scan(&avObject.ObjectID, &config)
	if err != nil {
		if errors.Is(err, pgx.ErrNoRows) {
			zap.S().Errorf("Error! Information not found in %s table for cid: %d", c.config.AvObjectsTable, cid)
			return nil, models.ErrDatabase
		}
		zap.S().Errorf("Error while scanning row. Error: %v", err)
		return nil, err
	}

	if err := json.Unmarshal([]byte(config), &avObject.Config); err != nil {
		zap.S().Errorf("Error while unmarshaling config, error: %s", err.Error())
		return nil, err
	}

	return avObject, nil
}

func (c *PostgresRepository) GetUrl(objectID int64) (*models.Url, error) {
	ctx, cancel := context.WithTimeout(context.Background(), c.config.Timeout)
	defer cancel()

	query := fmt.Sprintf("SELECT schema, host, port, path FROM %s WHERE id = %d", c.config.UrlsTable, objectID)

	zap.S().Infof("Query string: %v", query)

	UrlObject := new(models.Url)

	err := c.db.QueryRow(ctx, query).Scan(&UrlObject.Schema, &UrlObject.Host, &UrlObject.Port, &UrlObject.Path)
	if err != nil {
		if errors.Is(err, pgx.ErrNoRows) {
			zap.S().Errorf("Error! Information not found in %s table for objectID: %d", c.config.UrlsTable, objectID)
			return nil, models.ErrDatabase
		}
		zap.S().Errorf("Error while getting row. Error: %v", err)
		return nil, err
	}

	return UrlObject, nil
}
