import type { Id } from "@code/backend/convex/_generated/dataModel";
import type { WorkNotice } from "@code/primitives/work";

import type { ConversationMessage } from "@/lib/chat/types";

export interface WorkRecord {
  readonly _id: Id<"works">;
  readonly title: string;
  readonly objective: string;
  readonly status: string;
  readonly definitionVersion?: number;
  readonly definitionApprovalVersion?: number;
  readonly designVersion?: number;
  readonly signals: readonly {
    readonly sources: readonly { messageId: string; rawText: string }[];
  }[];
  readonly runs: readonly WorkRun[];
  readonly definition: {
    readonly risk?: string;
    readonly questions?: readonly { status: string }[];
  } | null;
  readonly design: {
    readonly architectureSummary?: string;
    readonly slices?: readonly {
      readonly id: string;
      readonly title: string;
      readonly observableBehavior: string;
    }[];
  } | null;
}

export interface WorkRun {
  readonly artifacts?: readonly WorkArtifact[];
  readonly attemptEvents?: readonly WorkAttemptEvent[];
  readonly baseRevision?: string;
  readonly candidateRevision?: string;
  readonly executionKind?: string;
  readonly _id: Id<"workRuns">;
  readonly status: string;
  readonly terminalClassification?: string;
  readonly terminalSummary?: string;
}

export interface WorkArtifact {
  readonly _id: string;
  readonly metadataJson: string;
  readonly title: string;
  readonly uri?: string;
}

export interface WorkAttemptEvent {
  readonly _id: string;
  readonly message: string;
}

export interface GitConnection {
  readonly id: string;
  readonly provider: "github" | "gitea";
  readonly serverUrl: string;
  readonly username?: string;
}

export interface ProjectListItem {
  readonly id: string;
  readonly name: string;
}

export interface WorkspaceState {
  readonly agent: {
    readonly error?: Error;
    readonly historyReady: boolean;
    readonly messages: readonly ConversationMessage[];
    readonly sendMessage: (
      message: string,
      options?: { readonly images?: readonly File[] }
    ) => Promise<void>;
    readonly status:
      | "connecting"
      | "error"
      | "idle"
      | "streaming"
      | "submitted";
  };
  readonly approveDefinition: (
    workId: Id<"works">,
    version: number
  ) => Promise<unknown>;
  readonly approveDesign: (
    workId: Id<"works">,
    definitionVersion: number,
    designVersion: number
  ) => Promise<unknown>;
  readonly authorizeGithub: () => Promise<unknown>;
  readonly cancelExecution: (runId: Id<"workRuns">) => Promise<unknown>;
  readonly cancelSimulation: (runId: Id<"workRuns">) => Promise<unknown>;
  readonly clearOperationError: () => void;
  readonly connectGitea: (input: {
    readonly serverUrl: string;
    readonly token: string;
    readonly username?: string;
  }) => Promise<void>;
  readonly connectLinkedGithub: () => Promise<void>;
  readonly connectRepository: () => Promise<void>;
  readonly error?: Error;
  readonly gitConnections: readonly GitConnection[] | undefined;
  readonly operationError?: Error;
  readonly pending: boolean;
  readonly projectGitConnection: GitConnection | null | undefined;
  readonly projects: readonly ProjectListItem[] | undefined;
  readonly repository: string;
  readonly requestDefinition: (workId: Id<"works">) => Promise<unknown>;
  readonly retrySimulation: (runId: Id<"workRuns">) => Promise<unknown>;
  readonly saveDefinition: (
    workId: Id<"works">,
    payload: unknown
  ) => Promise<unknown>;
  readonly saveDesign: (
    workId: Id<"works">,
    payload: unknown
  ) => Promise<unknown>;
  readonly selectProject: (projectId: string) => void;
  readonly selectedProject: ProjectListItem | null;
  readonly setRepository: (value: string) => void;
  readonly startExecution: (
    workId: Id<"works">,
    sliceId?: string
  ) => Promise<unknown>;
  readonly startSimulation: (
    workId: Id<"works">,
    scenario:
      | "success"
      | "transient-failure-then-success"
      | "needs-input"
      | "permanent-failure"
      | "cancelled",
    sliceId?: string
  ) => Promise<unknown>;
  readonly works: readonly WorkRecord[] | undefined;
}

export type WorkspaceTimelineItem =
  | { readonly kind: "message"; readonly message: ConversationMessage }
  | { readonly kind: "work"; readonly notice: WorkNotice };

export interface ArtifactMetadata {
  readonly changedFiles?: readonly string[];
}

export const parseArtifactMetadata = (
  artifact: WorkArtifact
): ArtifactMetadata => {
  if (!artifact.metadataJson) {
    return {};
  }
  try {
    return JSON.parse(artifact.metadataJson) as ArtifactMetadata;
  } catch {
    return {};
  }
};

export const changedFilesFor = (artifact: WorkArtifact): readonly string[] =>
  parseArtifactMetadata(artifact).changedFiles ?? [];
