import os
import json
import hashlib
from datetime import datetime
from .repo_utils import EXCLUDE_DIRS

class SyncManager:
    """
    Manages local file hashes to track manual changes and maintain synchronization state.
    """
    def __init__(self):
        self.config_dir = os.path.expanduser("~/.codedthemes")
        self.config_file = os.path.join(self.config_dir, "workspace.json")
        os.makedirs(self.config_dir, exist_ok=True)
        self.workspaces = self.load()
        
    def load(self):
        """
        Loads the workspace synchronization state from the cloud config.
        """
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as f: return json.load(f)
            except: pass
        return {}
        
    def save(self):
        """
        Saves the workspace synchronization state locally.
        """
        with open(self.config_file, 'w') as f:
            json.dump(self.workspaces, f, indent=2)

    def compute_hashes(self, repo_path):
        """
        Computes MD5 hashes for all relevant files in the repository.
        """
        hashes = {}
        for root, dirs, files in os.walk(repo_path):
            dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS]
            for file in files:
                abs_path = os.path.join(root, file)
                try:
                    hasher = hashlib.md5()
                    with open(abs_path, 'rb') as f:
                        while chunk := f.read(8192): hasher.update(chunk)
                    hashes[os.path.relpath(abs_path, repo_path)] = hasher.hexdigest()
                except Exception:
                    pass
        return hashes

    def update_sync_state(self, repo_path, workspace_id, user_id):
        """
        Updates the synchronization state with the latest file hashes.
        """
        repo_key = f"{user_id}:{os.path.abspath(repo_path)}"
        self.workspaces[repo_key] = {
            "workspace_id": workspace_id,
            "repo_path": os.path.abspath(repo_path),
            "last_sync": datetime.utcnow().isoformat(),
            "file_hashes": self.compute_hashes(repo_path)
        }
        self.save()

    def get_changed_files(self, repo_path, user_id):
        """
        Identifies files that have been modified or deleted locally since the last sync.
        """
        repo_key = f"{user_id}:{os.path.abspath(repo_path)}"
        if repo_key not in self.workspaces: return []
        
        current_hashes = self.compute_hashes(repo_path)
        last_hashes = self.workspaces[repo_key].get("file_hashes", {})
        changes = []
        
        for rel_path, fhash in current_hashes.items():
            if rel_path not in last_hashes or last_hashes[rel_path] != fhash:
                try:
                    with open(os.path.join(repo_path, rel_path), 'r', encoding='utf-8', errors='ignore') as f:
                        changes.append({"path": rel_path, "content": f.read()})
                except Exception:
                    pass
                    
        for rel_path in last_hashes:
            if rel_path not in current_hashes:
                changes.append({"path": rel_path, "deleted": True})
                
        return changes
