#!/usr/bin/env python3
"""
Automated login for Right Drive's SECOND Motorway account,
accounts@rightdrive.co.uk (Mark 2026-08-27: "we have 2 accounts for MW as
to make a purchase it has 2fa via sms and so can we add another account to
push the watched cars from BB to both accounts... also make this a auto
login in so its always active"). Whoever completes an actual purchase needs
this inbox's own SMS code, a step only a person can do, so this script only
ever logs the account IN, it never places or touches a bid; the only real
action ANY of this project's Motorway automation is ever allowed to take on
either account is BidBrain's own approved shortlist/watchlist sync (see
daily_run.watchlist_sync_pass), so both accounts show the same starred
cars without either one ever bidding on BidBrain's own say so.

Genuinely separate from the primary account's own auto_login_motorway.py in
one real way: this account gets its OWN persistent browser profile
(bidbrain.browser.ACCOUNTS_PROFILE_DIR, data/browser_profile_accounts),
never the shared PROFILE_DIR every other Motorway read and write in this
project already relies on, so the two logins can never clash or evict each
other. Its own credential lives under a deliberately distinct keychain
"server" string (pro.motorway.co.uk.accounts, see setup_credential.py),
since a real macOS keychain server field is just a lookup key, not a
resolvable hostname, and the real site is genuinely the same
pro.motorway.co.uk for both accounts.

The password is never printed, logged, written to a file, or returned from
any function here, only held in a local variable long enough to type it
into the page, read at run time from the macOS keychain via the `security`
command line tool.

Motorway's own login form has no CAPTCHA (checked live building the primary
account's own script, same shape here), but a genuine SMS 2FA step IS a
real possibility on this account (Mark's own words above), unlike the
primary account which has never shown one. This script watches for a real
one time code input appearing after submitting the form and fails loudly
with a clear message rather than hang forever waiting on a code nobody at
an unattended scheduled run can supply; the existing manual fallback
(python3 login.py motorway_accounts manual, or a direct headed run of this
script) is the real answer when that happens, matching the same safety net
already built for Dealer Auction's own occasional SMS step.

One time setup, done by Mark, not by this script:
    ~/BidBrain/.venv/bin/python setup_credential.py motorway_accounts
  The first time this script runs, macOS may prompt for permission to read
  that keychain item. Choose "Always Allow" so future scheduled runs do not
  need anyone at the keyboard.

Usage:   python3 auto_login_motorway_accounts.py            headless, for real use
         python3 auto_login_motorway_accounts.py --headed    a visible window, to watch it work

This only ever logs in. It never reads stock, purchases or bids on anything.
"""

import sys
import subprocess
from urllib.parse import urlparse
from playwright.sync_api import sync_playwright
from bidbrain import browser, db

SERVER = "pro.motorway.co.uk.accounts"
LOGIN_URL = browser.SITES["motorway"]["login_url"]
# A logged in dealer page, any one will do, just needs a URL not reachable
# without a real session. Matches login.py's own real time auto detect
# signal for this exact site.
CHECK_URL = "https://pro.motorway.co.uk/vehicles"


def _keychain_lookup(server):
    """Return (account, password) for this server from the macOS login
    keychain, or (None, None) if nothing is saved. Never prints either
    value. Raises RuntimeError (with no secret in the message) if the
    `security` tool itself is missing, which should not happen on macOS."""
    try:
        pw = subprocess.run(
            ["security", "find-internet-password", "-s", server, "-w"],
            capture_output=True, text=True,
        )
    except FileNotFoundError:
        raise RuntimeError("The macOS `security` command line tool is not available.")
    if pw.returncode != 0:
        return None, None
    password = pw.stdout.rstrip("\n")

    meta = subprocess.run(
        ["security", "find-internet-password", "-s", server],
        capture_output=True, text=True,
    )
    account = None
    for line in meta.stdout.splitlines():
        line = line.strip()
        if line.startswith('"acct"'):
            start = line.find('="')
            if start != -1:
                account = line[start + 2:-1]
            break
    return account, password


def _looks_logged_out(url):
    """The same real time signal login.py's own auto detect already uses for
    this site: the dealer host, but still on the sign in form's own path."""
    parts = urlparse(url)
    return not (parts.netloc == "pro.motorway.co.uk"
                and "login" not in parts.path and "signin" not in parts.path)


