/**
 * MI Content Triage — orchestrates content analysis and shape creation.
 *
 * Sends raw pasted/dropped content to `/api/mi/triage`, stores the proposal,
 * and commits approved shapes via MiActionExecutor.
 */

import type { MiAction } from "./mi-actions";
import { MiActionExecutor } from "./mi-action-executor";

export interface TriageProposedShape {
	tagName: string;
	label: string;
	props: Record<string, any>;
	snippet: string;
}

export interface TriageConnection {
	fromIndex: number;
	toIndex: number;
	reason: string;
}

export interface TriageProposal {
	summary: string;
	shapes: TriageProposedShape[];
	connections: TriageConnection[];
}

export type TriageStatus = "idle" | "analyzing" | "ready" | "error";

/** Extract URLs from raw text. */
function extractUrls(text: string): string[] {
	const urlPattern = /https?:\/\/[^\s<>"{}|\\^`\[\]]+/g;
	return [...new Set(text.match(urlPattern) || [])];
}

export class TriageManager {
	proposal: TriageProposal | null = null;
	status: TriageStatus = "idle";
	error: string | null = null;

	private onChange: (() => void) | null = null;

	constructor(onChange?: () => void) {
		this.onChange = onChange || null;
	}

	private notify() {
		this.onChange?.();
	}

	async analyze(raw: string, type: "paste" | "drop" = "paste"): Promise<void> {
		if (!raw.trim()) {
			this.status = "error";
			this.error = "No content to analyze";
			this.notify();
			return;
		}

		this.status = "analyzing";
		this.error = null;
		this.proposal = null;
		this.notify();

		try {
			const res = await fetch("/api/mi/triage", {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ content: raw.slice(0, 50000), contentType: type }),
			});

			if (!res.ok) {
				const err = await res.json().catch(() => ({ error: "Request failed" }));
				throw new Error(err.error || `HTTP ${res.status}`);
			}

			const data = await res.json();
			this.proposal = {
				summary: data.summary || "Content analyzed",
				shapes: Array.isArray(data.shapes) ? data.shapes : [],
				connections: Array.isArray(data.connections) ? data.connections : [],
			};
			this.status = this.proposal.shapes.length > 0 ? "ready" : "error";
			if (this.proposal.shapes.length === 0) {
				this.error = "No shapes identified in content";
			}
		} catch (e: any) {
			this.status = "error";
			this.error = e.message || "Analysis failed";
			this.proposal = null;
		}

		this.notify();
	}

	removeShape(index: number): void {
		if (!this.proposal) return;
		this.proposal.shapes.splice(index, 1);
		// Reindex connections — remove any referencing deleted index, adjust higher indices
		this.proposal.connections = this.proposal.connections
			.filter((c) => c.fromIndex !== index && c.toIndex !== index)
			.map((c) => ({
				...c,
				fromIndex: c.fromIndex > index ? c.fromIndex - 1 : c.fromIndex,
				toIndex: c.toIndex > index ? c.toIndex - 1 : c.toIndex,
			}));
		this.notify();
	}

	commitAll(): void {
		if (!this.proposal || this.proposal.shapes.length === 0) return;

		const actions: MiAction[] = [];

		// Create shapes with $N refs
		for (let i = 0; i < this.proposal.shapes.length; i++) {
			const shape = this.proposal.shapes[i];
			actions.push({
				type: "create-shape",
				tagName: shape.tagName,
				props: { ...shape.props },
				ref: `$${i + 1}`,
			});
		}

		// Create connections
		for (const conn of this.proposal.connections) {
			actions.push({
				type: "connect",
				sourceId: `$${conn.fromIndex + 1}`,
				targetId: `$${conn.toIndex + 1}`,
			});
		}

		const executor = new MiActionExecutor();
		executor.execute(actions);

		this.status = "idle";
		this.proposal = null;
	}
}
