# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# Licensed under the MIT License

"""Workspace panel and data CRUD routes — /api/workspace/*."""

from __future__ import annotations

import json
import logging
import os
import threading
from datetime import datetime
from pathlib import Path

from flask import Blueprint, Response, jsonify, request, send_file

from ..auth import require_auth
from ..helpers import get_agent, get_service_manager, DATA_DIR, safe_error

logger = logging.getLogger(__name__)

bp = Blueprint("workspace", __name__)


# ============================================================
# Workspace Panel
# ============================================================


@bp.route("/api/workspace")
@require_auth
def api_workspace():
    """Get workspace config + computed overview metrics for the active job class."""
    try:
        from familiar.jobs import get_active_job_class

        jc = get_active_job_class()
        if not jc or not jc.workspace:
            return jsonify({"workspace": None})

        from familiar.dashboard.workspace import (
            get_nonprofit_alerts,
            resolve_overview_cards,
        )

        ws = dict(jc.workspace)
        overview = ws.get("overview", {})
        if overview:
            ws["overview"]["computed_cards"] = resolve_overview_cards(overview)

        # Add smart alerts for nonprofit workspace
        if jc.key == "nonprofit_director":
            try:
                ws["alerts"] = get_nonprofit_alerts()
            except Exception:
                ws["alerts"] = []

        return jsonify({"workspace": ws})
    except Exception as e:
        logger.warning("Workspace load error: %s", e)
        return jsonify({"error": safe_error(e)}), 500


@bp.route("/api/workspace/section/<key>")
@require_auth
def api_workspace_section(key):
    """Get data for a specific workspace section."""
    try:
        from familiar.jobs import get_active_job_class

        jc = get_active_job_class()
        if not jc or not jc.workspace:
            return jsonify({"error": "No active workspace"}), 404

        sections = jc.workspace.get("sections", [])
        section_config = next((s for s in sections if s.get("key") == key), None)
        if not section_config:
            return jsonify({"error": f"Section '{key}' not found"}), 404

        from familiar.dashboard.workspace import get_section_data

        sort = request.args.get("sort")
        sort_dir = request.args.get("dir", "asc")
        page = int(request.args.get("page", 1))
        limit = int(request.args.get("limit", 50))

        data = get_section_data(section_config, sort, sort_dir, page, limit)
        return jsonify(data)
    except Exception as e:
        logger.warning("Workspace section error: %s", e)
        return jsonify({"error": safe_error(e)}), 500


@bp.route("/api/workspace/action", methods=["POST"])
@require_auth
def api_workspace_action():
    """Execute a workspace action (tool call or agent chat)."""
    try:
        payload = request.get_json() or {}
        action_config = {
            "mode": payload.get("mode", "agent"),
            "tool": payload.get("tool", ""),
            "tool_args": payload.get("tool_args", {}),
            "prompt": payload.get("prompt", ""),
            "prompt_template": payload.get("prompt_template", ""),
        }
        row_data = payload.get("row_data", {})

        from familiar.dashboard.workspace import execute_action

        agent = get_agent()
        result = execute_action(action_config, row_data, agent)
        return jsonify(result)
    except Exception as e:
        logger.warning("Workspace action error: %s", e)
        return jsonify({"result": str(e), "success": False}), 500


# ============================================================
# Workspace Data CRUD (generic JSON file records)
# ============================================================

# Allowed data files and their keys — prevents arbitrary file access
_WS_DATA_REGISTRY = {
    "studio": {"file": "studio.json", "keys": {"pieces", "commissions", "shows", "materials", "clients"}},
    "kitchen": {"file": "kitchen.json", "keys": {"recipes", "menus", "vendors"}},
    "security": {"file": "security.json", "keys": {"incidents"}},
    "osint": {"file": "osint.json", "keys": {"investigations"}},
    "network": {"file": "network.json", "keys": {"hosts"}},
}


def _ws_load_data(source: str) -> tuple:
    """Load a workspace JSON data file. Returns (data_dict, path)."""
    import json as _json

    from familiar.core.paths import DATA_DIR

    reg = _WS_DATA_REGISTRY.get(source)
    if not reg:
        return {}, None
    path = DATA_DIR / reg["file"]
    if not path.exists():
        return {}, path
    try:
        with open(path, encoding="utf-8") as f:
            return _json.load(f), path
    except (ValueError, IOError):
        return {}, path


def _ws_save_data(source: str, data: dict) -> bool:
    """Save workspace JSON data file (atomic: write to temp, then rename)."""
    import json as _json
    import tempfile

    from familiar.core.paths import DATA_DIR

    reg = _WS_DATA_REGISTRY.get(source)
    if not reg:
        return False
    path = DATA_DIR / reg["file"]
    path.parent.mkdir(parents=True, exist_ok=True)
    fd, tmp = tempfile.mkstemp(dir=path.parent, suffix=".tmp")
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as f:
            _json.dump(data, f, indent=2, default=str)
        os.replace(tmp, path)
    except BaseException:
        try:
            os.unlink(tmp)
        except OSError:
            pass
        raise
    return True


@bp.route("/api/workspace/data/<source>/<key>", methods=["POST"])
@require_auth
def api_workspace_data_create(source, key):
    """Create a record in a workspace data file."""
    import uuid

    reg = _WS_DATA_REGISTRY.get(source)
    if not reg or key not in reg["keys"]:
        return jsonify({"error": "Invalid source/key"}), 400
    payload = request.get_json(silent=True) or {}
    data, _ = _ws_load_data(source)
    records = data.get(key, [])
    record = {**payload, "id": str(uuid.uuid4())[:8]}
    records.append(record)
    data[key] = records
    _ws_save_data(source, data)
    return jsonify({"record": record, "id": record["id"]}), 201


@bp.route("/api/workspace/data/<source>/<key>/<record_id>", methods=["PUT"])
@require_auth
def api_workspace_data_update(source, key, record_id):
    """Update a record in a workspace data file."""
    reg = _WS_DATA_REGISTRY.get(source)
    if not reg or key not in reg["keys"]:
        return jsonify({"error": "Invalid source/key"}), 400
    payload = request.get_json(silent=True) or {}
    data, _ = _ws_load_data(source)
    records = data.get(key, [])
    for i, r in enumerate(records):
        if r.get("id") == record_id:
            records[i] = {**r, **payload, "id": record_id}
            data[key] = records
            _ws_save_data(source, data)
            return jsonify({"record": records[i]})
    return jsonify({"error": "Record not found"}), 404


@bp.route("/api/workspace/data/<source>/<key>/<record_id>", methods=["DELETE"])
@require_auth
def api_workspace_data_delete(source, key, record_id):
    """Delete a record from a workspace data file."""
    reg = _WS_DATA_REGISTRY.get(source)
    if not reg or key not in reg["keys"]:
        return jsonify({"error": "Invalid source/key"}), 400
    data, _ = _ws_load_data(source)
    records = data.get(key, [])
    before = len(records)
    records = [r for r in records if r.get("id") != record_id]
    if len(records) == before:
        return jsonify({"error": "Record not found"}), 404
    data[key] = records
    _ws_save_data(source, data)
    return jsonify({"status": "ok"})

