// AGPL-3.0-only
//
// This is free software for the public good of a permacomputer
// hosted at permacomputer.com, an always-on computer by the people, for the
// people. One which is durable, easy to repair, and distributed like tap water
// for machine learning intelligence.
//
// The permacomputer is community-owned infrastructure optimized around
// four values:
//
//   TRUTH    - First principles, math & science, open source code
//   FREEDOM  - Voluntary partnerships, freedom from tyranny & corporate control
//   HARMONY  - Minimal waste, self-renewing systems with diverse connections
//   LOVE     - Be yourself without hurting others, cooperation through natural law
//
// This software contributes to that vision by making machine learning
// accessible to everyone through a free, open, embeddable chat interface.
// Code is seeds to sprout on any abandoned technology.
//
// Learn more: https://www.permacomputer.com
//
// NO WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
//
// Copyright 2025-2026 TimeHexOn & foxhop & russell@unturf
// https://www.permacomputer.com

// Conversation history and localStorage functionality
// Supports automatic AES-256 encryption when vault is unlocked
import { getSystemMessage } from "./config.js";

// Encrypted storage format version
const ENCRYPTED_STORAGE_VERSION = 1;

// Check if vault is available and unlocked (uses window global, no import needed)
function getVault() {
	if (
		typeof window !== "undefined" &&
		window.UncloseVault &&
		window.UncloseVault.isUnlocked()
	) {
		return window.UncloseVault;
	}
	return null;
}

// Parse stored data to determine format (plaintext array vs encrypted wrapper)
function parseStoredData(raw) {
	if (!raw) return { type: "empty", data: null };
	try {
		const parsed = JSON.parse(raw);
		if (
			parsed &&
			typeof parsed === "object" &&
			!Array.isArray(parsed) &&
			parsed._encrypted === true
		) {
			return { type: "encrypted", data: parsed._data, version: parsed._v };
		}
		if (Array.isArray(parsed)) {
			return { type: "plaintext", data: parsed };
		}
		return { type: "unknown", data: null };
	} catch (e) {
		return { type: "corrupted", data: null };
	}
}

// Helper function to generate a page-specific key for localStorage
export function getPageSpecificKey(baseKey) {
	// Use the current page's URL to create a unique key
	// Replace non-alphanumeric characters to make it a valid key
	const pageIdentifier = window.location.href.replace(/[^a-zA-Z0-9]/g, "_");
	return `${baseKey}-${pageIdentifier}`;
}

// Functions for conversation history persistence
export function saveConversationHistory(chatHistory) {
	const historyToSave = chatHistory.filter((msg) => msg.role !== "system");
	const storageKey = getPageSpecificKey("hermes-conversation-history");

	const vault = getVault();
	if (vault) {
		const encrypted = vault.encrypt(historyToSave, vault._password);
		if (encrypted) {
			const wrapper = {
				_encrypted: true,
				_v: ENCRYPTED_STORAGE_VERSION,
				_data: encrypted,
			};
			localStorage.setItem(storageKey, JSON.stringify(wrapper));
			return;
		}
		console.warn("Conversation encryption failed, saving as plaintext");
	}

	// Vault is mandatory — never save plaintext conversations
	console.warn("Vault locked: conversation not saved to localStorage");
}

export function loadConversationHistory() {
	const storageKey = getPageSpecificKey("hermes-conversation-history");
	const raw = localStorage.getItem(storageKey);
	const stored = parseStoredData(raw);

	switch (stored.type) {
		case "empty":
			return [];

		case "plaintext": {
			const history = stored.data.filter((msg) => msg.role !== "system");
			// Auto-migrate to encrypted if vault is unlocked
			const vault = getVault();
			if (vault && history.length > 0) {
				const encrypted = vault.encrypt(history, vault._password);
				if (encrypted) {
					const wrapper = {
						_encrypted: true,
						_v: ENCRYPTED_STORAGE_VERSION,
						_data: encrypted,
					};
					localStorage.setItem(storageKey, JSON.stringify(wrapper));
					console.log("Migrated plaintext conversation to encrypted storage");
				}
			}
			return history;
		}

		case "encrypted": {
			const vault = getVault();
			if (!vault) {
				console.log("Encrypted conversation found but vault is locked");
				return [];
			}
			const decrypted = vault.decrypt(stored.data, vault._password);
			if (decrypted && Array.isArray(decrypted)) {
				return decrypted.filter((msg) => msg.role !== "system");
			}
			console.warn("Failed to decrypt conversation history");
			return [];
		}

		case "unknown":
		case "corrupted":
		default:
			console.error(
				"Corrupted conversation history data, treating as empty",
			);
			return [];
	}
}

// Get just the custom prompt for attention echo (not full system message with page content)
// This is exported so chat.js can add it only to LLM requests, not stored history
export function getCustomPromptEcho() {
	if (typeof window !== "undefined" && window.UNCLOSEAI_SYSTEM_PROMPT) {
		return window.UNCLOSEAI_SYSTEM_PROMPT;
	}
	return null;
}

export async function clearConversationHistory() {
	localStorage.removeItem(getPageSpecificKey("hermes-conversation-history"));
	const systemContent = await getSystemMessage();
	// Echo is NOT added here - it's only added at LLM request time in chat.js
	return [{ role: "system", content: systemContent }];
}

// Initialize chat history
export async function initializeChatHistory() {
	const systemContent = await getSystemMessage();
	// Echo is NOT added here - it's only added at LLM request time in chat.js
	return [
		{ role: "system", content: systemContent },
		...loadConversationHistory(),
	];
}

// Auto-migrate plaintext conversations when vault is unlocked
if (typeof window !== "undefined") {
	window.addEventListener("uncloseai-vault-unlocked", () => {
		const history = loadConversationHistory();
		if (history.length > 0) {
			console.log("Vault unlocked: conversation encryption verified");
		}
	});
}
