package database

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/vingarcia/ksql"
	"github.com/vingarcia/ksql/adapters/kpgx"
)

var ProductsTable = ksql.NewTable("products", "id")

var UserClaimsTable = ksql.NewTable("user_claims", "id")

var AutomatedClaimsTable = ksql.NewTable("automated_claims", "id")

// Struct used in dependency injection can be replaced with a mock for testing.
type Database struct {
	db *ksql.DB
}

// initializeDatabase creates the database and calls createTables.
func InitializeDatabase() Database {
	ctx := context.Background()

	// urlExample := "postgres://username:password@localhost:5432/database_name"
	host := os.Getenv("PGHOST")
	dbName := os.Getenv("DB_NAME")

	connectString := fmt.Sprintf("postgres:///?host=%s&database=%s", host, dbName)

	db, err := kpgx.New(ctx, connectString, ksql.Config{})
	if err != nil {
		log.Fatalf("Unable to connect to database: %v\n", err)
	}

	database := Database{
		db: &db,
	}

	database.createTables(ctx)
	return database
}

// createTables adds the product, automated_claims, and user_claims tables to the initialized database.
func (database *Database) createTables(ctx context.Context) {
	_, err := database.db.Exec(ctx, `
		CREATE TABLE IF NOT EXISTS products (
			id BIGSERIAL PRIMARY KEY,
			system TEXT,
			barcode TEXT,
			created_at TIMESTAMPTZ
		);
	`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = database.db.Exec(ctx, `
		CREATE TABLE IF NOT EXISTS user_claims (
			id BIGSERIAL PRIMARY KEY,
			product_id INTEGER,
			evidence_type INTEGER,
			evidence  JSONB,
			claims INTEGER[],
			counterclaims INTEGER[],
			created_at TIMESTAMPTZ,
			created_by TEXT,

			CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
		);

		-- CREATE INDEX idx_user_claims_product_id ON user_claims USING HASH (product_id);
	`)
	if err != nil {
		log.Fatal(err)
	}
	_, err = database.db.Exec(ctx, `
		CREATE TABLE IF NOT EXISTS automated_claims (
			id BIGSERIAL PRIMARY KEY,
			product_id INTEGER,
			worker_type INTEGER,
			evidence  JSONB,
			claims INTEGER[],
			counterclaims INTEGER[],
			created_at TIMESTAMPTZ,

			CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
		);

		-- CREATE INDEX idx_automated_claims_product_id ON automated_claims USING HASH (product_id);
	`)
	if err != nil {
		log.Fatal(err)
	}
}