import json
from pathlib import Path
from runtime.memory.vector_store import VectorStore

class PeopleMemory:
    def __init__(self, vector_store: VectorStore, data_dir: Path):
        self.vector_store = vector_store
        self.data_dir = data_dir
        self.namespace = 'people'

    def remember_person(self, name: str, role: str = '', notes: str = '') -> str:
        return self.vector_store.add(
            content=notes,
            metadata={'type': 'person', 'name': name, 'role': role},
            namespace=self.namespace
        )

    def update_person(self, name: str, notes: str) -> str:
        res = self.vector_store.search_by_metadata({'type': 'person', 'name': name}, namespace=self.namespace, limit=1)
        if res:
            r = res[0]
            new_content = r['content'] + "\n" + notes
            self.vector_store.update(r['id'], content=new_content)
            return r['id']
        else:
            return self.remember_person(name, notes=notes)

    def get_person(self, name: str) -> dict | None:
        res = self.vector_store.search_by_metadata({'type': 'person', 'name': name}, namespace=self.namespace, limit=1)
        if not res:
            return None
        r = res[0]
        prefs = self.get_preferences(name)
        exp = self.get_expertise(name)
        return {
            'name': name,
            'role': r['metadata'].get('role', ''),
            'notes': r['content'],
            'preferences': [p['preference'] for p in prefs],
            'expertise': [e['expertise'] for e in exp],
            'created_at': r['created_at']
        }

    def remember_preference(self, person_name: str, preference: str, category: str = 'general') -> str:
        return self.vector_store.add(
            content=preference,
            metadata={'type': 'preference', 'person': person_name, 'category': category},
            namespace=self.namespace
        )

    def get_preferences(self, person_name: str) -> list[dict]:
        res = self.vector_store.search_by_metadata({'type': 'preference', 'person': person_name}, namespace=self.namespace, limit=100)
        return [{'id': r['id'], 'preference': r['content'], 'category': r['metadata'].get('category'), 'created_at': r['created_at']} for r in res]

    def remember_expertise(self, person_name: str, expertise: str, level: str = 'intermediate') -> str:
        return self.vector_store.add(
            content=expertise,
            metadata={'type': 'expertise', 'person': person_name, 'level': level},
            namespace=self.namespace
        )

    def get_expertise(self, person_name: str) -> list[dict]:
        res = self.vector_store.search_by_metadata({'type': 'expertise', 'person': person_name}, namespace=self.namespace, limit=100)
        return [{'id': r['id'], 'expertise': r['content'], 'level': r['metadata'].get('level'), 'created_at': r['created_at']} for r in res]

    def track_interaction(self, person_name: str, summary: str, models_used: list[str] | None = None) -> str:
        return self.vector_store.add(
            content=summary,
            metadata={'type': 'interaction', 'person': person_name, 'models_used': models_used or []},
            namespace=self.namespace
        )

    def get_interaction_history(self, person_name: str, limit: int = 10) -> list[dict]:
        res = self.vector_store.search_by_metadata({'type': 'interaction', 'person': person_name}, namespace=self.namespace, limit=limit)
        res.sort(key=lambda x: x['created_at'], reverse=True)
        return [{'id': r['id'], 'summary': r['content'], 'models_used': r['metadata'].get('models_used'), 'created_at': r['created_at']} for r in res[:limit]]

    def list_people(self) -> list[dict]:
        c = self.vector_store.conn.cursor()
        c.execute("SELECT metadata, created_at FROM vectors WHERE namespace = ?", (self.namespace,))
        people = {}
        for row in c.fetchall():
            meta = json.loads(row['metadata'] or '{}')
            name = meta.get('name') or meta.get('person')
            if not name:
                continue
            if name not in people:
                people[name] = {'name': name, 'role': '', 'interaction_count': 0, 'last_interaction': row['created_at']}
            if meta.get('type') == 'person':
                people[name]['role'] = meta.get('role', '')
            if meta.get('type') == 'interaction':
                people[name]['interaction_count'] += 1
                people[name]['last_interaction'] = max(people[name]['last_interaction'], row['created_at'])
        return list(people.values())

    def forget_person(self, name: str) -> int:
        res = self.vector_store.search_by_metadata({'person': name}, namespace=self.namespace, limit=1000)
        res += self.vector_store.search_by_metadata({'name': name}, namespace=self.namespace, limit=1000)
        ids = list(set([r['id'] for r in res]))
        if ids:
            self.vector_store.batch_delete(ids)
        return len(ids)

    def context_for_prompt(self, person_name: str) -> str:
        p = self.get_person(person_name)
        if not p:
            return ""
        context = f"[Known about {person_name}]\nRole: {p['role']}\nNotes: {p['notes']}\n"
        if p['preferences']:
            context += "Preferences: " + ", ".join(p['preferences']) + "\n"
        if p['expertise']:
            context += "Expertise: " + ", ".join(p['expertise']) + "\n"
        interactions = self.get_interaction_history(person_name, limit=3)
        if interactions:
            context += "Recent interactions:\n"
            for i in interactions:
                context += f"- {i['summary']}\n"
        context += f"[End person context]\n"
        return context

    def search_people(self, query: str, top_k: int = 5) -> list[dict]:
        res = self.vector_store.search(query, top_k=top_k, namespace=self.namespace)
        return [{'person_name': r['metadata'].get('name') or r['metadata'].get('person'), 'type': r['metadata'].get('type'), 'content': r['content'], 'score': r['score']} for r in res]

    def export_people(self) -> dict:
        people = self.list_people()
        data = {}
        for p in people:
            name = p['name']
            full = self.get_person(name)
            if full:
                data[name] = {
                    'role': full['role'],
                    'notes': full['notes'],
                    'preferences': full['preferences'],
                    'expertise': full['expertise'],
                    'interaction_count': p['interaction_count']
                }
        return data
