package dialectsfcrm_test

import (
	"context"
	"encoding/json"
	"net/http"
	"reflect"
	"testing"

	dialectsfcrm "github.com/nexuscrm/dialect-sf-crm"
	"github.com/nexuscrm/dialect-sf-crm/wire"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/dialect"
	"github.com/nexuscrm/shared/pkg/models"
)

func TestIdentityNeutralUsesMountedVersionForURLDiscovery(t *testing.T) {
	email := "ada@example.com"
	req := &dialect.Request{
		Version: "v62.0",
		Params:  map[string]string{"orgId": constants.DefaultOrgID, "userId": "005000000000123AAA"},
		User: &models.UserSession{
			ID:    "005000000000123AAA",
			Name:  "Ada Lovelace",
			Email: &email,
		},
	}

	resp, err := dialectsfcrm.IdentityNeutralHandler(context.Background(), req, dialect.Deps{})
	if err != nil {
		t.Fatalf("IdentityNeutralHandler returned error: %v", err)
	}
	body := responseJSONMap(t, resp)
	if body["id"] != "http://127.0.0.1:3001/id/00D000000000001/005000000000123AAA" {
		t.Fatalf("identity id = %#v", body["id"])
	}
	if body["username"] != "ada@example.com" || body["email"] != "ada@example.com" {
		t.Fatalf("identity email fields = username:%#v email:%#v", body["username"], body["email"])
	}
	urls := body["urls"].(map[string]any)
	if urls["rest"] != "http://127.0.0.1:3001/services/data/v62.0/" ||
		urls["enterprise"] != "http://127.0.0.1:3001/services/Soap/c/62.0/00D000000000001" {
		t.Fatalf("identity urls = %#v", urls)
	}
}

func TestIdentityNeutralCrossUserRequiresViewAllUsersCapability(t *testing.T) {
	req := &dialect.Request{
		Version: "v63.0",
		Params:  map[string]string{"orgId": constants.DefaultOrgID, "userId": "005OTHER000000AAA"},
		User:    &models.UserSession{ID: "005CURRENT0000AAA", Name: "Ada Lovelace"},
	}

	resp, err := dialectsfcrm.IdentityNeutralHandler(context.Background(), req, dialect.Deps{
		Contracts: contract.Deps{Policy: fakeCapabilityPolicy{}},
	})
	if err != nil {
		t.Fatalf("IdentityNeutralHandler returned error: %v", err)
	}
	if resp.Status != http.StatusForbidden {
		t.Fatalf("status = %d, want 403", resp.Status)
	}
	wantBody := wire.SFErrorResponse(wire.SFCodeForbidden, "Cannot view other user's identity")
	if !reflect.DeepEqual(resp.Body, wantBody) {
		t.Fatalf("body = %#v, want %#v", resp.Body, wantBody)
	}

	resp, err = dialectsfcrm.IdentityNeutralHandler(context.Background(), req, dialect.Deps{
		Contracts: contract.Deps{Policy: fakeCapabilityPolicy{allow: true}},
	})
	if err != nil {
		t.Fatalf("IdentityNeutralHandler with capability returned error: %v", err)
	}
	body := responseJSONMap(t, resp)
	if body["user_id"] != "005OTHER000000AAA" {
		t.Fatalf("user_id = %#v, want target user", body["user_id"])
	}
}

type fakeCapabilityPolicy struct {
	allow bool
}

func (p fakeCapabilityPolicy) Access(context.Context, *models.UserSession, string, contract.AccessRequest) (*contract.EffectiveObjectAccess, error) {
	return nil, nil
}

func (p fakeCapabilityPolicy) HasCapability(context.Context, *models.UserSession, contract.Capability) bool {
	return p.allow
}

func responseJSONMap(t *testing.T, resp *dialect.Response) map[string]any {
	t.Helper()
	if resp.Status != http.StatusOK {
		t.Fatalf("status = %d, want 200; body=%#v", resp.Status, resp.Body)
	}
	data, err := json.Marshal(resp.Body)
	if err != nil {
		t.Fatalf("marshal response body: %v", err)
	}
	var body map[string]any
	if err := json.Unmarshal(data, &body); err != nil {
		t.Fatalf("unmarshal response body: %v", err)
	}
	return body
}
