import { truncateToWidth, visibleWidth } from "@singularity-forge/tui";
import { getAutoSession } from "../auto/session.js";
import { refreshGitStatus } from "./git.js";
import { renderModeBadge } from "./header.js";

const RESET = "\x1b[0m";
const BOLD = "\x1b[1m";
const SE = {
	ember40: "#ff8838",
	gray60: "#8d877a",
	stone60: "#6b6659",
	paper: "#f7f5f1",
	warning: "#ff8838",
	success: "#24a148",
	error: "#da1e28",
};
function hexToRgb(hex) {
	const cleaned = hex.replace("#", "");
	return {
		r: parseInt(cleaned.slice(0, 2), 16),
		g: parseInt(cleaned.slice(2, 4), 16),
		b: parseInt(cleaned.slice(4, 6), 16),
	};
}
function ansiFg(hex, text, bold = false) {
	// Use 16-color ANSI codes for Termius compatibility
	// Map hex colors to nearest standard ANSI color
	const { r, g, b } = hexToRgb(hex);
	const brightness = (r + g + b) / 3;
	let colorCode;
	if (brightness < 50) {
		colorCode = 30; // black
	} else if (brightness < 100) {
		colorCode = 90; // bright black
	} else if (r > g + b) {
		colorCode = bold ? 91 : 31; // red
	} else if (g > r + b) {
		colorCode = bold ? 92 : 32; // green
	} else if (b > r + g) {
		colorCode = bold ? 94 : 34; // blue
	} else if (r > 200 && g > 150) {
		colorCode = bold ? 93 : 33; // yellow/orange
	} else if (r > 200 && g < 100 && b > 150) {
		colorCode = bold ? 95 : 35; // magenta
	} else if (g > 200 && b > 150) {
		colorCode = bold ? 96 : 36; // cyan
	} else if (brightness > 200) {
		colorCode = bold ? 97 : 37; // white
	} else {
		colorCode = bold ? 97 : 37; // default white
	}
	return `\x1b[${bold ? "1;" : ""}${colorCode}m${text}${RESET}`;
}
function toneHex(tone) {
	switch (tone) {
		case "accent":
		case "warning":
			return SE.ember40;
		case "success":
			return SE.success;
		case "error":
			return SE.error;
		case "text":
			return SE.paper;
		default:
			return SE.gray60;
	}
}
function chip(label, value, tone = "text") {
	return `${ansiFg(SE.gray60, `${label} `)}${ansiFg(toneHex(tone), value)}`;
}
function join(parts) {
	return parts.filter(Boolean).join(ansiFg(SE.stone60, " | "));
}
function shorten(text, max) {
	return text.length > max ? `${text.slice(0, Math.max(0, max - 3))}...` : text;
}

