"""File-browser + note-index endpoints (sandbox-enforced)."""
import json
import re
import subprocess
import sys
from urllib.parse import parse_qs, urlparse

import constants


class FilesHandlers:
    """Mixin for /api/files, /api/refresh-index."""

    def _resolve_sandboxed(self, path):
        """Resolve `path` against ALLOWED_WORKSPACES. Returns (target, workspace) or (None, None)."""
        allowed_dirs = constants.ALLOWED_WORKSPACES
        for base in allowed_dirs:
            try:
                candidate = (base / path).resolve()
                if any(str(candidate).startswith(str(d)) for d in allowed_dirs):
                    return candidate, base
            except Exception:
                continue
        return None, None

    def handle_files_get(self):
        """List files or get file content."""
        params = parse_qs(urlparse(self.path).query)
        path = params.get('path', [''])[0]
        action = params.get('action', ['list'])[0]

        target, workspace = self._resolve_sandboxed(path)
        if target is None:
            self.send_json({'error': 'Access denied'}, 403)
            return

        if action != 'list':
            self.send_json({'error': 'Unknown action'}, 400)
            return

        if not target.exists():
            self.send_json({'error': 'Path not found'}, 404)
            return

        if target.is_file():
            try:
                content = target.read_text(encoding='utf-8', errors='replace')
                self.send_json({
                    'type': 'file',
                    'path': path,
                    'name': target.name,
                    'content': content[:100000],
                    'size': target.stat().st_size,
                    'truncated': target.stat().st_size > 100000,
                })
            except Exception as e:
                self.send_json({'error': str(e)}, 500)
        else:
            items = []
            try:
                for item in sorted(target.iterdir()):
                    stat = item.stat()
                    item_path = f"{path}/{item.name}" if path else item.name
                    items.append({
                        'name': item.name,
                        'type': 'dir' if item.is_dir() else 'file',
                        'size': stat.st_size if item.is_file() else None,
                        'mtime': stat.st_mtime,
                        'path': item_path,
                    })
                self.send_json({'type': 'dir', 'path': path, 'items': items})
            except Exception as e:
                self.send_json({'error': str(e)}, 500)

    def handle_files_post(self):
        """Save file content."""
        try:
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length).decode('utf-8')
            data = json.loads(post_data)

            path = data.get('path', '')
            content = data.get('content', '')

            target, workspace = self._resolve_sandboxed(path)
            if target is None:
                self.send_json({'error': 'Access denied'}, 403)
                return

            target.parent.mkdir(parents=True, exist_ok=True)
            target.write_text(content, encoding='utf-8')

            self.send_json({'status': 'saved', 'path': path, 'size': len(content)})
        except Exception as e:
            self.send_json({'error': str(e)}, 500)

    def handle_refresh_index(self):
        """Regenerate memory/kb/index.json by running tools/update_notes_index.py."""
        try:
            script = constants.TOOLS_DIR / 'update_notes_index.py'
            result = subprocess.run(
                [sys.executable, str(script)],
                capture_output=True, text=True, timeout=30,
            )
            if result.returncode == 0:
                output = result.stdout
                total_match = re.search(r'with (\d+) notes', output)
                total = int(total_match.group(1)) if total_match else 0
                self.send_json({
                    'success': True,
                    'message': f'Index regenerat cu {total} notițe',
                    'total': total,
                    'output': output,
                })
            else:
                self.send_json({'success': False, 'error': result.stderr or 'Unknown error'}, 500)
        except subprocess.TimeoutExpired:
            self.send_json({'success': False, 'error': 'Timeout'}, 500)
        except Exception as e:
            self.send_json({'success': False, 'error': str(e)}, 500)
