"""Composite flow: signup → save creds → trikatuka → smurfmarkt.

One SB context, one incognito window, all three sub-flows in sequence. After
signup succeeds we save credentials to the vault immediately so even a
trikatuka or smurfmarkt failure downstream doesn't lose them.
"""
from typing import Any, Callable, Dict

import abort
from config import Config
from utils.logger import child
from vault import save_credentials

from . import smurfmarkt, spotify_signup, trikatuka

log = child("full_flow")


def run(sb_factory: Callable, params: Dict[str, Any], cfg: Config) -> Dict[str, Any]:
    new_email = params.get("new_email")
    new_password = params.get("new_password")
    old_email = params.get("old_email")
    old_password = params.get("old_password")
    upgrade_key = params.get("upgrade_key")
    country = params.get("country") or "US"
    display_name = params.get("displayName") or params.get("display_name")
    dob = params.get("dob")
    gender = params.get("gender")
    save_as_site = params.get("save_as_site") or cfg.signup_save_as_site

    log_parts = []

    with sb_factory() as sb:
        abort.register_sb(sb)
        try:
            signup_params = {
                "email": new_email,
                "password": new_password,
                "displayName": display_name,
                "dob": dob,
                "gender": gender,
            }
            r1 = spotify_signup.run(sb, signup_params, cfg)
            log_parts.append(f"signup: {'ok' if r1.get('ok') else 'FAIL ' + str(r1.get('error'))}")
            if not r1.get("ok"):
                return {
                    "ok": False,
                    "error": r1.get("error"),
                    "log": "\n".join(log_parts),
                    "email": new_email,
                    "password": new_password,
                    "save_as_site": save_as_site,
                }

            # Save credentials IMMEDIATELY so trikatuka/smurfmarkt failure can't lose them
            save_credentials(
                cfg, site=save_as_site, email=new_email, password=new_password,
                note=f"formfill-sb signup {r1.get('final_url', '')}",
            )
            log_parts.append(f"vault saved ({save_as_site})")

            trikatuka_params = {
                "old_email": old_email,
                "old_password": old_password,
                "new_email": new_email,
                "new_password": new_password,
            }
            r2 = trikatuka.run(sb, trikatuka_params, cfg)
            log_parts.append(f"trikatuka: {'ok' if r2.get('ok') else 'FAIL ' + str(r2.get('error'))}")
            if not r2.get("ok"):
                return {
                    "ok": False,
                    "error": "trikatuka: " + str(r2.get("error")),
                    "log": "\n".join(log_parts),
                    "email": new_email,
                    "password": new_password,
                    "save_as_site": save_as_site,
                }

            smurf_params = {
                "upgrade_key": upgrade_key,
                "email": new_email,
                "password": new_password,
                "country": country,
            }
            r3 = smurfmarkt.run(sb, smurf_params, cfg)
            log_parts.append(f"smurfmarkt: {'ok' if r3.get('ok') else 'FAIL ' + str(r3.get('error'))}")
            return {
                "ok": bool(r3.get("ok")),
                "error": r3.get("error"),
                "log": "\n".join(log_parts),
                "email": new_email,
                "password": new_password,
                "save_as_site": save_as_site,
            }
        finally:
            abort.clear_sb()
