package validate

import (
	"strings"

	contracterrors "bit.admedia.com/scm/ad/adpilot-indexing-commit-intel.com/internal/contracts/errors"
	"bit.admedia.com/scm/ad/adpilot-indexing-commit-intel.com/internal/contracts/events"
	"bit.admedia.com/scm/ad/adpilot-indexing-commit-intel.com/internal/contracts/metadata"
)

func envelope(env metadata.Envelope) error {
	if strings.TrimSpace(env.EventID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "event_id", "event_id is required")
	}
	if strings.TrimSpace(env.EventVersion) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "event_version", "event_version is required")
	}
	if env.EventVersion != metadata.EventVersionV1 {
		return contracterrors.New(contracterrors.CodeUnsupportedVersion, "event_version", "unsupported event version")
	}
	if env.CreatedAt.IsZero() {
		return contracterrors.New(contracterrors.CodeMissingField, "created_at", "created_at is required")
	}
	return nil
}

func repoCommit(repoID, commitSHA string) error {
	if strings.TrimSpace(repoID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "repo_id", "repo_id is required")
	}
	if strings.TrimSpace(commitSHA) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "commit_sha", "commit_sha is required")
	}
	return nil
}

// GraphArtifactReady validates a graph.artifact.ready event.
func GraphArtifactReady(event events.GraphArtifactReadyEvent) error {
	if err := envelope(event.Envelope); err != nil {
		return err
	}
	if err := repoCommit(event.RepoID, event.CommitSHA); err != nil {
		return err
	}
	if strings.TrimSpace(event.ArtifactID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "artifact_id", "artifact_id is required")
	}
	if strings.TrimSpace(event.ArtifactURI) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "artifact_uri", "artifact_uri is required")
	}
	if strings.TrimSpace(event.ParserVersion) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "parser_version", "parser_version is required")
	}
	if strings.TrimSpace(event.GraphSchemaVersion) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "graph_schema_version", "graph_schema_version is required")
	}
	return nil
}

// GraphDeltaReady validates a graph.delta.ready event.
func GraphDeltaReady(event events.GraphDeltaReadyEvent) error {
	if err := envelope(event.Envelope); err != nil {
		return err
	}
	if strings.TrimSpace(event.RepoID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "repo_id", "repo_id is required")
	}
	if strings.TrimSpace(event.BaseCommitSHA) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "base_commit_sha", "base_commit_sha is required")
	}
	if strings.TrimSpace(event.TargetCommitSHA) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "target_commit_sha", "target_commit_sha is required")
	}
	if strings.TrimSpace(event.DeltaArtifactID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "delta_artifact_id", "delta_artifact_id is required")
	}
	if strings.TrimSpace(event.DeltaArtifactURI) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "delta_artifact_uri", "delta_artifact_uri is required")
	}
	if strings.TrimSpace(event.GraphSchemaVersion) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "graph_schema_version", "graph_schema_version is required")
	}
	return nil
}

// CommitAnalysisReady validates a commit.analysis.ready event.
func CommitAnalysisReady(event events.CommitAnalysisReadyEvent) error {
	if err := envelope(event.Envelope); err != nil {
		return err
	}
	if err := repoCommit(event.RepoID, event.CommitSHA); err != nil {
		return err
	}
	if strings.TrimSpace(event.AnalysisID) == "" {
		return contracterrors.New(contracterrors.CodeMissingField, "analysis_id", "analysis_id is required")
	}
	return nil
}
