#!/usr/bin/env python3
"""Serve the shortlist page + capture 👍/👎 votes from TWO voters (Jonathan, Gwenda).

Replaces the plain `python -m http.server 8765`: same static serving, PLUS a
`POST /vote` endpoint that writes per-person verdicts to the store. This is the
capture half of the preference loop — votes become the labels the taste-learning
refines fuzzy criteria (character) from, and the per-person overlap is the weekly
consensus instrument (both-👍 → worth visiting, both-👎 → drop, split → discuss).

Run:  python3 vote_server.py            # http://127.0.0.1:8765
Vote: POST /vote {"url": "...", "voter": "jonathan"|"gwenda", "verdict": "up"|"down"|"clear"}
"""
import datetime
import json
import threading
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

from store import load, persist, upsert

DIR = Path(__file__).resolve().parent
PORT = 8765
VOTERS = {'jonathan', 'gwenda'}
VERDICTS = {'up', 'down', 'clear'}

# Two people vote at once (Jonathan + Gwenda) → serialise the load→mutate→persist
# critical section so simultaneous clicks can't lost-update or race the file write.
_VOTE_LOCK = threading.Lock()


class Handler(SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=str(DIR), **kwargs)

    def log_message(self, *args):
        pass  # quiet

    def _send(self, code, obj):
        body = json.dumps(obj).encode()
        self.send_response(code)
        self.send_header('Content-Type', 'application/json')
        self.send_header('Content-Length', str(len(body)))
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()
        self.wfile.write(body)

    def do_POST(self):
        if self.path.split('?')[0] != '/vote':
            return self._send(404, {'error': 'not found'})
        try:
            n = int(self.headers.get('Content-Length', 0) or 0)
            data = json.loads(self.rfile.read(n) or b'{}')
        except (ValueError, json.JSONDecodeError):
            return self._send(400, {'error': 'bad json'})
        url = data.get('url')
        voter = (data.get('voter') or '').lower()
        verdict = (data.get('verdict') or '').lower()
        if not url or voter not in VOTERS or verdict not in VERDICTS:
            return self._send(400, {'error': 'need url + voter(jonathan|gwenda) + verdict(up|down|clear)'})
        with _VOTE_LOCK:  # serialise concurrent J+G votes; persist is now atomic in store.py
            store = load()
            if url not in store:
                return self._send(404, {'error': 'unknown url'})
            verdicts = dict(store[url].get('verdicts') or {})
            if verdict == 'clear':
                verdicts.pop(voter, None)
            else:
                verdicts[voter] = verdict
            upsert(store, url, {'verdicts': verdicts,
                                'verdicts_updated': datetime.datetime.now().isoformat()})
            persist(store)
        return self._send(200, {'ok': True, 'url': url, 'verdicts': verdicts})


if __name__ == '__main__':
    print(f'Serving {DIR}\n  → http://127.0.0.1:{PORT}   (POST /vote to record 👍/👎)')
    print('  Stop any existing `http.server` on 8765 first (lsof -ti:8765 | xargs kill).')
    ThreadingHTTPServer(('127.0.0.1', PORT), Handler).serve_forever()
