import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";

export interface MemoryEntry {
	id: string;
	content: string;
	tags: string[];
	timestamp: string;
}

const DB_NAME = "jae-memory";
const DB_VERSION = 1;
const STORE_NAME = "memories";
let _db: IDBDatabase | null = null;

async function openDB(): Promise<IDBDatabase> {
	if (_db) return _db;
	return new Promise((resolve, reject) => {
		const req = indexedDB.open(DB_NAME, DB_VERSION);
		req.onupgradeneeded = () => req.result.createObjectStore(STORE_NAME, { keyPath: "id" });
		req.onsuccess = () => {
			_db = req.result;
			resolve(_db);
		};
		req.onerror = () => reject(req.error);
	});
}
export async function memoryLoad(): Promise<MemoryEntry[]> {
	const db = await openDB();
	return new Promise((resolve, reject) => {
		const tx = db.transaction(STORE_NAME, "readonly");
		const req = tx.objectStore(STORE_NAME).getAll();
		req.onsuccess = () => resolve(req.result || []);
		req.onerror = () => reject(req.error);
	});
}
export async function memorySave(content: string, tags: string[] = []): Promise<string> {
	const db = await openDB();
	const entry: MemoryEntry = { id: crypto.randomUUID(), content, tags, timestamp: new Date().toISOString() };
	return new Promise((resolve, reject) => {
		const tx = db.transaction(STORE_NAME, "readwrite");
		tx.objectStore(STORE_NAME).put(entry);
		tx.oncomplete = () => resolve(entry.id);
		tx.onerror = () => reject(tx.error);
	});
}
export async function memoryDelete(id: string): Promise<void> {
	const db = await openDB();
	return new Promise((resolve, reject) => {
		const tx = db.transaction(STORE_NAME, "readwrite");
		tx.objectStore(STORE_NAME).delete(id);
		tx.oncomplete = () => resolve();
		tx.onerror = () => reject(tx.error);
	});
}

@customElement("memory-manager")
export class MemoryManager extends LitElement {
	@state() private open = false;
	@state() private entries: MemoryEntry[] = [];
	@state() private loading = false;
	@state() private newContent = "";
	@state() private newTags = "";
	@state() private filter = "";

	protected override createRenderRoot() {
		return this;
	}

	async show() {
		this.open = true;
		this.loading = true;
		this.requestUpdate();
		this.entries = await memoryLoad();
		this.loading = false;
		this.requestUpdate();
	}
	hide() {
		this.open = false;
		this.requestUpdate();
	}

	get filtered() {
		if (!this.filter) return this.entries;
		const q = this.filter.toLowerCase();
		return this.entries.filter(
			(e) => e.content.toLowerCase().includes(q) || e.tags.some((t) => t.toLowerCase().includes(q)),
		);
	}

	async deleteEntry(id: string) {
		await memoryDelete(id);
		this.entries = this.entries.filter((e) => e.id !== id);
		this.requestUpdate();
	}

	async addEntry() {
		if (!this.newContent.trim()) return;
		const tags = this.newTags
			.split(",")
			.map((t) => t.trim())
			.filter(Boolean);
		await memorySave(this.newContent.trim(), tags);
		this.newContent = "";
		this.newTags = "";
		this.entries = await memoryLoad();
		this.requestUpdate();
	}

	override render() {
		if (!this.open) return html``;
		const entries = this.filtered;
		return html`
      <div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50" @click=${(e: Event) => {
			if (e.target === e.currentTarget) this.hide();
		}}>
        <div class="bg-popover text-foreground border border-border rounded-xl shadow-2xl w-full max-w-2xl mx-4 flex flex-col max-h-[80vh]">
          <div class="flex items-center justify-between px-6 py-4 border-b border-border shrink-0">
            <h2 class="font-semibold text-lg">&#x1F9E0; Memory Manager</h2>
            <button class="text-muted-foreground hover:text-foreground" @click=${() => this.hide()}>&#x2715;</button>
          </div>
          <div class="px-6 py-3 border-b border-border shrink-0">
            <input type="text" placeholder="Filter memories..." class="w-full bg-secondary text-foreground rounded-lg px-3 py-2 text-sm outline-none"
              .value=${this.filter} @input=${(e: Event) => {
						this.filter = (e.target as HTMLInputElement).value;
					}} />
          </div>
          <div class="flex-1 overflow-y-auto px-6 py-4">
            ${this.loading ? html`<div class="text-center text-muted-foreground py-8">Loading...</div>` : ""}
            ${!this.loading && entries.length === 0 ? html`<div class="text-center text-muted-foreground py-8">No memories stored yet</div>` : ""}
            <div class="flex flex-col gap-2">
              ${entries.map(
						(entry) => html`
                <div class="flex gap-3 p-3 rounded-lg border border-border bg-background group">
                  <div class="flex-1 min-w-0">
                    <div class="text-sm">${entry.content}</div>
                    <div class="flex items-center gap-2 mt-1">
                      <span class="text-xs text-muted-foreground">${entry.timestamp.slice(0, 10)}</span>
                      ${entry.tags.map((tag) => html`<span class="text-xs bg-secondary px-1.5 py-0.5 rounded">${tag}</span>`)}
                    </div>
                  </div>
                  <button class="shrink-0 text-muted-foreground hover:text-destructive opacity-0 group-hover:opacity-100 transition-opacity"
                    @click=${() => this.deleteEntry(entry.id)} title="Delete">&#x1F5D1;</button>
                </div>
              `,
					)}
            </div>
          </div>
          <div class="px-6 py-4 border-t border-border shrink-0">
            <div class="flex flex-col gap-2">
              <textarea placeholder="New memory content..." class="w-full bg-secondary rounded-lg px-3 py-2 text-sm outline-none resize-none"
                rows="2" .value=${this.newContent}
                @input=${(e: Event) => {
							this.newContent = (e.target as HTMLTextAreaElement).value;
						}}></textarea>
              <div class="flex gap-2">
                <input type="text" placeholder="Tags (comma separated)" class="flex-1 bg-secondary rounded-lg px-3 py-2 text-sm outline-none"
                  .value=${this.newTags} @input=${(e: Event) => {
							this.newTags = (e.target as HTMLInputElement).value;
						}} />
                <button class="bg-primary text-primary-foreground px-4 py-2 rounded-lg text-sm font-medium hover:opacity-90"
                  @click=${() => this.addEntry()}>Save</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    `;
	}
}
