package repository

import (
	"context"
	"dataservices/commons/errs"
	"dataservices/internal/entity"

	"gorm.io/gorm/clause"
)

func CreateGhappEvent(ctx context.Context, event *entity.GhappEvent) (*entity.GhappEvent, error) {
	err := MustFromContext(ctx).Table(entity.TableGhappEvent).Save(event).Error
	if err != nil {
		return nil, errs.WrapGORMError(err, "failed to create ghapp_event")
	}
	return event, nil
}

func CreateGhappPreflightRequest(ctx context.Context, request *entity.GhappPreflightRequest) (*entity.GhappPreflightRequest, error) {
	err := MustFromContext(ctx).Table(entity.TableGhappPreflightRequest).Save(request).Error
	if err != nil {
		return nil, errs.WrapGORMError(err, "failed to create ghapp_preflight_request")
	}
	return request, nil
}

func GetOrgProjectPreflightRequest(ctx context.Context, orgId, projectId, preflightRequestId uint64) (*entity.GhappPreflightRequest, error) {
	var result *entity.GhappPreflightRequest
	err := MustFromContext(ctx).Table(
		entity.TableGhappPreflightRequest,
	).Where(
		"id=? and org_id=? and project_id=?",
		preflightRequestId,
		orgId,
		projectId,
	).First(&result).Error
	return result, err
}

func CreateGhappAuthorization(ctx context.Context, authorization *entity.GhappAuthorization) (*entity.GhappAuthorization, error) {
	err := MustFromContext(ctx).Table(entity.TableGhappAuthorization).Save(authorization).Error
	if err != nil {
		return nil, errs.WrapGORMError(err, "failed to create ghapp_authorization")
	}
	return authorization, nil
}

func CreatePreflightGhappAuthorization(ctx context.Context, preflightRequestId uint64) error {
	return MustFromContext(ctx).Exec(
		"INSERT INTO ghapp_authorization (`preflight_request_id`, `state`) VALUES (?, ?)",
		preflightRequestId,
		entity.GhappAuthorizationStatePreflight,
	).Error
}

func GetGhappAuthorizationByAuthorizeAccountId(ctx context.Context, dataappId uint64, authorizeAccountId int64) (*entity.GhappAuthorization, error) {
	var result *entity.GhappAuthorization
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"dataapp_id=? and authorize_account_id=?",
		dataappId,
		authorizeAccountId,
	).First(&result).Error
	return result, err
}

func GetGhappAuthorizationByPreflightRequestId(ctx context.Context, preflightRequestId uint64) (*entity.GhappAuthorization, error) {
	var result *entity.GhappAuthorization
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"preflight_request_id=?",
		preflightRequestId,
	).First(&result).Error
	return result, err
}

func GetConfirmedGhappAuthorizationByPreflightRequestId(ctx context.Context, preflightRequestId uint64) (*entity.GhappAuthorization, error) {
	var result *entity.GhappAuthorization
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"preflight_request_id=? and state=?",
		preflightRequestId,
		entity.GhappAuthorizationStateConfirmed,
	).First(&result).Error
	return result, err
}

func GetConfirmedGhappAuthorizationByDataappId(ctx context.Context, dataappId uint64) (*entity.GhappAuthorization, error) {
	var result *entity.GhappAuthorization
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"dataapp_id=? and state=?",
		dataappId,
		entity.GhappAuthorizationStateConfirmed,
	).First(&result).Error
	return result, err
}

func UpdateGhappAuthorizationState(ctx context.Context, ghappAuthorizationId uint64, state string) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"id=?",
		ghappAuthorizationId,
	).Update("state", state).Error
}

func UpdateGhappAuthorizationAccount(ctx context.Context, ghappAuthorizationId uint64, accountId int64, accountLogin string) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"id=?",
		ghappAuthorizationId,
	).Updates(
		map[string]interface{}{
			"authorize_account_id":    accountId,
			"authorize_account_login": accountLogin,
			"state":                   entity.GhappAuthorizationStateUnconfirmed,
		},
	).Error
}

func UpdatePreflightGhappAuthorizationDataappId(ctx context.Context, preflightRequestId, dataappId uint64) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"preflight_request_id=?",
		preflightRequestId,
	).Update(
		"dataapp_id",
		dataappId,
	).Error
}

func ListConfirmedGhappAuthorizationByAccountId(ctx context.Context, accountId int64) ([]*entity.GhappAuthorization, error) {
	var result []*entity.GhappAuthorization
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorization,
	).Where(
		"authorize_account_id=? and state=?",
		accountId,
		entity.GhappAuthorizationStateConfirmed,
	).Find(&result).Error
	return result, err
}

func UpdateGhappAuthorizedInstallationStateToUninstalled(ctx context.Context, ghappAuthorizationId uint64) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorizedInstallation,
	).Where(
		"ghapp_authorization_id",
		ghappAuthorizationId,
	).Update(
		"state", entity.GhappAuthorizedInstallationStateUninstalled,
	).Error
}

func UpdateGhappAuthorizedInstallationState(ctx context.Context, installationId int64, state string) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorizedInstallation,
	).Where(
		"installation_id",
		installationId,
	).Update(
		"state", state,
	).Error
}

func UpsertGhappAuthorizedInstallation(ctx context.Context, installation *entity.GhappAuthorizedInstallation) error {
	return MustFromContext(ctx).Table(
		entity.TableGhappAuthorizedInstallation,
	).Clauses(clause.OnConflict{
		DoUpdates: clause.AssignmentColumns([]string{"state"}),
	}).Create(
		installation,
	).Error
}

func ListGhappAuthorizedInstallationByAuthorizationId(ctx context.Context, ghappAuthorizationId uint64) ([]*entity.GhappAuthorizedInstallation, error) {
	var result []*entity.GhappAuthorizedInstallation
	err := MustFromContext(ctx).Table(
		entity.TableGhappAuthorizedInstallation,
	).Where(
		"ghapp_authorization_id=? and state=?",
		ghappAuthorizationId,
		entity.GhappAuthorizedInstallationStateInstalled,
	).Find(&result).Error
	return result, err
}
