package dialectsfcrm

import (
	"context"
	"fmt"
	"html"
	"net/url"
	"regexp"
	"strings"

	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/models"
)

// ContentDistributionHrefFieldsFunc returns fields whose values may contain
// legacy Salesforce ContentDistribution URLs for the supplied object.
type ContentDistributionHrefFieldsFunc func(objectName string) []string

const contentDistributionUnavailableLabel = "File unavailable"

var contentDistributionHrefAnchorRE = regexp.MustCompile(`(?i)href=["']([^"']+)["']`)

type recordReadDecorator interface {
	DecorateRecordRead(ctx context.Context, objectName string, recordID string, record contract.Record, req recordReadDecorationRequest) error
}

type recordAttachmentSourceResolver interface {
	ResolveAuthorizedRecordAttachmentSource(ctx context.Context, req contract.RecordAttachmentSourceRequest, lookup contract.RecordAttachmentSourceLookup, user *models.UserSession) (*contract.RecordAttachmentSourceResult, bool, error)
}

type recordReadDecorationRequest struct {
	FileURLPrefix                string
	User                         *models.UserSession
	RecordAttachmentSource       recordAttachmentSourceResolver
	RecordAttachmentSourceLookup contract.RecordAttachmentSourceLookup
}

type contentDistributionRecordReadDecorator struct {
	fieldsForObject ContentDistributionHrefFieldsFunc
}

// NewContentDistributionRecordReadDecorator returns the CRM-owned decorator
// that rewrites legacy Salesforce ContentDistribution hrefs into local file
// download URLs. Nil field provider means no decorator is installed, keeping
// the neutral runtime app-blind by default.
func NewContentDistributionRecordReadDecorator(fieldsForObject ContentDistributionHrefFieldsFunc) recordReadDecorator {
	if fieldsForObject == nil {
		return nil
	}
	return &contentDistributionRecordReadDecorator{
		fieldsForObject: fieldsForObject,
	}
}

func (d *contentDistributionRecordReadDecorator) DecorateRecordRead(ctx context.Context, objectName string, recordID string, record contract.Record, req recordReadDecorationRequest) error {
	if d == nil || d.fieldsForObject == nil || record == nil {
		return nil
	}
	for _, fieldName := range d.fieldsForObject(objectName) {
		raw, ok := record[fieldName].(string)
		if !ok || strings.TrimSpace(raw) == "" {
			continue
		}
		rewritten, err := d.rewriteFieldValue(ctx, objectName, recordID, raw, req)
		if err != nil {
			return fmt.Errorf("href rewrite %s.%s: %w", objectName, fieldName, err)
		}
		if rewritten != raw {
			record[fieldName] = rewritten
		}
	}
	return nil
}

// rewriteFieldValue rewrites a single column's value, handling two shapes:
//
//  1. HTML anchor `<a href=".../sfc/p/...">label</a>`. The href is replaced
//     inline and the visible label is preserved.
//  2. Bare Salesforce ContentDistribution URLs. The local URL is wrapped in an
//     anchor whose label is the resolved file name.
func (d *contentDistributionRecordReadDecorator) rewriteFieldValue(ctx context.Context, parentObjectAPIName, parentID, value string, req recordReadDecorationRequest) (string, error) {
	localFileURLPrefix := strings.TrimRight(strings.TrimSpace(req.FileURLPrefix), "/")
	if localFileURLPrefix == "" {
		return value, nil
	}
	if req.User == nil || req.RecordAttachmentSource == nil || req.RecordAttachmentSourceLookup == nil {
		return value, nil
	}
	if idx := contentDistributionHrefAnchorRE.FindStringSubmatchIndex(value); idx != nil {
		hrefStart, hrefEnd := idx[2], idx[3]
		href := html.UnescapeString(value[hrefStart:hrefEnd])
		if strings.HasPrefix(href, localFileURLPrefix+"/") {
			return value, nil
		}
		distIDBody, ok := extractDistributionIDBody(href)
		if !ok {
			return value, nil
		}
		row, err := d.resolveAuthorizedDistribution(ctx, parentObjectAPIName, parentID, distIDBody, req)
		if err != nil || row == nil {
			return value, err
		}
		if row.unavailable {
			return value[:hrefStart] + "#" + value[hrefEnd:], nil
		}
		newHref := localFileDownloadURL(localFileURLPrefix, row.id)
		return value[:hrefStart] + newHref + value[hrefEnd:], nil
	}

	trimmed := strings.TrimSpace(value)
	if !strings.HasPrefix(trimmed, "http://") && !strings.HasPrefix(trimmed, "https://") {
		return value, nil
	}
	if strings.HasPrefix(trimmed, localFileURLPrefix+"/") {
		return value, nil
	}
	distIDBody, ok := extractDistributionIDBody(trimmed)
	if !ok {
		return value, nil
	}
	row, err := d.resolveAuthorizedDistribution(ctx, parentObjectAPIName, parentID, distIDBody, req)
	if err != nil || row == nil {
		return value, err
	}
	if row.unavailable {
		return contentDistributionUnavailableLabel, nil
	}
	label := html.EscapeString(row.name)
	return fmt.Sprintf(`<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>`, localFileDownloadURL(localFileURLPrefix, row.id), label), nil
}

func localFileDownloadURL(localFileURLPrefix, fileID string) string {
	return fmt.Sprintf("%s/%s/download", strings.TrimRight(strings.TrimSpace(localFileURLPrefix), "/"), fileID)
}

// extractDistributionIDBody pulls the 12-char ContentDistribution body that
// Salesforce embeds in `/sfc/p/<orgNs>/a/<distIdBody>/<secret>`.
func extractDistributionIDBody(href string) (string, bool) {
	parsed, err := url.Parse(strings.TrimSpace(href))
	if err != nil {
		return "", false
	}
	segments := strings.Split(strings.Trim(parsed.Path, "/"), "/")
	for i := 0; i+5 < len(segments); i++ {
		if segments[i] != "sfc" || segments[i+1] != "p" || segments[i+3] != "a" {
			continue
		}
		distIDBody := segments[i+4]
		if len(distIDBody) != 12 || segments[i+5] == "" {
			return "", false
		}
		return distIDBody, true
	}
	return "", false
}

type resolvedSystemFile struct {
	id          string
	name        string
	unavailable bool
}

func (d *contentDistributionRecordReadDecorator) resolveAuthorizedDistribution(ctx context.Context, parentObjectAPIName, parentID, distIDBody string, req recordReadDecorationRequest) (*resolvedSystemFile, error) {
	if req.User == nil || req.RecordAttachmentSource == nil || req.RecordAttachmentSourceLookup == nil {
		return nil, nil
	}
	result, found, err := req.RecordAttachmentSource.ResolveAuthorizedRecordAttachmentSource(ctx, contract.RecordAttachmentSourceRequest{
		ParentObjectAPIName: parentObjectAPIName,
		ParentID:            parentID,
		SourceObject:        "ContentDistribution",
		SourceField:         "IdBody",
		SourceValue:         distIDBody,
	}, req.RecordAttachmentSourceLookup, req.User)
	if err != nil || !found {
		return nil, err
	}
	if result == nil {
		return &resolvedSystemFile{unavailable: true}, nil
	}
	fileID := strings.TrimSpace(result.FileID)
	if fileID == "" {
		return &resolvedSystemFile{unavailable: true}, nil
	}
	name := strings.TrimSpace(result.FileName)
	if name == "" {
		name = fileID
	}
	return &resolvedSystemFile{id: fileID, name: name}, nil
}
