// Package pr records SCM observations for pull requests associated with sessions.
package pr

import (
	"context"
	"time"

	"github.com/aoagents/agent-orchestrator/backend/internal/domain"
	"github.com/aoagents/agent-orchestrator/backend/internal/ports"
)

type lifecycle interface {
	ApplyPRObservation(ctx context.Context, id domain.SessionID, o ports.PRObservation) error
}

// Manager persists PR observations and forwards them to lifecycle for agent
// nudges and direct lifecycle effects.
type Manager struct {
	writer    ports.PRWriter
	lifecycle lifecycle
	clock     func() time.Time
}

// Deps are the collaborators a PR Manager needs.
type Deps struct {
	Writer    ports.PRWriter
	Lifecycle lifecycle
	Clock     func() time.Time
}

// New builds a PR Manager from its dependencies, defaulting the clock to time.Now.
func New(d Deps) *Manager {
	m := &Manager{writer: d.Writer, lifecycle: d.Lifecycle, clock: d.Clock}
	if m.clock == nil {
		m.clock = time.Now
	}
	return m
}

// ApplyObservation records a successfully fetched PR observation. Failed fetches
// are ignored because their fields are not authoritative facts.
func (m *Manager) ApplyObservation(ctx context.Context, id domain.SessionID, o ports.PRObservation) error {
	if !o.Fetched {
		return nil
	}
	if err := m.write(ctx, id, o); err != nil {
		return err
	}
	if m.lifecycle == nil {
		return nil
	}
	return m.lifecycle.ApplyPRObservation(ctx, id, o)
}

func (m *Manager) write(ctx context.Context, id domain.SessionID, o ports.PRObservation) error {
	now := m.clock()
	row := domain.PullRequest{URL: o.URL, SessionID: id, Number: o.Number, Draft: o.Draft, Merged: o.Merged, Closed: o.Closed, CI: o.CI, Review: o.Review, Mergeability: o.Mergeability, UpdatedAt: now}
	checks := make([]domain.PullRequestCheck, len(o.Checks))
	for i, c := range o.Checks {
		checks[i] = domain.PullRequestCheck{Name: c.Name, CommitHash: c.CommitHash, Status: c.Status, URL: c.URL, LogTail: c.LogTail, CreatedAt: now}
	}
	comments := make([]domain.PullRequestComment, len(o.Comments))
	for i, c := range o.Comments {
		comments[i] = domain.PullRequestComment{ID: c.ID, Author: c.Author, File: c.File, Line: c.Line, Body: c.Body, Resolved: c.Resolved, CreatedAt: now}
	}
	return m.writer.WritePR(ctx, row, checks, comments)
}
