package manage

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

func (service *Service) resolveTargetView(ctx context.Context, workspaceID string, requestedKind TargetKind, targetRef string, strict bool) (TargetView, error) {
	ref := strings.TrimSpace(targetRef)
	if ref == "" {
		return TargetView{}, badRequest("target.ref is required")
	}

	kind := requestedKind
	if strings.TrimSpace(string(kind)) == "" {
		inferredKind, err := service.inferTargetKind(ctx, workspaceID, ref)
		if err != nil {
			return TargetView{}, err
		}
		kind = inferredKind
	}

	switch kind {
	case TargetKindChannel:
		row := service.db.QueryRow(ctx, `
SELECT COALESCE(NULLIF(cp.slug, ''), s.id)
FROM scopes s
JOIN scope_channel_profiles cp ON cp.scope_id = s.id
WHERE s.workspace_id = $1
  AND s.id = $2
  AND s.type = 'channel'
  AND s.status = 'active'
`, workspaceID, ref)
		var slug string
		if err := row.Scan(&slug); err != nil {
			if coredb.IsNotFound(err) {
				if strict {
					return TargetView{}, notFound("target channel not found")
				}
				return TargetView{Kind: kind, Ref: ref, Label: ref}, nil
			}
			return TargetView{}, fmt.Errorf("load trigger target scope channel: %w", err)
		}
		return TargetView{Kind: kind, Ref: ref, Label: "#" + slug}, nil
	case TargetKindReplyThread:
		row := service.db.QueryRow(ctx, `
SELECT COALESCE(s.parent_scope_id, ''), COALESCE(s.root_message_id, ''),
       COALESCE(NULLIF(parent_cp.slug, ''), s.parent_scope_id, ''),
       COALESCE(NULLIF(s.root_message_short_id, ''), s.root_message_id, '')
FROM scopes s
LEFT JOIN scope_channel_profiles parent_cp ON parent_cp.scope_id = s.parent_scope_id
WHERE s.workspace_id = $1
  AND s.id = $2
  AND s.type = 'thread'
  AND s.status = 'active'
`, workspaceID, ref)
		var parentChannelID string
		var parentMessageID string
		var channelSlug string
		var shortID string
		if err := row.Scan(&parentChannelID, &parentMessageID, &channelSlug, &shortID); err != nil {
			if coredb.IsNotFound(err) {
				if strict {
					return TargetView{}, notFound("target reply thread not found")
				}
				return TargetView{Kind: kind, Ref: ref, Label: ref}, nil
			}
			return TargetView{}, fmt.Errorf("load trigger target scope thread: %w", err)
		}
		return TargetView{
			Kind:            kind,
			Ref:             ref,
			Label:           fmt.Sprintf("#%s/%s", channelSlug, shortID),
			ParentChannelID: parentChannelID,
			ParentMessageID: parentMessageID,
		}, nil
	case TargetKindDM:
		row := service.db.QueryRow(ctx, `
SELECT id
FROM scopes
WHERE workspace_id = $1
  AND id = $2
  AND type = 'dm'
  AND status = 'active'
`, workspaceID, ref)
		var dmID string
		if err := row.Scan(&dmID); err != nil {
			if coredb.IsNotFound(err) {
				if strict {
					return TargetView{}, notFound("target DM not found")
				}
				return TargetView{Kind: kind, Ref: ref, Label: ref}, nil
			}
			return TargetView{}, fmt.Errorf("load trigger target scope DM: %w", err)
		}
		return TargetView{Kind: kind, Ref: ref, Label: "DM"}, nil
	case TargetKindTask:
		row := service.db.QueryRow(ctx, `
SELECT id
FROM scopes
WHERE workspace_id = $1
  AND id = $2
  AND type = 'task'
  AND status = 'active'
  AND archived_at IS NULL
`, workspaceID, ref)
		var taskScopeID string
		if err := row.Scan(&taskScopeID); err != nil {
			if coredb.IsNotFound(err) {
				if strict {
					return TargetView{}, notFound("target task not found")
				}
				return TargetView{Kind: kind, Ref: ref, Label: ref}, nil
			}
			return TargetView{}, fmt.Errorf("load trigger target scope task: %w", err)
		}
		return TargetView{Kind: kind, Ref: ref, Label: "#" + taskScopeID}, nil
	default:
		return TargetView{}, badRequest("unsupported target.kind")
	}
}

func (service *Service) inferTargetKind(ctx context.Context, workspaceID string, targetRef string) (TargetKind, error) {
	row := service.db.QueryRow(ctx, `
SELECT type
FROM scopes
WHERE workspace_id = $1
  AND id = $2
  AND status = 'active'
  AND archived_at IS NULL
`, workspaceID, targetRef)
	var scopeType string
	if err := row.Scan(&scopeType); err != nil {
		if coredb.IsNotFound(err) {
			return "", notFound("target not found")
		}
		return "", fmt.Errorf("infer trigger target kind from scope: %w", err)
	}
	switch scopeType {
	case "channel":
		return TargetKindChannel, nil
	case "thread":
		return TargetKindReplyThread, nil
	case "dm":
		return TargetKindDM, nil
	case "task":
		return TargetKindTask, nil
	default:
		return "", notFound("target not found")
	}
}
