import type {
  AgentRunId,
  AttemptId,
  AuditRecord,
  BusinessEvent,
  ChangeSetId,
  FactoryRunId,
  GoalId,
  OutboxMessageId,
  PlanId,
  PlanRevisionId,
  ProjectId,
  ProjectVisionVersionId,
  ReviewId,
  TaskId,
  WorkspaceId,
} from "@awp/contracts";
import type {
  AgentRun,
  Attempt,
  ChangeSet,
  FactoryRun,
  Goal,
  Plan,
  PlanRevision,
  Project,
  ProjectVisionVersion,
  Review,
  Task,
  Workspace,
} from "@awp/domain";

export interface EntityRepository<T, Id> {
  getById(id: Id): Promise<T | undefined>;
  insert(entity: T): Promise<void>;
  update(entity: T): Promise<void>;
}

export type ProjectRepository = EntityRepository<Project, ProjectId>;
export interface ProjectVisionRepository {
  getById(id: ProjectVisionVersionId): Promise<ProjectVisionVersion | undefined>;
  getCurrent(projectId: ProjectId): Promise<ProjectVisionVersion | undefined>;
  insert(entity: ProjectVisionVersion): Promise<void>;
}
export interface GoalRepository extends EntityRepository<Goal, GoalId> {
  listByProject(projectId: ProjectId): Promise<readonly Goal[]>;
}
export interface PlanRepository extends EntityRepository<Plan, PlanId> {
  listByProject(projectId: ProjectId): Promise<readonly Plan[]>;
}
export interface PlanRevisionRepository {
  getById(id: PlanRevisionId): Promise<PlanRevision | undefined>;
  getCurrent(planId: PlanId): Promise<PlanRevision | undefined>;
  insert(entity: PlanRevision): Promise<void>;
}
export interface TaskRepository extends EntityRepository<Task, TaskId> {
  listByProject(projectId: ProjectId): Promise<readonly Task[]>;
}
export interface FactoryRunRepository extends EntityRepository<FactoryRun, FactoryRunId> {
  listByProject(projectId: ProjectId): Promise<readonly FactoryRun[]>;
}
export type AgentRunRepository = EntityRepository<AgentRun, AgentRunId>;
export type WorkspaceRepository = EntityRepository<Workspace, WorkspaceId>;
export type AttemptRepository = EntityRepository<Attempt, AttemptId>;
export type ChangeSetRepository = EntityRepository<ChangeSet, ChangeSetId>;
export type ReviewRepository = EntityRepository<Review, ReviewId>;

export interface BusinessEventRepository {
  append(event: BusinessEvent): Promise<void>;
}
export interface AuditRepository {
  append(record: AuditRecord): Promise<void>;
}
export interface OutboxMessage {
  readonly id: OutboxMessageId;
  readonly topic: string;
  readonly payload: unknown;
  readonly occurredAt: string;
}
export interface OutboxRepository {
  append(message: OutboxMessage): Promise<void>;
}

export interface ApplicationTransaction {
  readonly projects: ProjectRepository;
  readonly projectVisions: ProjectVisionRepository;
  readonly goals: GoalRepository;
  readonly plans: PlanRepository;
  readonly planRevisions: PlanRevisionRepository;
  readonly tasks: TaskRepository;
  readonly factoryRuns: FactoryRunRepository;
  readonly agentRuns: AgentRunRepository;
  readonly workspaces: WorkspaceRepository;
  readonly attempts: AttemptRepository;
  readonly changeSets: ChangeSetRepository;
  readonly reviews: ReviewRepository;
  readonly events: BusinessEventRepository;
  readonly audit: AuditRepository;
  readonly outbox: OutboxRepository;
}

export interface UnitOfWork {
  transaction<T>(work: (tx: ApplicationTransaction) => Promise<T>): Promise<T>;
}
