"""Daily Insta sync — runs on server PC at 19:00 KST.

1. Fetches new Discord forum threads (incremental — skips entries already in
   insta_meta.json by thread_id).
2. Downloads new photos/videos to C:\\fearx-photos\\insta\\<thread_id>\\.
3. Rebuilds insta_mapping.json (week/day/lunch/dinner buckets) with
   fearx-photos.sbxg.win URLs.
4. Pushes insta_mapping.json to EC2: /home/ubuntu/insta_bot/insta_mapping.json

Logs to stdout (run-sync.cmd appends to sync.log).

Env vars (set by run-sync.cmd):
- DISCORD_TOKEN
- EC2_SSH_KEY (path to private key, default C:\\Users\\User\\.ssh\\ec2_key)
- EC2_USER_HOST (default ubuntu@15.165.22.192)
"""
import json
import os
import subprocess
import sys
import time
from datetime import datetime, timezone, timedelta
from pathlib import Path

if hasattr(sys.stdout, 'reconfigure'):
    sys.stdout.reconfigure(encoding='utf-8')

HERE = Path(__file__).resolve().parent
PHOTOS_ROOT = Path(r'C:\fearx-photos\insta')
META = HERE / 'insta_meta.json'
MAPPING = HERE / 'insta_mapping.json'

EC2_KEY = os.environ.get('EC2_SSH_KEY', r'C:\Users\User\.ssh\ec2_key')
EC2_HOST = os.environ.get('EC2_USER_HOST', 'ubuntu@15.165.22.192')
EC2_DEST = '/home/ubuntu/insta_bot/insta_mapping.json'


def run(cmd, **kwargs):
    print(f'[run] {" ".join(cmd) if isinstance(cmd, list) else cmd}', flush=True)
    return subprocess.run(cmd, **kwargs)


def main():
    ts = datetime.now(timezone(timedelta(hours=9))).isoformat()
    print(f'\n=== fearx-insta-sync run @ {ts} ===', flush=True)

    # 1. Extract + download new photos
    extract = HERE / 'extract_insta_from_discord.py'
    if not extract.is_file():
        print(f'missing: {extract}', file=sys.stderr); sys.exit(1)
    r = run([sys.executable, str(extract), '--download'])
    if r.returncode != 0:
        print('extract failed', file=sys.stderr); sys.exit(2)

    # 2. Sync downloaded files to C:\fearx-photos\insta\ (master)
    local_photos = HERE / 'insta_photos'
    if local_photos.is_dir():
        PHOTOS_ROOT.mkdir(parents=True, exist_ok=True)
        # Robocopy: mirror new files only, no deletions on master
        rc = run(['robocopy', str(local_photos), str(PHOTOS_ROOT),
                  '/E', '/XO', '/NFL', '/NDL', '/NJH', '/NJS', '/NP'])
        # robocopy exit codes 0-7 = success
        if rc.returncode > 7:
            print(f'robocopy returned {rc.returncode}', file=sys.stderr)

    # 3. Build + migrate mapping
    build = HERE / 'build_insta_mapping.py'
    migrate = HERE / 'migrate_mapping_to_server.py'
    if not build.is_file() or not migrate.is_file():
        print('missing build/migrate scripts', file=sys.stderr); sys.exit(3)
    run([sys.executable, str(build)], check=True)
    run([sys.executable, str(migrate)], check=True)

    # 4. Push mapping to EC2
    if not MAPPING.is_file():
        print('mapping missing, skipping push', file=sys.stderr); sys.exit(4)
    if not Path(EC2_KEY).is_file():
        print(f'SSH key missing: {EC2_KEY}', file=sys.stderr); sys.exit(5)
    scp = run([
        'scp', '-i', EC2_KEY, '-o', 'StrictHostKeyChecking=no',
        '-o', 'UserKnownHostsFile=' + os.environ.get('USERPROFILE', '') + r'\.ssh\known_hosts',
        str(MAPPING), f'{EC2_HOST}:{EC2_DEST}'
    ])
    if scp.returncode != 0:
        print('scp failed', file=sys.stderr); sys.exit(6)
    print('=== sync complete ===', flush=True)


if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print(f'sync error: {e}', file=sys.stderr)
        sys.exit(99)