/** Minimal theme adapter so renderModeBadge (header.js) can run with footer's ANSI helpers. */
const FOOTER_THEME = {
	fg: (tone, text) => ansiFg(toneHex(tone), text),
	bold: (text) => `${BOLD}${text}${RESET}`,
};
function getSessionStats(ctx) {
	let cost = 0;
	let tokens = 0;
	let cxPct = 0;
	try {
		for (const entry of ctx.sessionManager.getEntries()) {
			if (entry.type === "message") {
				const msg = entry.message;
				if (msg?.role === "assistant" && msg.usage) {
					cost += msg.usage.cost?.total || 0;
					tokens += (msg.usage.input || 0) + (msg.usage.output || 0);
				}
			}
		}
		const cx = ctx.getContextUsage?.();
		if (cx?.percent != null) cxPct = cx.percent;
	} catch {
		/* ignore */
	}
	return { cost, tokens, cxPct };
}
export function renderFooter(_theme, footerData, ctx, width) {
	const git = refreshGitStatus(process.cwd());
	const { cost, tokens, cxPct } = getSessionStats(ctx);
	const session = getAutoSession();
	const mode = session?.getMode?.();
	const leftParts = [];
	if (git.repo) {
		leftParts.push(ansiFg(SE.ember40, git.repo, true));
	} else {
		leftParts.push(`${BOLD}${ansiFg(SE.ember40, "SF")}`);
	}
	if (git.branch) {
		leftParts.push(chip("branch", git.branch, "muted"));
		const state = git.dirty ? "dirty" : git.untracked ? "new" : "clean";
		leftParts.push(
			chip("state", state, state === "clean" ? "success" : "warning"),
		);
		if (git.added || git.deleted) {
			leftParts.push(chip("diff", `+${git.added}/-${git.deleted}`, "warning"));
		}
		if (git.ahead || git.behind) {
			const syncParts = [];
			if (git.ahead) syncParts.push(`↑${git.ahead}`);
			if (git.behind) syncParts.push(`↓${git.behind}`);
			leftParts.push(chip("sync", syncParts.join(" "), "warning"));
		}
		if (git.lastCommit) {
			leftParts.push(
				chip(
					"last",
					`${git.lastCommit.timeAgo} ${shorten(git.lastCommit.message, 26)}`,
					"muted",
				),
			);
		}
	}
	const statuses = Array.from(footerData.getExtensionStatuses().entries())
		.sort(([a], [b]) => a.localeCompare(b))
		.map(([, text]) => String(text ?? "").trim())
		.filter(Boolean);
	if (statuses.length) {
		leftParts.push(chip("status", statuses.join(" "), "accent"));
	}
	const rightParts = [];
	if (mode) {
		rightParts.push(renderModeBadge(FOOTER_THEME, mode, width < 80));
	}
	if (ctx.model) {
		rightParts.push(
			chip("model", `${ctx.model.provider}/${ctx.model.id}`, "text"),
		);
	}
	if (cost > 0) {
		rightParts.push(chip("spent", `$${cost.toFixed(2)}`, "warning"));
	}
	// Only show ctx% once the session has sent at least one message (avoid "1%" noise from system prompt at startup)
	if (tokens > 0) {
		const cxTone = cxPct >= 85 ? "error" : cxPct >= 60 ? "warning" : "success";
		rightParts.push(chip("ctx", `${Math.round(cxPct)}%`, cxTone));
	}
	let rightLine = join(rightParts);
	const maxRightWidth = Math.max(16, Math.floor(width * 0.55));
	if (visibleWidth(rightLine) > maxRightWidth) {
		rightLine = truncateToWidth(
			rightLine,
			maxRightWidth,
			ansiFg(SE.gray60, "..."),
		);
	}
	const rightWidth = visibleWidth(rightLine);
	const leftBudget = Math.max(1, width - rightWidth - 2);
	const leftLine = truncateToWidth(
		join(leftParts),
		leftBudget,
		ansiFg(SE.gray60, "..."),
	);
	const gap = Math.max(1, width - visibleWidth(leftLine) - rightWidth);
	const line = leftLine + " ".repeat(gap) + rightLine;
	return [truncateToWidth(line, width, ansiFg(SE.gray60, "..."))];
}

/**
 * Minimal auto-mode footer — shows only mode badge + progress hint.
 * Keeps the user aware SF is running autonomously without full footer noise.
 */
export function renderAutoFooter(_theme, footerData, ctx, width) {
	const session = getAutoSession();
	const mode = session?.getMode?.() ?? {
		workMode: "build",
		runControl: "autonomous",
		permissionProfile: "normal",
		modelMode: "smart",
	};

	const badge = renderModeBadge(FOOTER_THEME, mode, width < 80);
	const leftParts = [`${BOLD}${ansiFg(SE.ember40, "SF")}`, badge].filter(
		Boolean,
	);

	const statuses = Array.from(footerData.getExtensionStatuses().entries())
		.sort(([a], [b]) => a.localeCompare(b))
		.map(([, text]) => String(text ?? "").trim())
		.filter(Boolean);
	if (statuses.length) {
		leftParts.push(ansiFg(SE.gray60, statuses.join(" ")));
	}

	const rightParts = [];
	if (ctx.model) {
		rightParts.push(ansiFg(SE.gray60, `${ctx.model.provider}/${ctx.model.id}`));
	}
	const { cost } = getSessionStats(ctx);
	if (cost > 0) {
		rightParts.push(ansiFg(SE.warning, `$${cost.toFixed(2)}`));
	}

	const leftLine = leftParts.join(" ");
	const rightLine = rightParts.join(ansiFg(SE.gray60, " · "));
	const rightWidth = visibleWidth(rightLine);
	const gap = Math.max(1, width - visibleWidth(leftLine) - rightWidth);
	const line = leftLine + " ".repeat(gap) + rightLine;
	return [truncateToWidth(line, width, ansiFg(SE.gray60, "..."))];
}
