"""
Move misplaced pins to correct boards.
Uses the profile Created view (known to work), opens each pin, changes board if needed.
"""
import sys, time, json, re
from pathlib import Path
sys.path.insert(0, '/app')
from pinterest.client import PinterestClient

data_dir = Path('/app/data/pinterest')

BOARD_KEY_TO_NAME = {
    'ghostbusters': 'Ghostbusters Cosplay & Equipment',
    'bttf': 'Back to the Future Replicas',
    'demon_slayer': 'Demon Slayer Art & Collectibles',
    'arcade_retro': 'Retro Arcade & Synthwave Art',
    'anime': 'Anime Posters & Wall Art',
    'anime_merch': 'Anime Merchandise & Gifts',
    'rmpropworks': 'RMPropWorks Studio: Behind the Scenes',
}

# Boards that existed BEFORE today — pins in these need checking
OLD_BOARDS = {
    'Back to the Future Replicas',
    'Ghostbusters Cosplay & Equipment',
    'RMPropWorks Studio: Behind the Scenes',
}

THEME_KEYWORDS = {
    'ghostbusters': ['ghostbusters', 'proton pack', 'ecto', 'ghost trap', 'stay puft', 'slimer'],
    'bttf': ['back to the future', 'bttf', 'delorean', 'flux capacitor', 'time circuits', '88 mph'],
    'demon_slayer': ['demon slayer', 'kimetsu', 'breathing', 'hashira', 'tanjiro', 'nezuko',
                     'rengoku', 'zenitsu', 'inosuke', 'giyu', 'shinobu', 'mitsuri', 'muichiro',
                     'obanai', 'sanemi', 'gyomei', 'kokushibo'],
    'arcade_retro': ['arcade', 'synthwave', 'vaporwave', 'neon city', 'neo-noir', 'rainy city',
                     'futuristic urban', 'cyberpunk', 'retro arcade'],
    'anime_merch': ['mug', 'gift', 'merchandise'],
    'anime': ['anime', 'manga', 'jjk', 'gojo', 'death note', 'solo leveling', 'samurai warrior',
              'spirit energy', 'cosmic warrior', 'ethereal', 'throughout heaven', 'i alone',
              'i am justice', 'just as planned', 'all according to plan', 'power level'],
}

def detect_board(title: str) -> str:
    t = title.lower()
    for key in ['ghostbusters', 'bttf', 'demon_slayer', 'arcade_retro', 'anime_merch', 'anime']:
        for kw in THEME_KEYWORDS[key]:
            if kw in t:
                return key
    return 'rmpropworks'


def load_all_pins(page) -> list:
    """Load all pins from profile Created view."""
    page.goto('https://www.pinterest.com/rmacsparran/_created/', timeout=60000)
    time.sleep(5)

    # Click Created tab
    action_bar = page.query_selector('[data-test-id="action-bar"]')
    if action_bar:
        for l in action_bar.query_selector_all('a, button, [role="tab"]'):
            if 'Created' in (l.inner_text() or ''):
                page.evaluate('el => el.click()', l)
                break
    time.sleep(5)

    # Scroll to load all pins
    last_count = 0
    for i in range(20):
        page.evaluate('window.scrollBy(0, 2000)')
        time.sleep(2)
        elems = page.query_selector_all('[data-test-id="pin"]')
        if len(elems) == last_count and i > 2:
            break
        last_count = len(elems)
        print(f'  Loaded {len(elems)} pins so far...')

    page.evaluate('window.scrollTo(0, 0)')
    time.sleep(2)

    pins = []
    for elem in page.query_selector_all('[data-test-id="pin"]'):
        try:
            title_el = elem.query_selector('[data-test-id="pinrep-footer-organic-title"]')
            title = (title_el.inner_text() or '').strip() if title_el else ''
            link_el = elem.query_selector('a[href*="/pin/"]')
            href = link_el.get_attribute('href') if link_el else ''
            if title and href:
                pins.append({'title': title, 'href': href})
        except:
            pass
    return pins


def get_pin_current_board(page, pin_url: str) -> str:
    """Navigate to pin and read its current board name."""
    page.goto(pin_url, timeout=30000)
    time.sleep(4)
    # Board is usually shown as a link above the pin title
    for sel in [
        '[data-test-id="board-name"]',
        '[data-test-id="pin-board-name"]',
        'a[href*="/rmacsparran/"][href$="/"]',
    ]:
        el = page.query_selector(sel)
        if el:
            txt = (el.inner_text() or '').strip()
            if txt and txt not in ('RMPropWorks', 'rmacsparran'):
                return txt
    return ''