def _shows_otp_prompt(page):
    """A real one time code input appeared after submitting the form (Mark
    2026-08-27: this account has SMS 2FA "to make a purchase", so a code
    challenge on login itself is a real possibility, unlike the primary
    account which has never shown one). Checked broadly rather than against
    one guessed selector, since the exact markup was never seen live (no
    2FA challenge happened to fire during this script's own build and
    testing); any of these is treated the same way, a loud stop, never a
    hang waiting on a code nobody at an unattended run can supply."""
    for sel in ('input[autocomplete="one-time-code"]', 'input[name*="otp" i]',
                'input[name*="code" i]', 'input[type="tel"][maxlength]'):
        try:
            if page.query_selector(sel):
                return True
        except Exception:
            pass
    return False


def login(headless=True):
    account, password = _keychain_lookup(SERVER)
    if not account or not password:
        raise RuntimeError(
            f"No saved login found for {SERVER}. Run: "
            f"~/BidBrain/.venv/bin/python setup_credential.py motorway_accounts, then try again."
        )

    with sync_playwright() as p:
        ctx = browser.open_context(p, headless=headless, profile_dir=browser.ACCOUNTS_PROFILE_DIR)
        try:
            page = ctx.pages[0] if ctx.pages else ctx.new_page()
            page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=30000)
            page.wait_for_timeout(1500)
            # This profile can already be logged in from an earlier session,
            # same real signal already proven for the primary account's own
            # script (2026-08-26): /signin redirects straight to a real
            # dealer page with nothing to log into.
            if not _looks_logged_out(page.url):
                db.record_site_health("motorway_accounts", True, "")
                print("Already logged in to Motorway (accounts@rightdrive.co.uk). Nothing to do.")
                return
            try:
                page.wait_for_selector("#username", timeout=15000)
            except Exception:
                raise RuntimeError(
                    "Motorway's login page did not show the expected email field. "
                    "The page may have changed, check it by eye "
                    "(python3 login.py motorway_accounts)."
                )
            page.fill("#username", account)
            page.fill("#password", password)
            password = None  # cleared as soon as it is no longer needed
            try:
                cb = page.query_selector("#remember")
                if cb and not cb.is_checked():
                    cb.click()
            except Exception:
                pass  # a missing "keep me signed in" box is not worth failing over
            try:
                page.click('button[type="submit"]', timeout=5000)
            except Exception:
                raise RuntimeError("Could not find the Motorway login submit button.")
            page.wait_for_timeout(2000)

            if _shows_otp_prompt(page):
                raise RuntimeError(
                    "Motorway asked for a one time code (SMS 2FA) after logging in. "
                    "This needs a person present to enter it. Run: "
                    "python3 login.py motorway_accounts manual, complete the code, "
                    "and say you are logged in.")

            # A wrong password shows a real, real time error right here, on
            # THIS page, straight after the submit (found live 2026-08-27,
            # ".mw-feedback-tooltip-content", a real "Your username or
            # password were incorrect" tooltip). Caught here, before ever
            # navigating away: a first version checked for it only after
            # the CHECK_URL navigation below, which is a genuinely
            # DIFFERENT page load, one with no failed submit of its own to
            # show a tooltip for, so a real, readable reason was silently
            # coming back blank every time, caught live rather than
            # trusted from the code alone.
            err = page.query_selector(
                '.mw-feedback-tooltip-content, [class*="error" i], [role="alert"]')
            if err:
                detail = err.inner_text().strip()
                raise RuntimeError(
                    f"Motorway (accounts@rightdrive.co.uk) login did not succeed: {detail}")

            # No fixed "logged in" selector to wait on here; instead land on
            # a real dealer page and use the same dead-session check
            # login.py's own auto detect already relies on. A captcha or a
            # changed page lands here, never guessed which, just fail
            # loudly.
            try:
                page.goto(CHECK_URL, wait_until="domcontentloaded", timeout=30000)
                page.wait_for_timeout(2000)
            except Exception:
                raise RuntimeError("Motorway did not respond after logging in.")
            if _looks_logged_out(page.url):
                if _shows_otp_prompt(page):
                    raise RuntimeError(
                        "Motorway asked for a one time code (SMS 2FA). This needs a "
                        "person present. Run: python3 login.py motorway_accounts manual.")
                raise RuntimeError(
                    "Motorway (accounts@rightdrive.co.uk) login did not succeed: still on "
                    "the sign in page after submitting, a captcha or bot check may have "
                    "blocked it.")

            db.record_site_health("motorway_accounts", True, "")
            print("Logged in to Motorway (accounts@rightdrive.co.uk). Session saved.")
        finally:
            ctx.close()


if __name__ == "__main__":
    headless = "--headed" not in sys.argv
    try:
        login(headless=headless)
    except Exception as e:
        print(f"FAILED: {e}")
        sys.exit(1)
