// Package roleproposal implements the team_role_proposal Approval subject.
// The generic Approval instance is the only durable proposal row; this package
// validates, renders, and atomically applies its versioned payload.
package roleproposal

import (
	"encoding/json"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/store/approval"
)

const (
	SubjectType          = "team_role_proposal"
	PayloadSchemaVersion = 4

	StatusPending   = approval.StatePending
	StatusApproved  = approval.StateApproved
	StatusRejected  = approval.StateRejected
	StatusCancelled = approval.StateCancelled
	StatusApplied   = approval.StateApproved
)

// MemberInput is one requested active Team member overlay.
type MemberInput struct {
	TeamMemberID      string
	RoleLabel         *string
	RoleOverlayPrompt *string
	WakeOnTeamMention *bool
}

// SubmitInput is an authenticated Team leader command.
type SubmitInput struct {
	TeamID          string
	ClientRequestID string
	Description     *string
	Members         []MemberInput
	CorrelationID   string
	Now             time.Time
}

type WithdrawInput struct {
	ApprovalID      string
	ExpectedVersion int64
	ClientRequestID string
	Now             time.Time
}

// Applicant records the trusted runtime principal for audit and
// presentation. Authorization always re-checks current database facts.
type Applicant struct {
	AgentID      string `json:"agentId"`
	MemberID     string `json:"memberId"`
	TeamMemberID string `json:"teamMemberId"`
}

// BaseTeam is the Team portion of the immutable submission-time audit snapshot.
type BaseTeam struct {
	Description string `json:"description"`
}

// BaseMember is one canonical active-roster submission-time audit snapshot.
type BaseMember struct {
	TeamMemberID       string `json:"teamMemberId"`
	MemberName         string `json:"memberName"`
	MemberID           string `json:"memberId"`
	Role               string `json:"role"`
	RoleLabel          string `json:"roleLabel"`
	RoleOverlayPrompt  string `json:"roleOverlayPrompt"`
	RoleOverlayVersion int64  `json:"roleOverlayVersion"`
	WakeOnTeamMention  bool   `json:"wakeOnTeamMention"`
}

// Base contains immutable submission-time facts used for audit and target
// identity validation. Mutable role values do not fence a later approval.
type Base struct {
	Digest  string       `json:"digest"`
	Team    BaseTeam     `json:"team"`
	Members []BaseMember `json:"members"`
}

// MemberPayload is one proposed active Team member overlay.
type MemberPayload struct {
	TeamMemberID      string  `json:"teamMemberId"`
	MemberName        string  `json:"memberName"`
	RoleLabel         *string `json:"roleLabel,omitempty"`
	RoleOverlayPrompt *string `json:"roleOverlayPrompt,omitempty"`
	WakeOnTeamMention *bool   `json:"wakeOnTeamMention,omitempty"`
}

// Proposed is the complete desired Team role configuration.
type Proposed struct {
	Description *string         `json:"description,omitempty"`
	Members     []MemberPayload `json:"members"`
}

// Payload is the canonical immutable Approval payload.
type Payload struct {
	SchemaVersion   int       `json:"schemaVersion"`
	ClientRequestID string    `json:"clientRequestId"`
	Applicant       Applicant `json:"applicant"`
	Base            Base      `json:"base"`
	Proposed        Proposed  `json:"proposed"`
}

// Proposal is a read model derived entirely from one generic Approval instance.
// It is not backed by a Team-specific proposal table.
type Proposal struct {
	WorkspaceID           string
	TeamID                string
	ApplicantAgentID      string
	ApplicantMemberID     string
	ApplicantTeamMemberID string
	ClientRequestID       string
	ID                    string
	Status                string
	Version               int64
	Payload               json.RawMessage
	PayloadDigest         string
	CreatedAt             time.Time
	UpdatedAt             time.Time
	DecidedAt             *time.Time
}

// Result contains the Approval facts committed atomically by Submit.
type Result struct {
	Proposal    Proposal
	Approval    approval.Instance
	Assignments []approval.Assignment
	Created     bool
}

// DecisionResult is returned by Decide.
type DecisionResult struct {
	Proposal Proposal
	Approval approval.DecisionResult
	Changed  bool
	Applied  bool
	Stale    bool
}

type WithdrawResult struct {
	Proposal      Proposal
	Approval      approval.DecisionResult
	AlreadyClosed bool
}

type teamState struct {
	WorkspaceID       string
	TeamID            string
	Description       string
	CreatedByMemberID string
	Status            string
}

type memberState struct {
	TeamMemberID      string
	MemberID          string
	MemberName        string
	Role              string
	RoleLabel         string
	RoleOverlayPrompt string
	WakeOnTeamMention bool
	OverlayVersion    int64
}