def move_pin_to_board(page, pin_url: str, target_board: str) -> bool:
    """Change a pin's board via the edit modal."""
    try:
        try:
            page.goto(pin_url, timeout=60000)
        except Exception:
            print('      Timeout on first load, retrying...')
            time.sleep(10)
            page.goto(pin_url, timeout=60000)
        time.sleep(5)

        # Find edit button
        edit_btn = None
        for sel in ['[data-test-id="edit-pin-button"]', '[aria-label="Edit pin"]',
                    '[aria-label="Edit"]', '[data-test-id="edit-closeup-button"]']:
            edit_btn = page.query_selector(sel)
            if edit_btn:
                break
        if not edit_btn:
            # Try clicking the pencil icon (edit-button testid seen in board view)
            page.evaluate('''() => {
                const btns = Array.from(document.querySelectorAll('button, [role="button"]'));
                for (const b of btns) {
                    const aria = b.getAttribute('aria-label') || '';
                    if (aria.toLowerCase().includes('edit')) { b.click(); return true; }
                }
                return false;
            }''')
            time.sleep(2)
        else:
            page.evaluate('el => el.click()', edit_btn)
            time.sleep(3)

        # Look for board selector in edit modal
        # Try clicking current board name to open dropdown
        board_sel = None
        for sel in [
            '[data-test-id="board-dropdown-select-button"]',
            '[data-test-id="board-select-button"]',
        ]:
            board_sel = page.query_selector(sel)
            if board_sel:
                break

        if not board_sel:
            # Find button that has a board name in it
            for btn in page.query_selector_all('button, [role="button"]'):
                txt = (btn.inner_text() or '').strip()
                if any(b in txt for b in BOARD_KEY_TO_NAME.values()):
                    board_sel = btn
                    break

        if not board_sel:
            print('      No board selector found')
            return False

        page.evaluate('el => el.click()', board_sel)
        time.sleep(2)

        # Search for target board
        search = page.query_selector('input[placeholder*="search" i], input[placeholder*="board" i]')
        if search:
            page.evaluate('el => el.click()', search)
            page.keyboard.type(target_board[:15])
            time.sleep(1)

        # Find and click the target board option
        for item in page.query_selector_all('[role="option"], [data-test-id*="board-row"], li'):
            if target_board.lower()[:15] in (item.inner_text() or '').lower():
                page.evaluate('el => el.click()', item)
                time.sleep(2)

                # Save
                for save_sel in ['[data-test-id="edit-pin-save-button"]', 'button[type="submit"]']:
                    save_btn = page.query_selector(save_sel)
                    if save_btn:
                        page.evaluate('el => el.click()', save_btn)
                        time.sleep(3)
                        return True
                # Try pressing Enter
                page.keyboard.press('Enter')
                time.sleep(3)
                return True

        print(f'      Target board option not found: {target_board!r}')
        return False

    except Exception as ex:
        print(f'      Error: {ex}')
        return False


def main():
    moved = 0
    correct = 0
    failed = 0

    with PinterestClient(data_dir) as client:
        client.is_authenticated()

        print('Loading all pins from Created view...')
        pins = load_all_pins(client.page)
        print(f'Total pins found: {len(pins)}')

        # Group by detected correct board
        to_move = []
        for pin in pins:
            correct_key = detect_board(pin['title'])
            correct_board = BOARD_KEY_TO_NAME[correct_key]
            to_move.append({**pin, 'correct_board': correct_board, 'correct_key': correct_key})

        # Show what we're going to do
        print('\nDetected board assignments:')
        from collections import Counter
        counts = Counter(p['correct_board'] for p in to_move)
        for board, count in sorted(counts.items()):
            print(f'  {count:3d} × {board}')

        # Only move pins assigned to the 4 NEW boards (they're empty — all such pins are misplaced)
        NEW_BOARDS = {'demon_slayer', 'anime', 'anime_merch', 'arcade_retro'}
        needs_move = [p for p in to_move if p['correct_key'] in NEW_BOARDS]
        skip_count = len(to_move) - len(needs_move)
        print(f'\nSkipping {skip_count} pins already in old boards (BTTF/Ghostbusters/RMPropWorks)')
        print(f'Moving {len(needs_move)} pins to new boards...')

        for i, pin in enumerate(needs_move):
            title = pin['title']
            correct_board = pin['correct_board']
            pin_url = f"https://www.pinterest.com{pin['href']}"

            print(f'\n[{i+1}/{len(needs_move)}] {title[:55]!r}')
            print(f'  → {correct_board!r}')

            ok = move_pin_to_board(client.page, pin_url, correct_board)
            if ok:
                print(f'  Moved!')
                moved += 1
            else:
                print(f'  FAILED')
                failed += 1

            time.sleep(5)  # longer pause — Pi needs breathing room

    print(f'\n=== COMPLETE ===')
    print(f'Moved: {moved}  |  Already correct: {correct}  |  Failed: {failed}')


if __name__ == '__main__':
    main()
