import random
import sys
import os
import json
from getpass import getpass

class zenith_11:
    STORAGE_FILE = ".zenith_storage"
    WIN_MAP = {
        "Rock": ["Scissors", "Lizard", "Fire", "Sponge", "TNT", "Human", "Towel"],
        "Paper": ["Rock", "Spock", "Water", "Towel", "TNT", "Human"],
        "Scissors": ["Paper", "Lizard", "Sponge", "Human", "Towel", "Water"],
        "Lizard": ["Spock", "Paper", "Water", "Sponge", "TNT", "Human", "Rock"],
        "Spock": ["Scissors", "Rock", "Fire", "TNT", "Human", "Water"],
        "Water": ["Fire", "Rock", "TNT", "Spock", "Scissors", "Human", "Lizard"],
        "Fire": ["Paper", "Lizard", "Towel", "Human", "Sponge", "TNT", "Rock"],
        "Human": ["Paper", "Spock", "Water", "Sponge", "Towel", "Fire", "Lizard"],
        "Towel": ["Water", "Spock", "Sponge", "Rock", "Lizard", "Fire", "TNT"],
        "Sponge": ["Water", "Spock", "Paper", "Fire", "Towel", "Scissors", "Lizard"],
        "TNT": ["Rock", "Scissors", "Human", "Fire", "Towel", "Lizard", "Paper"]
    }
    CHOICES = list(WIN_MAP.keys())

    @classmethod
    def internal_storage(cls, action="get", key=None, value=None):
        data = {}
        if os.path.exists(cls.STORAGE_FILE):
            try:
                with open(cls.STORAGE_FILE, "r") as f:
                    data = json.load(f)
            except: data = {}

        if action == "set" and key:
            data[key] = value
            with open(cls.STORAGE_FILE, "w") as f:
                json.dump(data, f)
        elif action == "get" and key:
            return data.get(key)
        elif action == "reset":
            if os.path.exists(cls.STORAGE_FILE):
                os.remove(cls.STORAGE_FILE)
            return True
        return data

    @classmethod
    def save_scoreboard(cls, p1_name, p1_score, p2_name, p2_score, difficulty=None):
        pid = os.getpid()
        filename = f"Match {pid} Scoreboard" + (f" ({difficulty}).sbrd" if difficulty else ".sbrd")
        xml_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<match>
  <player><user><![CDATA[{p1_name}]]></user><points>{p1_score}</points></player>
  <player><user><![CDATA[{p2_name}]]></user><points>{p2_score}</points></player>
</match>"""
        with open(filename, "w") as f:
            f.write(xml_content)
        print(f"\n[SYSTEM] Scoreboard saved as: {filename}")
        total_wins = cls.internal_storage("get", "lifetime_wins") or 0
        cls.internal_storage("set", "lifetime_wins", total_wins + p1_score)

    @classmethod
    def format_choice(cls, choice):
        c = choice.strip()
        return "TNT" if c.upper() == "TNT" else c.capitalize()

    @classmethod
    def show_help(cls):
        print("\n" + "="*50 + "\nZENITH-11 GUIDE\n" + "="*50)
        print(f"LIFETIME WINS: {cls.internal_storage('get', 'lifetime_wins') or 0}")
        print("\nADJUSTING DIFFICULTY:\n\n1: EASY\n2: MEDIUM\n3: HARD\n4: HARDER\n5: INSANE\n6: NIGHTMARE (harder than Insane, less hard than Extreme)\n7: EXTREME\n8: IMPOSSIBLE")
        print("\nCONTROLS:\n- 'l3ss0n' : Training\n- 'B'       : Save Scoreboard\n- 'reset'   : Wipe Storage\n- 'quit'    : Exit")
        input("\nPress Enter...")

    @classmethod
    def learning_lessons(cls):
        visits = cls.internal_storage("get", "lesson_visits") or 0
        cls.internal_storage("set", "lesson_visits", visits + 1)
        while True:
            query = cls.format_choice(input("\nXenon: Element or 'Q': "))
            if query == "Q": break
            if query in cls.WIN_MAP:
                print(f"Beats: {', '.join(cls.WIN_MAP[query])}")
                print(f"Weak to: {', '.join([k for k,v in cls.WIN_MAP.items() if query in v])}")

    @classmethod
    def startrps(cls):
        while True:
            try:
                last_user = cls.internal_storage("get", "last_user") or "New Player"
                print(f"\nZenith-11 (Welcome back, {last_user})")
                menu = input("S: Single | M: Multi | 'l3ss0n' | 'help' | 'reset' | 'quit'\n>>> ").strip().lower()

                if menu in ['quit', 'q']: break
                if menu == 'reset': cls.internal_storage("reset"); continue
                if menu == 'help': cls.show_help(); continue
                if menu == 'l3ss0n': cls.learning_lessons(); continue
                if menu not in ['s', 'm']: continue

                p1_name = input(f"Name (Default: {last_user}): ").strip() or last_user
                cls.internal_storage("set", "last_user", p1_name)

                p2_name, win_chance, diff_name = "Xenon", 0.0, "Medium"
                if menu == 's':
                    d_in = input("Diff (1-8): ").strip()
                    d_map = {"1":(0.0,"Easy"), "2":(0.0,"Medium"), "3":(0.25,"Hard"), "4":(0.45,"Harder"), 
                             "5":(0.60,"Insane"), "6":(0.80,"Nightmare"), "7":(0.95,"Extreme"), "8":(1.0,"Impossible")}
                    win_chance, diff_name = d_map.get(d_in, (0.0, "Medium"))
                else:
                    p2_name = input("Player 2 Name: ") or "Opponent"

                p1_s, p2_s = 0, 0
                while True:
                    print(f"\n{p1_name} [{p1_s}] vs {p2_name} [{p2_s}]")
                    p1_c = cls.format_choice(getpass("P1 Choice: ") if menu == 'm' else input("P1 Choice: "))
                    if p1_c not in cls.CHOICES: continue

                    if menu == 's':
                        counters = [atk for atk, vic in cls.WIN_MAP.items() if p1_c in vic]
                        p2_c = random.choice(counters) if random.random() < win_chance else random.choice(cls.CHOICES)
                    else:
                        p2_c = cls.format_choice(getpass("P2 Choice: "))

                    print(f"Reveal: {p1_c} vs {p2_c}")
                    if p1_c == p2_c: print("TIE")
                    elif p2_c in cls.WIN_MAP[p1_c]: print(f"{p1_name} WINS"); p1_s += 1
                    else: print(f"{p2_name} WINS"); p2_s += 1

                    act = input("\nC: Cont | Q: Quit | B: Save\n>>> ").upper()
                    if act == 'B': cls.save_scoreboard(p1_name, p1_s, p2_name, p2_s, diff_name)
                    if act == 'Q' or act == 'B': break
            except KeyboardInterrupt: break

def start_cli():
    zenith_11.startrps()

