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

export interface Memory {
  id: string;
  text: string;
  category: string;
  timestamp: number;
  source: "auto" | "manual";
  importance: number; // 1-5
}

const CATEGORIES = ["preference", "fact", "project", "person", "skill", "context", "custom"] as const;

@customElement("memory-manager")
export class MemoryManager extends LitElement {
  @state() private _memories: Memory[] = [];
  @state() private _filter = "";
  @state() private _catFilter = "all";
  @state() private _editing: string | null = null;
  @state() private _visible = false;
  @property({ type: Boolean }) open = false;

  protected override createRenderRoot() { return this; }

  override connectedCallback() {
    super.connectedCallback();
    this._load();
  }

  private _load() {
    try {
      const raw = localStorage.getItem("jae-memories");
      if (raw) this._memories = JSON.parse(raw);
    } catch {}
  }

  private _save() {
    localStorage.setItem("jae-memories", JSON.stringify(this._memories));
  }

  // === AUTO-LEARNING: Extract facts from messages ===
  autoLearn(userMsg: string, assistantMsg: string) {
    const facts = this._extractFacts(userMsg, assistantMsg);
    for (const fact of facts) {
      // Don't duplicate
      const exists = this._memories.some(m =>
        m.text.toLowerCase().includes(fact.text.toLowerCase().slice(0, 30))
      );
      if (!exists) {
        this._memories.push(fact);
      }
    }
    this._save();
  }

