package app

import (
	"context"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
	"github.com/tidbcloud/AgentTeam/internal/store/serviceactor"
)

func (store *Store) loadRuntimeAppInstallationFromServiceActor(ctx context.Context, installationID string) (model.RuntimeAppInstallation, error) {
	row := store.db.QueryRow(ctx, runtimeAppInstallationSelectSQL()+`
WHERE installation.id = $1
  AND installation.service_kind = $2
`, strings.TrimSpace(installationID), serviceactor.KindApp)
	return scanOptionalRuntimeAppInstallation(row)
}

func loadRuntimeAppInstallationFromQueryer(ctx context.Context, queryer coredb.QueryRower, installationID string) (model.RuntimeAppInstallation, error) {
	row := queryer.QueryRow(ctx, runtimeAppInstallationSelectSQL()+`
WHERE installation.id = $1
  AND installation.service_kind = $2
`, strings.TrimSpace(installationID), serviceactor.KindApp)
	return scanOptionalRuntimeAppInstallation(row)
}

func runtimeAppInstallationSelectSQL() string {
	return `
SELECT
    installation.id,
    definition.id,
    definition.slug,
    definition.name,
    COALESCE(JSON_UNQUOTE(JSON_EXTRACT(definition.config, '$.appKind')), ''),
    service_member.member_id,
    service_member.handle,
    installation.workspace_id,
    installation.config,
    COALESCE(JSON_UNQUOTE(JSON_EXTRACT(installation.metadata, '$.callbackURL')), ''),
    COALESCE(JSON_UNQUOTE(JSON_EXTRACT(definition.config, '$.callbackSigningSecret')), '')
FROM service_installations installation
JOIN service_definitions definition
  ON definition.id = installation.service_definition_id
 AND definition.service_kind = installation.service_kind
JOIN service_members service_member
  ON service_member.service_installation_id = installation.id
 AND service_member.service_kind = installation.service_kind
`
}

func scanOptionalRuntimeAppInstallation(row coredb.Row) (model.RuntimeAppInstallation, error) {
	installation, err := scanRuntimeAppInstallation(row)
	if err != nil {
		if coredb.IsNotFound(err) {
			return model.RuntimeAppInstallation{}, ErrNotFound
		}
		return model.RuntimeAppInstallation{}, err
	}
	return installation, nil
}

func scanRuntimeAppInstallation(scanner interface {
	Scan(...any) error
}) (model.RuntimeAppInstallation, error) {
	var installation model.RuntimeAppInstallation
	if err := scanner.Scan(
		&installation.InstallationID,
		&installation.AppID,
		&installation.AppSlug,
		&installation.AppName,
		&installation.AppKind,
		&installation.MemberID,
		&installation.Handle,
		&installation.WorkspaceID,
		&installation.Config,
		&installation.CallbackURL,
		&installation.CallbackSigningSecret,
	); err != nil {
		return model.RuntimeAppInstallation{}, err
	}
	installation.InstallationID = strings.TrimSpace(installation.InstallationID)
	installation.AppID = strings.TrimSpace(installation.AppID)
	installation.AppSlug = strings.TrimSpace(installation.AppSlug)
	installation.AppName = strings.TrimSpace(installation.AppName)
	installation.AppKind = strings.TrimSpace(installation.AppKind)
	installation.MemberID = strings.TrimSpace(installation.MemberID)
	installation.Handle = strings.TrimSpace(installation.Handle)
	installation.WorkspaceID = strings.TrimSpace(installation.WorkspaceID)
	installation.CallbackURL = strings.TrimSpace(installation.CallbackURL)
	installation.CallbackSigningSecret = strings.TrimSpace(installation.CallbackSigningSecret)
	return installation, nil
}
