# remottxrea/client/create_client.py

import os
from pyrogram import Client
from pyrogram.errors import SessionPasswordNeeded

from ..config.main_config import SESSIONS_DIR
from ..client.device_profile import get_random_device
from ..session.session_data_manager import session_data_manager
from ..config.apis import get_apis


class SessionCreator:

    def __init__(self):
        self.pending = {}

    # ---------- BUILD CLIENT ----------
    def build_client(self, phone, string_session=None):

        saved_data = session_data_manager.load(phone)

        if saved_data:
            device = saved_data["device"]
        else:
            device = get_random_device()

        if string_session:
            session_name = string_session
            in_memory = True
        else:
            session_name = os.path.join(SESSIONS_DIR, phone)
            in_memory = False

        api_id, api_hash = get_apis()

        return Client(
            name=session_name,
            api_id=api_id,
            api_hash=api_hash,
            device_model=device["device_model"],
            system_version=device["system_version"],
            app_version=device["app_version"],
            lang_code=device["lang_code"],
            in_memory=in_memory
        )

    # ---------- SEND CODE ----------
    async def send_code(self, phone):

        app = self.build_client(phone)

        await app.connect()

        sent_code = await app.send_code(phone)

        self.pending[phone] = {
            "app": app,
            "phone_code_hash": sent_code.phone_code_hash
        }

    # ---------- LOGIN WITH CODE ----------
    async def login_with_code(self, phone, code):

        data = self.pending.get(phone)
        if not data:
            return False

        app: Client = data["app"]

        try:
            await app.sign_in(
                phone,
                data["phone_code_hash"],
                code
            )

        except SessionPasswordNeeded:
            return "2FA"

        await self._save_session_data(
            phone,
            app,
            password=None
        )

        await app.disconnect()
        del self.pending[phone]

        return True

    # ---------- LOGIN WITH PASSWORD ----------
    async def login_with_password(self, phone, password):

        data = self.pending.get(phone)
        if not data:
            return False

        app: Client = data["app"]

        await app.check_password(password)

        await self._save_session_data(
            phone,
            app,
            password=password
        )

        await app.disconnect()
        del self.pending[phone]

        return True

    # ---------- SAVE SESSION DATA ----------
    async def _save_session_data(
        self,
        phone,
        app: Client,
        password
    ):

        me = await app.get_me()
        session_string = await app.export_session_string()

        api_id, api_hash = get_apis()

        data = {
            "phone": phone,
            "user_id": me.id,
            "username": me.username,
            "session_string": session_string,
            "device": {
                "api_id": api_id,
                "api_hash": api_hash,
                "device_model": app.device_model,
                "system_version": app.system_version,
                "app_version": app.app_version,
                "lang_code": app.lang_code
            },
            "2fa_password": password
        }

        session_data_manager.save(phone, data)