package scenarios_test

// Scenario tests for Approval Queue record display.
//
// APPR-003: Verify that records in the Approval Queue display proper names,
//           not "Unknown". This was observed during Chrome testing.

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"testing"
	"time"

	"github.com/nexuscrm/tests/contract/internal/liveapi"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ---------- APPR-003: Approval Queue records show actual names ----------

func TestAPPR003_ApprovalQueueRecordNames(t *testing.T) {
	// Scenario: When records are submitted for approval, the Approval Queue
	// should display the record's Name (e.g., "Acme Corp"), not "Unknown".
	// Chrome testing revealed all 4 pending approvals showed "Unknown" on
	// the NexusCRM backend.
	//
	// This test creates an Account, submits it for approval, then queries
	// the approval workitems to verify the record reference is resolvable.

	client := liveapi.NewAuthenticatedClient(t)

	// Step 1: Check if Account object exists
	descResp, err := client.Do(http.MethodGet, "/sobjects/Account/describe", "", nil)
	require.NoError(t, err)
	if descResp.StatusCode == http.StatusNotFound {
		t.Fatal("Account object does not exist")
	}
	descResp.Body.Close()

	// Step 2: Create a test Account
	acctName := fmt.Sprintf("ApprQueueTest_%d", time.Now().UnixNano())
	createResp, err := client.DoJSON(http.MethodPost, "/sobjects/Account", map[string]any{
		"Name": acctName,
	})
	require.NoError(t, err)

	createBody := liveapi.ReadBody(t, createResp)
	require.Equal(t, http.StatusCreated, createResp.StatusCode,
		"Account creation failed: %s", string(createBody))

	var created struct {
		ID string `json:"id"`
	}
	require.NoError(t, json.Unmarshal(createBody, &created))
	require.NotEmpty(t, created.ID)

	t.Cleanup(func() {
		delResp, _ := client.Do(http.MethodDelete, "/sobjects/Account/"+created.ID, "", nil)
		if delResp != nil {
			delResp.Body.Close()
		}
	})

	// Step 3: Submit the Account for approval
	submitResp, err := client.DoJSON(http.MethodPost, "/process/approvals", map[string]any{
		"requests": []map[string]any{{
			"actionType":       "Submit",
			"contextId":        created.ID,
			"comments":         "Test submission for approval queue display",
			"nextApproverIds":  []string{},
			"processDefinitionNameOrId": "",
		}},
	})
	require.NoError(t, err)

	submitBody := liveapi.ReadBody(t, submitResp)

	if submitResp.StatusCode != http.StatusOK {
		t.Skipf("could not submit record for approval (status %d): %s",
			submitResp.StatusCode, string(submitBody))
	}

	// Step 4: Query ProcessInstanceWorkitem to check the approval queue entry
	soql := fmt.Sprintf(
		"SELECT Id,ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem "+
			"WHERE ProcessInstance.TargetObjectId='%s'",
		created.ID,
	)
	queryResp, err := client.Do(http.MethodGet, "/query?q="+url.QueryEscape(soql), "", nil)
	require.NoError(t, err)

	queryBody := liveapi.ReadBody(t, queryResp)

	if queryResp.StatusCode != http.StatusOK {
		t.Logf("SOQL query for workitems failed (status %d): %s", queryResp.StatusCode, string(queryBody))
		// Try simpler query
		soql2 := "SELECT Id,ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem LIMIT 5"
		queryResp2, err2 := client.Do(http.MethodGet, "/query?q="+url.QueryEscape(soql2), "", nil)
		require.NoError(t, err2)
		queryBody = liveapi.ReadBody(t, queryResp2)

		if queryResp2.StatusCode != http.StatusOK {
			t.Fatalf("cannot query ProcessInstanceWorkitem at all (status %d): %s",
				queryResp2.StatusCode, string(queryBody))
		}
	}

	var queryResult struct {
		TotalSize int               `json:"totalSize"`
		Records   []json.RawMessage `json:"records"`
	}
	require.NoError(t, json.Unmarshal(queryBody, &queryResult))

	if queryResult.TotalSize == 0 {
		t.Skip("no approval workitems found — approval submission may not have created a workitem")
	}

	// Step 5: For each workitem, verify TargetObjectId resolves to a real record
	for i, raw := range queryResult.Records {
		var workitem map[string]any
		require.NoError(t, json.Unmarshal(raw, &workitem))

		// Extract TargetObjectId
		var targetID string
		if pi, ok := workitem["ProcessInstance"].(map[string]any); ok {
			if tid, ok := pi["TargetObjectId"].(string); ok {
				targetID = tid
			}
		}

		if targetID == "" {
			t.Logf("workitem %d: no TargetObjectId found", i)
			continue
		}

		// Try to resolve the target record
		getResp, getErr := client.Do(http.MethodGet, "/sobjects/Account/"+targetID, "", nil)
		if getErr != nil {
			t.Logf("workitem %d: cannot resolve TargetObjectId %s: %v", i, targetID, getErr)
			continue
		}

		getBody := liveapi.ReadBody(t, getResp)

		if getResp.StatusCode == http.StatusOK {
			var record map[string]any
			if json.Unmarshal(getBody, &record) == nil {
				name, _ := record["Name"].(string)
				assert.NotEmpty(t, name,
					"workitem %d: resolved record has no Name — UI would show 'Unknown'", i)
				t.Logf("workitem %d: TargetObjectId=%s resolves to Name=%q", i, targetID, name)
			}
		} else {
			t.Errorf("workitem %d: TargetObjectId=%s returns %d — UI would show 'Unknown': %s",
				i, targetID, getResp.StatusCode, string(getBody))
		}
	}
}
