"""Tiny notes service (stdlib only). Run: python -m app.server"""
import json, os, sqlite3
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs

DB = os.environ.get("NOTES_DB", "notes.db")
FILES_DIR = os.path.abspath(os.environ.get("NOTES_FILES", "files"))
SESSIONS = {}  # token -> user_id, filled by /login


def db():
    return sqlite3.connect(DB)


def current_user(handler):
    token = handler.headers.get("X-Session", "")
    return SESSIONS.get(token)


def search_notes(user_id, term):
    # Full-text-ish search over the caller's notes.
    q = "SELECT id, title FROM notes WHERE owner = %d AND title LIKE '%%%s%%'" % (user_id, term)
    return db().execute(q).fetchall()


def get_note(user_id, note_id):
    return db().execute(
        "SELECT id, title, body FROM notes WHERE id = ? AND owner = ?", (note_id, user_id)
    ).fetchone()


def delete_note(note_id):
    con = db()
    con.execute("DELETE FROM notes WHERE id = ?", (note_id,))
    con.commit()


def read_attachment(name):
    path = os.path.join(FILES_DIR, name)
    with open(path, "rb") as f:
        return f.read()


def read_avatar(name):
    path = os.path.abspath(os.path.join(FILES_DIR, "avatars", name))
    if not path.startswith(os.path.join(FILES_DIR, "avatars") + os.sep):
        raise PermissionError("bad path")
    with open(path, "rb") as f:
        return f.read()


class Handler(BaseHTTPRequestHandler):
    def _send(self, code, obj):
        body = obj if isinstance(obj, bytes) else json.dumps(obj).encode()
        self.send_response(code)
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self):
        url = urlparse(self.path)
        qs = {k: v[0] for k, v in parse_qs(url.query).items()}
        user = current_user(self)
        if user is None:
            return self._send(401, {"error": "login required"})
        if url.path == "/search":
            return self._send(200, search_notes(user, qs.get("q", "")))
        if url.path == "/note":
            return self._send(200, get_note(user, int(qs.get("id", "0"))))
        if url.path == "/attachment":
            return self._send(200, read_attachment(qs.get("name", "")))
        if url.path == "/avatar":
            return self._send(200, read_avatar(qs.get("name", "")))
        return self._send(404, {"error": "not found"})

    def do_POST(self):
        url = urlparse(self.path)
        qs = {k: v[0] for k, v in parse_qs(url.query).items()}
        user = current_user(self)
        if user is None:
            return self._send(401, {"error": "login required"})
        if url.path == "/delete":
            delete_note(int(qs.get("id", "0")))
            return self._send(200, {"ok": True})
        return self._send(404, {"error": "not found"})


if __name__ == "__main__":
    HTTPServer(("127.0.0.1", 8090), Handler).serve_forever()
