import type {
  AgentRunId,
  AttemptId,
  ChangeSetId,
  ConnectionId,
  CredentialReference,
  CredentialReferenceId,
  FactoryRunId,
  OperationId,
  PlanRevisionId,
  ProviderDescriptor,
  ProviderOperationContext,
  ProviderReference,
  ProviderResult,
  TaskId,
  WorkspaceId,
} from "@awp/contracts";

export interface ReconcileRequest {
  readonly context: ProviderOperationContext;
  readonly reference: ProviderReference;
}
export interface ProviderObservation {
  readonly state: string;
  readonly details: Readonly<Record<string, unknown>>;
}
export interface DescribedProvider {
  describe(): Promise<ProviderDescriptor>;
}

export interface AccountDescriptor {
  readonly accountKey: string;
  readonly label: string;
  readonly capabilities: readonly string[];
}
export interface AccountProvider extends DescribedProvider {
  listAccounts(
    context: ProviderOperationContext,
  ): Promise<ProviderResult<readonly AccountDescriptor[]>>;
}

export interface RepositoryInspection {
  readonly defaultBranch: string;
  readonly headRevision: string;
}
export interface ForgeProvider extends DescribedProvider {
  inspectRepository(
    context: ProviderOperationContext,
    repositoryKey: string,
  ): Promise<ProviderResult<RepositoryInspection>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}

export interface TrustedPublishRequest {
  readonly context: ProviderOperationContext;
  readonly changeSetId: ChangeSetId;
  readonly repositoryKey: string;
  readonly baseRevision: string;
  readonly candidateDigest: string;
}
export interface TrustedPublisher {
  publish(request: TrustedPublishRequest): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}

export interface FactoryProvider extends DescribedProvider {
  start(
    context: ProviderOperationContext,
    factoryRunId: FactoryRunId,
    planRevisionId: PlanRevisionId,
  ): Promise<ProviderResult<ProviderObservation>>;
  cancel(
    context: ProviderOperationContext,
    factoryRunId: FactoryRunId,
  ): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}
export interface AgentProvider extends DescribedProvider {
  startAttempt(
    context: ProviderOperationContext,
    attemptId: AttemptId,
    agentRunId: AgentRunId,
    taskId: TaskId,
    workspaceId: WorkspaceId,
  ): Promise<ProviderResult<ProviderObservation>>;
  cancelAttempt(
    context: ProviderOperationContext,
    attemptId: AttemptId,
  ): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}
export interface DurableWorkflowProvider extends DescribedProvider {
  start(
    context: ProviderOperationContext,
    operationId: OperationId,
    workflowKind: string,
    input: unknown,
  ): Promise<ProviderResult<ProviderObservation>>;
  cancel(
    context: ProviderOperationContext,
    operationId: OperationId,
  ): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}
export interface WorkspaceProvider extends DescribedProvider {
  create(
    context: ProviderOperationContext,
    workspaceId: WorkspaceId,
    profileKey: string,
  ): Promise<ProviderResult<ProviderObservation>>;
  destroy(
    context: ProviderOperationContext,
    workspaceId: WorkspaceId,
  ): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}
export interface CIProvider extends DescribedProvider {
  start(
    context: ProviderOperationContext,
    repositoryKey: string,
    candidateDigest: string,
  ): Promise<ProviderResult<ProviderObservation>>;
  cancel(
    context: ProviderOperationContext,
    reference: ProviderReference,
  ): Promise<ProviderResult<ProviderObservation>>;
  reconcile(request: ReconcileRequest): Promise<ProviderResult<ProviderObservation>>;
}

export interface SecretLease {
  readonly value: string;
  readonly expiresAt?: string;
  dispose(): void;
}
export interface SecretStore {
  resolve(reference: CredentialReference, purpose: string): Promise<SecretLease>;
  rotate(
    referenceId: CredentialReferenceId,
    connectionId: ConnectionId,
  ): Promise<CredentialReference>;
}
