/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package plugin

import (
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/apache/incubator-devlake/core/context"
	"github.com/apache/incubator-devlake/core/dal"
	"github.com/apache/incubator-devlake/core/errors"
	"github.com/apache/incubator-devlake/core/models/common"
	"github.com/apache/incubator-devlake/core/plugin"
	"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
	"github.com/apache/incubator-devlake/server/services/remote/bridge"
	"github.com/apache/incubator-devlake/server/services/remote/models"
	"github.com/apache/incubator-devlake/server/services/remote/models/migrationscripts"
	"github.com/apache/incubator-devlake/server/services/remote/plugin/doc"
)

type (
	remotePluginImpl struct {
		name                 string
		subtaskMetas         []plugin.SubTaskMeta
		pluginPath           string
		description          string
		invoker              bridge.Invoker
		connectionModelInfo  *models.RemoteConnectionModelInfo
		scopeModelInfo       *models.RemoteScopeModelInfo
		scopeConfigModelInfo *models.RemoteScopeConfigModelInfo
		toolModelInfos       []dal.Tabler
		migrationScripts     []plugin.MigrationScript
		resources            map[string]map[string]plugin.ApiResourceHandler
		openApiSpec          string
		dsHelper             *api.DsAnyHelper
	}
	RemotePluginTaskData struct {
		DbUrl       string                 `json:"db_url"`
		Scope       interface{}            `json:"scope"`
		Connection  interface{}            `json:"connection"`
		ScopeConfig interface{}            `json:"scope_config"`
		Options     map[string]interface{} `json:"options"`
	}
)

func newPlugin(info *models.PluginInfo, invoker bridge.Invoker) (*remotePluginImpl, errors.Error) {
	// connectionTabler, err := info.ConnectionModelInfo.LoadDynamicTabler(common.Model{})
	connectionModelInfo, err := models.NewRemoteConnectionModelInfo[common.Model](info.ConnectionModelInfo)
	if err != nil {
		return nil, errors.Default.Wrap(err, fmt.Sprintf("Couldn't load Connection type for plugin %s", info.Name))
	}
	// scopeTabler, err := info.ScopeModelInfo.LoadDynamicTabler(models.ScopeModel{})
	scopeModelInfo, err := models.NewRemoteScopeModelInfo[models.ScopeModel](info.ScopeModelInfo)
	if err != nil {
		return nil, errors.Default.Wrap(err, fmt.Sprintf("Couldn't load Scope type for plugin %s", info.Name))
	}
	// scopeConfigTabler, err := info.ScopeConfigModelInfo.LoadDynamicTabler(models.ScopeConfigModel{})
	scopeConfigModelInfo, err := models.NewRemoteScopeConfigModelInfo[models.ScopeConfigModel](info.ScopeConfigModelInfo)
	if err != nil {
		return nil, errors.Default.Wrap(err, fmt.Sprintf("Couldn't load ScopeConfig type for plugin %s", info.Name))
	}
	// put the scope and connection models in the tool list to be consistent with Go plugins
	toolModelInfos := []dal.Tabler{
		connectionModelInfo,
		scopeModelInfo,
		scopeConfigModelInfo,
	}
	for _, toolModelInfo := range info.ToolModelInfos {
		mi, err := models.GenerateRemoteModelInfo[models.ToolModel](toolModelInfo)
		if err != nil {
			return nil, err
		}
		toolModelInfos = append(toolModelInfos, mi)
	}
	openApiSpec, err := doc.GenerateOpenApiSpec(info)
	if err != nil {
		panic(err)
	}
	scripts := make([]plugin.MigrationScript, 0)
	for _, script := range info.MigrationScripts {
		script := script
		scripts = append(scripts, &script)
	}
	p := remotePluginImpl{
		name:                 info.Name,
		invoker:              invoker,
		pluginPath:           info.PluginPath,
		description:          info.Description,
		connectionModelInfo:  connectionModelInfo,
		scopeModelInfo:       scopeModelInfo,
		scopeConfigModelInfo: scopeConfigModelInfo,
		toolModelInfos:       toolModelInfos,
		migrationScripts:     scripts,
		openApiSpec:          *openApiSpec,
	}
	remoteBridge := bridge.NewBridge(invoker)
	for _, subtask := range info.SubtaskMetas {
		p.subtaskMetas = append(p.subtaskMetas, plugin.SubTaskMeta{
			Name:             subtask.Name,
			EntryPoint:       remoteBridge.RemoteSubtaskEntrypointHandler(subtask),
			Required:         subtask.Required,
			EnabledByDefault: subtask.EnabledByDefault,
			Description:      subtask.Description,
			DomainTypes:      subtask.DomainTypes,
		})
	}
	return &p, nil
}

