import json
import threading
import unittest
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

from engine_sdk import EngineClient, EngineConnectionError, EngineResponseError


class FakeEngineHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/api/health':
            self.send_json(200, {'status': 'ok', 'service': 'fake-engine'})
            return
        self.send_json(404, {'error': 'not_found'})

    def do_POST(self):
        if self.path != '/api/generate':
            self.send_json(404, {'error': 'not_found'})
            return
        length = int(self.headers.get('Content-Length', '0'))
        payload = json.loads(self.rfile.read(length))
        self.send_json(201, {'status': 'created', 'asset': {
            'id': 'asset-test',
            'prompt': payload['prompt'],
            'imageHash': 'hash-test',
        }})

    def send_json(self, status, payload):
        body = json.dumps(payload).encode('utf-8')
        self.send_response(status)
        self.send_header('Content-Type', 'application/json')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, *_args):
        pass


class EngineSdkTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.server = ThreadingHTTPServer(('127.0.0.1', 0), FakeEngineHandler)
        cls.thread = threading.Thread(target=cls.server.serve_forever, daemon=True)
        cls.thread.start()
        cls.base_url = f'http://127.0.0.1:{cls.server.server_port}'

    @classmethod
    def tearDownClass(cls):
        cls.server.shutdown()
        cls.thread.join()

    def test_health_and_status(self):
        client = EngineClient(self.base_url)
        self.assertEqual(client.health()['status'], 'ok')
        self.assertTrue(client.status()['connected'])

    def test_generate_preserves_contract(self):
        client = EngineClient(self.base_url)
        result = client.generate('uma identidade visual', colors=['#00ffaa'])
        self.assertEqual(result['asset']['id'], 'asset-test')
        self.assertEqual(result['asset']['prompt'], 'uma identidade visual')

    def test_invalid_generation_response_is_rejected(self):
        client = EngineClient('http://127.0.0.1:1', timeout=0.1)
        with self.assertRaises(EngineConnectionError):
            client.health()

    def test_status_is_safe_when_engine_is_down(self):
        client = EngineClient('http://127.0.0.1:1', timeout=0.1)
        status = client.status()
        self.assertFalse(status['connected'])
        self.assertIn('error', status)


if __name__ == '__main__':
    unittest.main()
