"""Asset library spike API (prod, behind the dashboard Google login + a proxy trust header).
GET  /api/state                      -> {assets: {id: {feedback: [...]}}, jobs: [...]}
POST /api/feedback {id, text}        -> saves a note on an asset
POST /api/rerun    {id, text}        -> saves the note (if any) and queues a re-run (one open job per asset)
POST /api/lighter  {id, target?}     -> queues a lighter copy (no target = auto: lightest that keeps the look)
POST /api/activate {id, version}     -> queues 'use this version in games'
The local workers read the queue through cli.py over ssh (re-runs and quick jobs in separate lanes)."""
import json, os, re
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import store
TRUST = open(os.environ.get('FAL_TRUST_FILE', '/home/forge/fal-feedback/trust')).read().strip()
ID = re.compile(r'^[a-z0-9.-]+/[a-z0-9.-]+$')


class H(BaseHTTPRequestHandler):
    def _send(self, code, obj):
        b = json.dumps(obj).encode()
        self.send_response(code); self.send_header('Content-Type', 'application/json'); self.send_header('Cache-Control', 'no-store')
        self.send_header('Content-Length', str(len(b))); self.end_headers(); self.wfile.write(b)

    def _ok(self):
        if self.headers.get('x-fal-trust') != TRUST:
            self._send(403, {'error': 'forbidden'}); return False
        return True

    def _user(self):
        for h in ('X-Forwarded-Email', 'X-Auth-Request-Email', 'X-Forwarded-User', 'Remote-User'):
            if self.headers.get(h):
                return self.headers[h][:120]
        return 'dashboard'

    def do_GET(self):
        if not self._ok(): return
        if self.path.split('?')[0] == '/api/state':
            with store.locked() as st:
                return self._send(200, st)
        self._send(404, {'error': 'not found'})

    def do_POST(self):
        if not self._ok(): return
        try:
            n = min(int(self.headers.get('Content-Length') or 0), 20000)
            body = json.loads(self.rfile.read(n) or b'{}')
        except ValueError:
            return self._send(400, {'error': 'bad json'})
        aid, text = str(body.get('id', '')), str(body.get('text', '')).strip()
        if not ID.match(aid):
            return self._send(400, {'error': 'bad id'})
        p = self.path.split('?')[0]
        with store.locked() as st:
            if p == '/api/feedback':
                if not text: return self._send(400, {'error': 'empty'})
                return self._send(200, {'saved': store.add_feedback(st, aid, text, self._user())})
            if p in ('/api/lighter', '/api/activate'):
                kind = p.rsplit('/', 1)[1]
                try:
                    params = ({'target': int(body['target'])} if body.get('target') not in (None, '') else {}) if kind == 'lighter' \
                        else {'version': int(body['version'])}
                except (KeyError, TypeError, ValueError):
                    return self._send(400, {'error': 'bad number'})
                if params.get('target') is not None and not 100 <= params['target'] <= 10_000_000:
                    return self._send(400, {'error': 'target out of range'})
                job, open_job = store.add_job(st, aid, '', self._user(), kind, params)
                if open_job: return self._send(409, {'error': 'already queued or running', 'job': open_job})
                return self._send(200, {'job': job})
            if p == '/api/rerun':
                if text: store.add_feedback(st, aid, text, self._user())
                fb = text or '\n'.join(f['text'] for f in st['assets'].get(aid, {}).get('feedback', [])[-3:])
                job, open_job = store.add_job(st, aid, fb, self._user())
                if open_job: return self._send(409, {'error': 'already queued or running', 'job': open_job})
                return self._send(200, {'job': job})
        self._send(404, {'error': 'not found'})

    def log_message(self, *a):
        pass


if __name__ == '__main__':
    ThreadingHTTPServer(('172.18.0.1', int(os.environ.get('FAL_PORT', '8963'))), H).serve_forever()
