package rest

import (
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ---------------------------------------------------------------------------
// toSFUIApp — internal model to Salesforce wire format
// ---------------------------------------------------------------------------

func TestToSFUIApp_Basic(t *testing.T) {
	app := &models.AppConfig{
		ID:          "sales_app",
		Label:       "Sales",
		Description: "Sales application",
		Color:       "#0070D2",
		Icon:        "/icon.png",
		IsDefault:   true,
	}

	sf := toSFUIApp(app)

	assert.Equal(t, "sales_app", sf.AppId)
	assert.Equal(t, "Sales", sf.Label)
	assert.Equal(t, "Sales application", sf.Description)
	assert.Equal(t, "#0070D2", sf.HeaderColor)
	assert.Equal(t, "/icon.png", sf.IconUrl)
	assert.True(t, sf.Selected)
	assert.Equal(t, []string{"Large"}, sf.FormFactors)
	assert.NotNil(t, sf.NavItems)
}

func TestToSFUIApp_ObjectNavItem(t *testing.T) {
	app := &models.AppConfig{
		ID:    "app1",
		Label: "App",
		NavigationItems: []models.NavigationItem{
			{
				ID:            "nav-0",
				Label:         "Accounts",
				Type:          constants.NavigationTypeObject,
				ObjectAPIName: "Account",
				Icon:          "/accounts.png",
			},
		},
	}

	sf := toSFUIApp(app)

	require.Len(t, sf.NavItems, 1)
	assert.Equal(t, "Account", sf.NavItems[0].ObjectApiName)
	assert.Equal(t, "Accounts", sf.NavItems[0].Label)
	assert.Equal(t, constants.NavigationTypeObject, sf.NavItems[0].ItemType)
}

func TestToSFUIApp_WebNavItem(t *testing.T) {
	app := &models.AppConfig{
		ID:    "app2",
		Label: "App",
		NavigationItems: []models.NavigationItem{
			{
				ID:      "nav-web",
				Label:   "External Site",
				Type:    constants.NavigationTypeWeb,
				PageURL: "https://example.com",
			},
		},
	}

	sf := toSFUIApp(app)

	require.Len(t, sf.NavItems, 1)
	require.NotNil(t, sf.NavItems[0].PageReference)
	assert.Equal(t, "standard__webPage", sf.NavItems[0].PageReference.Type)
	assert.Equal(t, "https://example.com", sf.NavItems[0].PageReference.Attributes["url"])
}

func TestToSFUIApp_DashboardNavItem(t *testing.T) {
	app := &models.AppConfig{
		ID:    "app3",
		Label: "App",
		NavigationItems: []models.NavigationItem{
			{
				ID:          "nav-dash",
				Label:       "Dashboard",
				Type:        constants.NavigationTypeDashboard,
				DashboardID: "dash-001",
			},
		},
	}

	sf := toSFUIApp(app)

	require.Len(t, sf.NavItems, 1)
	require.NotNil(t, sf.NavItems[0].PageReference)
	assert.Equal(t, "standard__dashboard", sf.NavItems[0].PageReference.Type)
	assert.Equal(t, "dash-001", sf.NavItems[0].PageReference.Attributes["dashboardId"])
}

func TestToSFUIApp_PageNavItem(t *testing.T) {
	app := &models.AppConfig{
		ID:    "app4",
		Label: "App",
		NavigationItems: []models.NavigationItem{
			{
				ID:            "nav-page",
				Label:         "Home",
				Type:          constants.NavigationTypePage,
				ObjectAPIName: "Home",
			},
		},
	}

	sf := toSFUIApp(app)

	require.Len(t, sf.NavItems, 1)
	assert.Equal(t, "Home", sf.NavItems[0].StandardType)
}

func TestToSFUIApp_EmptyNavItems(t *testing.T) {
	app := &models.AppConfig{
		ID:    "empty_app",
		Label: "Empty",
	}

	sf := toSFUIApp(app)
	assert.Empty(t, sf.NavItems)
}

// ---------------------------------------------------------------------------
// toAppConfig — Tooling API request to internal model
// ---------------------------------------------------------------------------

func TestToAppConfig_Basic(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "my_app",
		Metadata: toolingCustomApplicationMetadata{
			Label:       "My App",
			Description: "Test application",
		},
	}

	app := req.toAppConfig()

	assert.Equal(t, "my_app", app.ID)
	assert.Equal(t, "My App", app.Label)
	assert.Equal(t, "Test application", app.Description)
}

func TestToAppConfig_StandardObjectTabs(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "app_with_tabs",
		Metadata: toolingCustomApplicationMetadata{
			Label: "Tabbed App",
			Tabs:  []string{"standard-Account", "standard-Contact"},
		},
	}

	app := req.toAppConfig()

	require.Len(t, app.NavigationItems, 2)
	assert.Equal(t, constants.NavigationTypeObject, app.NavigationItems[0].Type)
	assert.Equal(t, "Account", app.NavigationItems[0].ObjectAPIName)
	assert.Equal(t, constants.NavigationTypeObject, app.NavigationItems[1].Type)
	assert.Equal(t, "Contact", app.NavigationItems[1].ObjectAPIName)
}

func TestToAppConfig_CustomObjectTabs(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "custom_app",
		Metadata: toolingCustomApplicationMetadata{
			Label: "Custom App",
			Tabs:  []string{"Custom_Obj__c"},
		},
	}

	app := req.toAppConfig()

	require.Len(t, app.NavigationItems, 1)
	assert.Equal(t, constants.NavigationTypeObject, app.NavigationItems[0].Type)
	assert.Equal(t, "Custom_Obj__c", app.NavigationItems[0].ObjectAPIName)
}

func TestToAppConfig_StandardPageTabs(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "page_app",
		Metadata: toolingCustomApplicationMetadata{
			Label: "Page App",
			Tabs:  []string{"Home", "Feed"},
		},
	}

	app := req.toAppConfig()

	require.Len(t, app.NavigationItems, 2)
	assert.Equal(t, constants.NavigationTypePage, app.NavigationItems[0].Type)
	assert.Equal(t, "Home", app.NavigationItems[0].Label)
	assert.Equal(t, constants.NavigationTypePage, app.NavigationItems[1].Type)
	assert.Equal(t, "Feed", app.NavigationItems[1].Label)
}

func TestToAppConfig_NilTabs(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "no_tabs",
		Metadata: toolingCustomApplicationMetadata{
			Label: "No Tabs",
		},
	}

	app := req.toAppConfig()
	assert.Nil(t, app.NavigationItems)
}

func TestToAppConfig_MixedTabs(t *testing.T) {
	req := &toolingCustomApplicationRequest{
		FullName: "mixed_app",
		Metadata: toolingCustomApplicationMetadata{
			Label: "Mixed App",
			Tabs:  []string{"standard-Account", "Custom_Obj__c", "Home"},
		},
	}

	app := req.toAppConfig()

	require.Len(t, app.NavigationItems, 3)
	assert.Equal(t, constants.NavigationTypeObject, app.NavigationItems[0].Type)
	assert.Equal(t, "Account", app.NavigationItems[0].ObjectAPIName)
	assert.Equal(t, constants.NavigationTypeObject, app.NavigationItems[1].Type)
	assert.Equal(t, "Custom_Obj__c", app.NavigationItems[1].ObjectAPIName)
	assert.Equal(t, constants.NavigationTypePage, app.NavigationItems[2].Type)
}
