""" Client management API. Clients group sheets and have their own dropdown (category/media) hierarchy. """ import json import logging import os import random import time from datetime import datetime, timezone from quart import Blueprint, jsonify, request from ..auth.middleware import auth_required, admin_required from ..config_runtime import server_config logger = logging.getLogger(__name__) clients_bp = Blueprint('clients', __name__, url_prefix='/api/clients') def load_clients() -> list: path = server_config.CLIENTS_FILE if not os.path.exists(path): return [] try: with open(path, 'r') as f: return json.load(f) except Exception: return [] def _save_clients(clients: list): with open(server_config.CLIENTS_FILE, 'w') as f: json.dump(clients, f, indent=2) def get_client_by_id(client_id: str) -> dict | None: for c in load_clients(): if c['id'] == client_id: return c return None @clients_bp.route('', methods=['GET']) @auth_required async def list_clients(): return jsonify({'clients': load_clients()}) @clients_bp.route('', methods=['POST']) @admin_required async def create_client(): body = await request.get_json() or {} name = body.get('name', '').strip() if not name: return jsonify({'error': 'name_required', 'message': 'Client name is required'}), 400 client_id = f"client_{int(time.time())}{random.randint(100, 999)}" client = { 'id': client_id, 'name': name, 'created': datetime.now(timezone.utc).isoformat(), 'hasCustomDropdowns': False, } clients = load_clients() clients.append(client) _save_clients(clients) return jsonify({'client': client}), 201 @clients_bp.route('/', methods=['DELETE']) @admin_required async def delete_client(client_id: str): clients = load_clients() clients = [c for c in clients if c['id'] != client_id] _save_clients(clients) # Remove client-specific dropdown file if present dropdown_path = os.path.join(server_config.CLIENTS_DROPDOWNS_DIR, f"{client_id}.json") if os.path.exists(dropdown_path): os.remove(dropdown_path) return jsonify({'success': True}) @clients_bp.route('/', methods=['PATCH']) @admin_required async def update_client(client_id: str): body = await request.get_json() or {} clients = load_clients() updated = None for c in clients: if c['id'] == client_id: if 'name' in body: c['name'] = body['name'].strip() updated = c break if not updated: return jsonify({'error': 'not_found'}), 404 _save_clients(clients) return jsonify({'client': updated})