#!/usr/bin/env python3
import json
import os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

BASE = Path('/home/sebas/work/gastos-europa')
APP = BASE / 'app'
DERIVED = BASE / 'derived'
DATA = BASE / 'data'
HTML = BASE / 'analysis.html'
TX = DERIVED / 'transactions.json'
SUMMARY = DERIVED / 'summary.json'
ALLOC = DATA / 'allocations.json'
EXCLUDED = DATA / 'excluded.json'
HOST = '127.0.0.1'
PORT = 18896


def read_json(path, default):
    try:
        return json.loads(path.read_text())
    except Exception:
        return default


def write_json(path, obj):
    path.parent.mkdir(parents=True, exist_ok=True)
    tmp = path.with_suffix(path.suffix + '.tmp')
    tmp.write_text(json.dumps(obj, indent=2, ensure_ascii=False) + '\n')
    os.replace(tmp, path)


class Handler(BaseHTTPRequestHandler):
    def _send(self, code, body, ctype='application/json; charset=utf-8'):
        body_b = body.encode('utf-8') if isinstance(body, str) else body
        self.send_response(code)
        self.send_header('Content-Type', ctype)
        self.send_header('Content-Length', str(len(body_b)))
        self.send_header('Cache-Control', 'no-store')
        self.end_headers()
        self.wfile.write(body_b)

    def _json(self, code, obj):
        self._send(code, json.dumps(obj, ensure_ascii=False), 'application/json; charset=utf-8')

    def do_GET(self):
        if self.path in ('/', '/index.html'):
            return self._send(200, HTML.read_text(), 'text/html; charset=utf-8')
        if self.path == '/api/data':
            payload = {
                'transactions': read_json(TX, []),
                'summary': read_json(SUMMARY, {}),
                'allocations': read_json(ALLOC, {}),
                'excluded': read_json(EXCLUDED, []),
            }
            return self._json(200, payload)
        if self.path == '/api/allocations':
            return self._json(200, read_json(ALLOC, {}))
        if self.path == '/api/excluded':
            return self._json(200, read_json(EXCLUDED, []))
        if self.path == '/healthz':
            return self._json(200, {'ok': True})
        return self._json(404, {'error': 'not found'})

    def do_POST(self):
        try:
            length = int(self.headers.get('Content-Length', '0'))
            raw = self.rfile.read(length).decode('utf-8') if length else '{}'
            body = json.loads(raw or '{}')
        except Exception as e:
            return self._json(400, {'error': 'bad json', 'detail': str(e)})
        if self.path == '/api/allocations':
            current = read_json(ALLOC, {})
            if isinstance(body, dict) and 'id' in body:
                ident = str(body.get('id', '')).strip()
                val = str(body.get('allocation', '')).strip()
                if not ident:
                    return self._json(400, {'error': 'missing id'})
                if val:
                    current[ident] = val
                else:
                    current.pop(ident, None)
                write_json(ALLOC, current)
                return self._json(200, {'ok': True, 'allocations': current})
            if isinstance(body, dict) and 'allocations' in body and isinstance(body['allocations'], dict):
                clean = {str(k): str(v) for k, v in body['allocations'].items() if str(v).strip()}
                write_json(ALLOC, clean)
                return self._json(200, {'ok': True, 'allocations': clean})
            return self._json(400, {'error': 'expected {id, allocation} or {allocations}'})
        if self.path == '/api/excluded':
            current = read_json(EXCLUDED, [])
            if not isinstance(current, list):
                current = []
            current = [str(x) for x in current if str(x).strip()]
            key = str(body.get('tx_key', '')).strip() if isinstance(body, dict) else ''
            if not key:
                return self._json(400, {'error': 'missing tx_key'})
            if key not in current:
                current.append(key)
                write_json(EXCLUDED, current)
            return self._json(200, {'ok': True, 'excluded': current})
        return self._json(404, {'error': 'not found'})

    def log_message(self, fmt, *args):
        return


if __name__ == '__main__':
    server = ThreadingHTTPServer((HOST, PORT), Handler)
    server.serve_forever()
