import json
import threading
import unittest
from http.server import BaseHTTPRequestHandler,ThreadingHTTPServer
from example import basic_header,endpoint,request_chat,check

class Handler(BaseHTTPRequestHandler):
    def log_message(self,*args): pass
    def do_POST(self):
        if self.headers.get('Authorization')!=basic_header('test-user','test-password'):
            self.send_response(401);self.end_headers();return
        if self.path.startswith('/redirect/'):
            self.send_response(302);self.send_header('Location','http://127.0.0.1:9/');self.end_headers();return
        body=json.loads(self.rfile.read(int(self.headers['Content-Length'])))
        if body.get('model')!='fixture-model': self.send_response(404);self.end_headers();return
        self.send_response(200);self.send_header('Content-Type','application/json');self.end_headers()
        self.wfile.write(json.dumps({'choices':[{'message':{'content':'FIXTURE ONLY'}}]}).encode())

class HttpTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.server=ThreadingHTTPServer(('127.0.0.1',0),Handler)
        cls.thread=threading.Thread(target=cls.server.serve_forever,daemon=True);cls.thread.start()
        cls.base=f'http://127.0.0.1:{cls.server.server_port}'
        cls.auth=basic_header('test-user','test-password')
    @classmethod
    def tearDownClass(cls):
        cls.server.shutdown();cls.server.server_close();cls.thread.join()
    def test_unauthenticated_and_wrong_credentials_denied(self):
        for auth in (None,basic_header('test-user','wrong'),'Bearer not-needed'):
            self.assertEqual(request_chat(self.base,'fixture-model',auth)[0],401)
    def test_authenticated_contract(self):
        self.assertEqual(check(self.base,'fixture-model',self.auth),
                         {'unauthenticated':401,'authenticated':200,'response_shape':'chat content string'})
    def test_wrong_model_is_failure(self):
        with self.assertRaises(RuntimeError):check(self.base,'wrong-model',self.auth)
    def test_does_not_follow_redirect(self):
        self.assertEqual(request_chat(self.base+'/redirect','fixture-model',self.auth)[0],302)
    def test_rejects_public_plaintext_or_embedded_secrets(self):
        for base in ('http://example.org','https://u:p@example.org','https://example.org?q=1','file:///tmp/a'):
            with self.assertRaises(ValueError):endpoint(base)
        self.assertTrue(endpoint('https://example.ngrok.app').endswith('/v1/chat/completions'))
    def test_bad_credentials_and_model(self):
        for user,pw in (('','x'),('a:b','x'),('a',''),('a','x\ny')):
            with self.assertRaises(ValueError):basic_header(user,pw)
        with self.assertRaises(ValueError):request_chat(self.base,'',self.auth)
if __name__=='__main__':unittest.main()