func (p *remotePluginImpl) Init(basicRes context.BasicRes) errors.Error {
	p.dsHelper = api.NewDataSourceAnyHelper(
		basicRes,
		p.Name(),
		[]string{"name"},
		func(c any) any {
			b := errors.Must1(json.Marshal(c))
			fmt.Printf("%s\n", b)
			tokenField := reflect.ValueOf(c).Elem().FieldByName("Token")
			if tokenField.IsValid() {
				tokenField.SetString("")
			}
			return c
		},
		p.connectionModelInfo,
		p.scopeModelInfo,
		p.scopeConfigModelInfo,
	)
	p.resources = GetDefaultAPI(p.invoker, p.dsHelper)
	return nil
}

func (p *remotePluginImpl) SubTaskMetas() []plugin.SubTaskMeta {
	return p.subtaskMetas
}

func (p *remotePluginImpl) GetTablesInfo() []dal.Tabler {
	return p.toolModelInfos
}

func (p *remotePluginImpl) PrepareTaskData(taskCtx plugin.TaskContext, options map[string]interface{}) (interface{}, errors.Error) {
	dbUrl := taskCtx.GetConfig("db_url")
	connectionId := uint64(options["connectionId"].(float64))
	connection, err := p.dsHelper.ConnSrv.FindByPkAny(connectionId)
	if err != nil {
		return nil, err
	}

	scopeId, ok := options["scopeId"].(string)
	if !ok {
		return nil, errors.BadInput.New("missing scopeId")
	}
	scopeDetail, err := p.dsHelper.ScopeSrv.GetScopeDetailAny(false, connectionId, scopeId)
	if err != nil {
		return nil, err
	}

	return RemotePluginTaskData{
		DbUrl:       dbUrl,
		Scope:       scopeDetail.Scope,
		Connection:  connection,
		ScopeConfig: scopeDetail.ScopeConfig,
		Options:     options,
	}, nil
}

func (p *remotePluginImpl) Description() string {
	return p.description
}

func (p *remotePluginImpl) Name() string {
	return p.name
}

func (p *remotePluginImpl) RootPkgPath() string {
	// RootPkgPath is used by DomainIdGenerator to find the name of the plugin that defines a given type.
	// While remote plugins do not use the DomainIdGenerator, we still need to implement this function.
	// Indeed, DomainIdGenerator uses FindPluginNameBySubPkgPath that returns the name of the first plugin
	// whose RootPkgPath is a prefix of the type package path.
	// So we forge a fake package path that is not a prefix of any go plugin package path.
	return "github.com/apache/incubator-devlake/services/remote/fakepackages/" + p.name
}

func (p *remotePluginImpl) ApiResources() map[string]map[string]plugin.ApiResourceHandler {
	return p.resources
}

func (p *remotePluginImpl) OpenApiSpec() string {
	return p.openApiSpec
}

func (p *remotePluginImpl) MigrationScripts() []plugin.MigrationScript {
	return append(p.migrationScripts, migrationscripts.All(p.name)...)
}

var _ models.RemotePlugin = (*remotePluginImpl)(nil)
