import requests as rq
import json as js
import uuid as ud
from flask import Flask, request, Response, jsonify

app = Flask(__name__)

MODEL = 'gpt-6'


def gc():
    A = 'application/json'
    return {
        'User-Agent': 'ChatGPT/1.2027.000 (Android 15; RMX3834; build 2700000)',
        'Accept': A,
        'Content-Type': A,
        'oai-client-type': 'android',
        'oai-device-id': str(ud.uuid4())
    }


def gt(h):
    B = 'https://android.chat.openai.com/backend-api/f/conversation/prepare'
    C = {'action': 'next', 'model': MODEL}
    try:
        A = rq.post(B, json=C, headers=h, timeout=5)
        if A.status_code == 200:
            return A.json().get('conduit_token', '')
    except Exception:
        pass
    return ''


def build_messages(messages):
    result = []
    for m in messages:
        role = m.get('role', 'user')
        content = m.get('content', '')
        if isinstance(content, list):
            parts = []
            for c in content:
                if isinstance(c, dict) and c.get('type') == 'text':
                    parts.append(c.get('text', ''))
                elif isinstance(c, str):
                    parts.append(c)
            content = '\n'.join(parts)
        result.append({
            'id': str(ud.uuid4()),
            'author': {'role': role},
            'content': {'content_type': 'text', 'parts': [content]}
        })
    return result


def stream_completion(messages, model):
    headers = gc()
    token = gt(headers)
    if token:
        headers['Conduit-Token'] = token
    headers['x-oai-convo-session-id'] = str(ud.uuid4())
    url = 'https://android.chat.openai.com/backend-api/f/conversation'
    payload = {
        'action': 'next',
        'messages': build_messages(messages),
        'model': model or MODEL,
        'parent_message_id': str(ud.uuid4()),
        'stream': True
    }
    resp = rq.post(url, headers=headers, json=payload, stream=True)
    last = ''
    for line in resp.iter_lines(decode_unicode=True):
        if not line:
            continue
        if not line.startswith('data: '):
            continue
        data = line[6:]
        if data == '[DONE]':
            break
        try:
            obj = js.loads(data)
            msg = obj.get('message')
            if not msg:
                continue
            author = msg.get('author', {})
            if author.get('role') != 'assistant':
                continue
            parts = msg.get('content', {}).get('parts', [])
            if not parts or not parts[0]:
                continue
            full = parts[0]
            delta = full[len(last):]
            if delta:
                last = full
                yield delta
        except Exception:
            continue


@app.route('/v1/models', methods=['GET'])
def list_models():
    return jsonify({
        'object': 'list',
        'data': [
            {'id': MODEL, 'object': 'model', 'owned_by': 'openai'},
        ]
    })


@app.route('/v1/chat/completions', methods=['POST'])
def chat_completions():
    body = request.get_json(force=True, silent=True) or {}
    messages = body.get('messages', [])
    model = body.get('model', MODEL)
    stream = bool(body.get('stream', False))
    completion_id = 'chatcmpl-' + str(ud.uuid4()).replace('-', '')

    if not stream:
        content = ''
        try:
            for chunk in stream_completion(messages, model):
                content += chunk
        except Exception:
            return jsonify({'error': {'message': 'upstream failed', 'type': 'upstream_error'}}), 502
        return jsonify({
            'id': completion_id,
            'object': 'chat.completion',
            'created': 0,
            'model': model,
            'choices': [{
                'index': 0,
                'message': {'role': 'assistant', 'content': content},
                'finish_reason': 'stop'
            }],
            'usage': {'prompt_tokens': 0, 'completion_tokens': 0, 'total_tokens': 0}
        })

    def generate():
        try:
            first = True
            for chunk in stream_completion(messages, model):
                if first:
                    first = False
                    head = {
                        'id': completion_id,
                        'object': 'chat.completion.chunk',
                        'created': 0,
                        'model': model,
                        'choices': [{'index': 0, 'delta': {'role': 'assistant'}, 'finish_reason': None}]
                    }
                    yield 'data: ' + js.dumps(head) + '\n\n'
                payload = {
                    'id': completion_id,
                    'object': 'chat.completion.chunk',
                    'created': 0,
                    'model': model,
                    'choices': [{'index': 0, 'delta': {'content': chunk}, 'finish_reason': None}]
                }
                yield 'data: ' + js.dumps(payload) + '\n\n'
            final = {
                'id': completion_id,
                'object': 'chat.completion.chunk',
                'created': 0,
                'model': model,
                'choices': [{'index': 0, 'delta': {}, 'finish_reason': 'stop'}]
            }
            yield 'data: ' + js.dumps(final) + '\n\n'
            yield 'data: [DONE]\n\n'
        except Exception:
            err = {'error': {'message': 'upstream failed', 'type': 'upstream_error'}}
            yield 'data: ' + js.dumps(err) + '\n\n'
            yield 'data: [DONE]\n\n'

    return Response(generate(), mimetype='text/event-stream')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, threaded=True)