package models

import (
	"context"
	"database/sql"
	. "github.com/go-jet/jet/v2/postgres"
	"screenmark/screenmark/.gen/haystack/haystack/model"
	. "screenmark/screenmark/.gen/haystack/haystack/table"

	"github.com/google/uuid"
)

type EventModel struct {
	dbPool *sql.DB
}

func (m EventModel) List(ctx context.Context, userId uuid.UUID) ([]model.Events, error) {
	listEventsStmt := SELECT(Events.AllColumns).
		FROM(
			Events.
				INNER_JOIN(UserEvents, UserEvents.EventID.EQ(Events.ID)),
		).
		WHERE(UserEvents.UserID.EQ(UUID(userId)))

	events := []model.Events{}

	err := listEventsStmt.QueryContext(ctx, m.dbPool, &events)
	return events, err
}

func (m EventModel) Save(ctx context.Context, userId uuid.UUID, event model.Events) (model.Events, error) {
	// TODO tx here
	insertEventStmt := Events.
		INSERT(Events.MutableColumns).
		MODEL(event).
		RETURNING(Events.AllColumns)

	insertedEvent := model.Events{}
	err := insertEventStmt.QueryContext(ctx, m.dbPool, &insertedEvent)

	if err != nil {
		return insertedEvent, err
	}

	insertUserEventStmt := UserEvents.
		INSERT(UserEvents.UserID, UserEvents.EventID).
		VALUES(userId, insertedEvent.ID)

	_, err = insertUserEventStmt.ExecContext(ctx, m.dbPool)

	return insertedEvent, err
}

func (m EventModel) SaveToImage(ctx context.Context, imageId uuid.UUID, eventId uuid.UUID) (model.ImageEvents, error) {
	insertImageEventStmt := ImageEvents.
		INSERT(ImageEvents.ImageID, ImageEvents.EventID).
		VALUES(imageId, eventId).
		RETURNING(ImageEvents.AllColumns)

	imageEvent := model.ImageEvents{}
	err := insertImageEventStmt.QueryContext(ctx, m.dbPool, &imageEvent)

	return imageEvent, err
}

func (m EventModel) UpdateLocation(ctx context.Context, eventId uuid.UUID, locationId uuid.UUID) (model.Events, error) {
	updateEventLocationStmt := Events.
		UPDATE(Events.LocationID).
		SET(locationId).
		WHERE(Events.ID.EQ(UUID(eventId))).
		RETURNING(Events.AllColumns)

	updatedEvent := model.Events{}
	err := updateEventLocationStmt.QueryContext(ctx, m.dbPool, &updatedEvent)

	return updatedEvent, err
}

func (m EventModel) UpdateOrganizer(ctx context.Context, eventId uuid.UUID, organizerId uuid.UUID) (model.Events, error) {
	updateEventContactStmt := Events.
		UPDATE(Events.OrganizerID).
		SET(organizerId).
		WHERE(Events.ID.EQ(UUID(eventId))).
		RETURNING(Events.AllColumns)

	updatedEvent := model.Events{}
	err := updateEventContactStmt.QueryContext(ctx, m.dbPool, &updatedEvent)

	return updatedEvent, err
}

func NewEventModel(db *sql.DB) EventModel {
	return EventModel{dbPool: db}
}
