import os
import socketserver
import textwrap
from Crypto.Util.number import getPrime

FLAG = os.getenv("FLAG", "vsosh{0000000}")
MODULUS = getPrime(64)

def parse_flag_int(flag_value: str) -> int:
    if "{" in flag_value and "}" in flag_value:
        inner = flag_value.split("{", 1)[1].rsplit("}", 1)[0]
        if inner.isdigit():
            return int(inner)
    raise

FLAG_INT = parse_flag_int(FLAG)
if not (0 < FLAG_INT < MODULUS):
    raise

BANNER = textwrap.dedent(
    """
    === Древний страж ===
    Страж-оракул возвращает: (flag * x) mod p
    - p - 64-битное простое число
    - x - целое, x != 0 и x != 1
    Введите 'help' для правил, 'exit' для выхода.
    """
).strip()

HELP = textwrap.dedent(
    """
    Отправьте одно целое число x.
    Ответ: (flag * x) mod p
    Ограничения: x != 0 и x != 1
    """
).strip()


class Handler(socketserver.BaseRequestHandler):
    def handle(self) -> None:
        conn = self.request
        conn.sendall((BANNER + "\n").encode())
        while True:
            conn.sendall(b"x> ")
            line = self._readline(conn)
            if line is None:
                return
            line = line.strip()
            if not line:
                continue
            if line.lower() in {"exit", "quit"}:
                conn.sendall(b"bye\n")
                return
            if line.lower() in {"help", "?"}:
                conn.sendall((HELP + "\n").encode())
                continue
            try:
                x = int(line)
            except ValueError:
                conn.sendall(b"invalid integer\n")
                continue
            if x in (0, 1):
                conn.sendall(b"x is forbidden\n")
                continue
            y = (FLAG_INT * x) % MODULUS
            conn.sendall((str(y) + "\n").encode())

    @staticmethod
    def _readline(conn, limit: int = 4096):
        data = bytearray()
        while len(data) < limit:
            chunk = conn.recv(1)
            if not chunk:
                return None
            if chunk == b"\n":
                break
            if chunk != b"\r":
                data += chunk
        return data.decode(errors="ignore")


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    allow_reuse_address = True


if __name__ == "__main__":
    host = "0.0.0.0"
    port = 5000
    with ThreadedTCPServer((host, port), Handler) as server:
        server.serve_forever()