  private _extractFacts(user: string, assistant: string): Memory[] {
    const facts: Memory[] = [];
    const now = Date.now();

    // Preference patterns
    const prefPatterns = [
      /(?:i (?:prefer|like|love|hate|use|want|need|always))\s+(.{5,80})/gi,
      /(?:my (?:favourite|favorite|preferred))\s+(?:\w+\s+)?(?:is|are)\s+(.{3,60})/gi,
      /(?:i(?:'m| am) (?:using|running|on))\s+(.{3,60})/gi,
    ];
    for (const pat of prefPatterns) {
      let m;
      while ((m = pat.exec(user)) !== null) {
        facts.push({
          id: crypto.randomUUID(),
          text: m[0].trim(),
          category: "preference",
          timestamp: now,
          source: "auto",
          importance: 2,
        });
      }
    }

    // Name / identity patterns
    const namePatterns = [
      /(?:my name is|i(?:'m| am) called|call me)\s+(\w[\w\s]{1,30})/gi,
      /(?:i work (?:at|for|on))\s+(.{3,60})/gi,
      /(?:my (?:email|address|phone|website) is)\s+(.{3,80})/gi,
    ];
    for (const pat of namePatterns) {
      let m;
      while ((m = pat.exec(user)) !== null) {
        facts.push({
          id: crypto.randomUUID(),
          text: m[0].trim(),
          category: "person",
          timestamp: now,
          source: "auto",
          importance: 3,
        });
      }
    }

    // Project patterns
    const projPatterns = [
      /(?:(?:the|my|our) project (?:is called|named|is))\s+(.{3,60})/gi,
      /(?:i(?:'m| am) (?:building|developing|creating|working on))\s+(.{3,80})/gi,
    ];
    for (const pat of projPatterns) {
      let m;
      while ((m = pat.exec(user)) !== null) {
        facts.push({
          id: crypto.randomUUID(),
          text: m[0].trim(),
          category: "project",
          timestamp: now,
          source: "auto",
          importance: 3,
        });
      }
    }

    return facts;
  }

  // === Get context for system prompt ===
  getContext(): string {
    if (this._memories.length === 0) return "";
    const sorted = [...this._memories].sort((a, b) => b.importance - a.importance);
    const lines = sorted.slice(0, 20).map(m => `- [${m.category}] ${m.text}`);
    return `\n\nUser memories (auto-learned):\n${lines.join("\n")}`;
  }

  addManual(text: string, category: string = "custom") {
    this._memories.push({
      id: crypto.randomUUID(),
      text,
      category,
      timestamp: Date.now(),
      source: "manual",
      importance: 3,
    });
    this._save();
    this.requestUpdate();
  }

  private _delete(id: string) {
    this._memories = this._memories.filter(m => m.id !== id);
    this._save();
    this.requestUpdate();
  }

  private _setImportance(id: string, val: number) {
    const m = this._memories.find(x => x.id === id);
    if (m) { m.importance = val; this._save(); this.requestUpdate(); }
  }

  show() { this._visible = true; this.requestUpdate(); }
  hide() { this._visible = false; this.requestUpdate(); }
  toggle() { this._visible = !this._visible; this.requestUpdate(); }

  get memoryCount() { return this._memories.length; }

  override render() {
    if (!this._visible) return html``;
    const filtered = this._memories.filter(m => {
      if (this._catFilter !== "all" && m.category !== this._catFilter) return false;
      if (this._filter && !m.text.toLowerCase().includes(this._filter.toLowerCase())) return false;
      return true;
    }).sort((a, b) => b.timestamp - a.timestamp);

    return html`
    <div class="glass-panel fixed inset-0 z-[200] flex items-center justify-center bg-black/50 backdrop-blur-sm animate-fade-in" @click=${(e: Event) => { if (e.target === e.currentTarget) this.hide(); }}>
      <div class="glass-card w-[600px] max-h-[70vh] flex flex-col rounded-2xl overflow-hidden shadow-2xl" @click=${(e: Event) => e.stopPropagation()}>
        <div class="flex items-center justify-between p-4 border-b border-white/10">
          <div class="flex items-center gap-2">
            <span class="text-lg">\u{1F9E0}</span>
            <span class="text-sm font-semibold text-foreground">Memory Bank</span>
            <span class="text-[10px] px-1.5 py-0.5 rounded-full bg-primary/20 text-primary">${this._memories.length} memories</span>
          </div>
          <button @click=${() => this.hide()} class="w-7 h-7 flex items-center justify-center rounded-lg hover:bg-white/10 text-muted-foreground transition-all">\u2715</button>
        </div>
        <div class="flex items-center gap-2 p-3 border-b border-white/5">
          <input type="text" placeholder="Search memories..." .value=${this._filter}
            @input=${(e: InputEvent) => { this._filter = (e.target as HTMLInputElement).value; this.requestUpdate(); }}
            class="flex-1 px-3 py-1.5 text-xs bg-white/5 border border-white/10 rounded-lg text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-primary/50" />
          <select @change=${(e: Event) => { this._catFilter = (e.target as HTMLSelectElement).value; this.requestUpdate(); }}
            class="px-2 py-1.5 text-xs bg-white/5 border border-white/10 rounded-lg text-foreground">
            <option value="all">All</option>
            ${CATEGORIES.map(c => html`<option value=${c}>${c}</option>`)}
          </select>
        </div>
        <div class="flex-1 overflow-y-auto p-3 space-y-2">
          ${filtered.length === 0 ? html`<div class="text-center text-xs text-muted-foreground/50 py-8">No memories yet. Chat with JAE to build your memory bank!</div>` : ""}
          ${filtered.map(m => html`
            <div class="group flex items-start gap-3 p-3 rounded-xl bg-white/[0.03] hover:bg-white/[0.06] border border-white/5 transition-all duration-200">
              <div class="flex flex-col items-center gap-1 shrink-0">
                <span class="text-[10px] px-1.5 py-0.5 rounded bg-primary/15 text-primary/80">${m.category}</span>
                <span class="text-[9px] text-muted-foreground/40">${m.source === "auto" ? "\u{1F916}" : "\u{270D}\uFE0F"}</span>
              </div>
              <div class="flex-1 min-w-0">
                <div class="text-xs text-foreground/90">${m.text}</div>
                <div class="text-[9px] text-muted-foreground/40 mt-1">${new Date(m.timestamp).toLocaleDateString()}</div>
              </div>
              <div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0">
                <select .value=${String(m.importance)} @change=${(e: Event) => this._setImportance(m.id, Number((e.target as HTMLSelectElement).value))}
                  class="text-[10px] bg-transparent border border-white/10 rounded px-1 py-0.5 text-foreground" title="Importance">
                  ${[1,2,3,4,5].map(n => html`<option value=${n} ?selected=${m.importance === n}>${"\u2B50".repeat(n)}</option>`)}
                </select>
                <button @click=${() => this._delete(m.id)} class="w-5 h-5 flex items-center justify-center rounded hover:bg-red-500/20 text-red-400 text-[10px] transition-colors">\u2715</button>
              </div>
            </div>
          `)}
        </div>
        <div class="p-3 border-t border-white/10">
          <div class="flex gap-2">
            <input id="jae-mem-input" type="text" placeholder="Add a memory manually..." 
              class="flex-1 px-3 py-1.5 text-xs bg-white/5 border border-white/10 rounded-lg text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-primary/50"
              @keydown=${(e: KeyboardEvent) => { if (e.key === "Enter") { const inp = e.target as HTMLInputElement; if (inp.value.trim()) { this.addManual(inp.value.trim()); inp.value = ""; } } }} />
            <button @click=${() => { const inp = this.querySelector("#jae-mem-input") as HTMLInputElement; if (inp?.value.trim()) { this.addManual(inp.value.trim()); inp.value = ""; } }}
              class="px-3 py-1.5 text-xs bg-primary/20 text-primary rounded-lg hover:bg-primary/30 transition-colors">Add</button>
          </div>
        </div>
      </div>
    </div>`;
  }
}
