"""
Минимальное API для демонстрации Compose:
- подключение к Postgres по DATABASE_URL
- таблица notes при старте
- загрузка файла в каталог UPLOAD_DIR (том)
"""
import os
import uuid
from pathlib import Path

from flask import Flask, jsonify, request
import psycopg2
from psycopg2.extras import RealDictCursor

app = Flask(__name__)

UPLOAD_DIR = Path(os.environ.get("UPLOAD_DIR", "/data/uploads"))
DATABASE_URL = os.environ.get(
    "DATABASE_URL",
    "postgresql://app:app@localhost:5432/appdb",
)


def get_conn():
    return psycopg2.connect(DATABASE_URL, cursor_factory=RealDictCursor)


def init_db():
    UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                CREATE TABLE IF NOT EXISTS notes (
                    id SERIAL PRIMARY KEY,
                    body TEXT NOT NULL,
                    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
                );
                """
            )
        conn.commit()


@app.route("/health")
def health():
    try:
        with get_conn() as conn:
            with conn.cursor() as cur:
                cur.execute("SELECT 1 AS ok;")
                row = cur.fetchone()
        return jsonify({"status": "ok", "db": bool(row)}), 200
    except Exception as exc:  # noqa: BLE001 — демо
        return jsonify({"status": "error", "detail": str(exc)}), 503


@app.route("/status")
def stack_status():
    """Сводка для дашборда на статике: API видит БД изнутри сети Compose."""
    db_ok = False
    err = None
    try:
        with get_conn() as conn:
            with conn.cursor() as cur:
                cur.execute("SELECT version() AS v;")
                row = cur.fetchone()
        db_ok = bool(row)
        pg_version = (row.get("v") or "")[:48] if row else ""
    except Exception as exc:  # noqa: BLE001
        err = str(exc)
        pg_version = ""
    return jsonify(
        {
            "api": {"ok": True, "service": "api"},
            "database": {"ok": db_ok, "detail": pg_version or None, "error": err},
        }
    )


def _note_row(r):
    d = dict(r)
    if d.get("created_at") is not None:
        d["created_at"] = d["created_at"].isoformat()
    return d


@app.route("/notes", methods=["GET"])
def list_notes():
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT id, body, created_at FROM notes ORDER BY id DESC LIMIT 50;"
            )
            rows = cur.fetchall()
    return jsonify([_note_row(r) for r in rows])


@app.route("/notes", methods=["POST"])
def create_note():
    data = request.get_json(silent=True) or {}
    body = (data.get("body") or "").strip()
    if not body:
        return jsonify({"error": "body required"}), 400
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                "INSERT INTO notes (body) VALUES (%s) RETURNING id, body, created_at;",
                (body,),
            )
            row = cur.fetchone()
        conn.commit()
    return jsonify(_note_row(row)), 201


@app.route("/upload", methods=["POST"])
def upload():
    if "file" not in request.files:
        return jsonify({"error": "file field required"}), 400
    f = request.files["file"]
    if not f.filename:
        return jsonify({"error": "empty filename"}), 400
    safe_name = f"{uuid.uuid4().hex}_{f.filename}"
    dest = UPLOAD_DIR / safe_name
    f.save(dest)
    return jsonify({"saved_as": safe_name, "path_in_container": str(dest)}), 201


@app.route("/uploads", methods=["GET"])
def list_uploads():
    files = sorted(p.name for p in UPLOAD_DIR.iterdir() if p.is_file())
    return jsonify({"files": files})


with app.app_context():
    init_db()


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
