#!/usr/bin/env python3
"""Refresh the part_vehicle_preview materialized view.

Uses REFRESH MATERIALIZED VIEW CONCURRENTLY so reads are not blocked.
Requires the unique index idx_pvp_part to exist.

Usage:
    python3 refresh_part_vehicle_preview.py
    python3 refresh_part_vehicle_preview.py --dsn "postgresql://..."

Recommended cron (as postgres user or via systemd timer):
    0 3 * * * /usr/bin/python3 /home/Autopartes/scripts/refresh_part_vehicle_preview.py >> /var/log/nexus-pos/mv_refresh.log 2>&1
"""

import argparse
import os
import subprocess
import sys
import time
from datetime import datetime

import psycopg2

DEFAULT_DSN = os.environ.get('MASTER_DB_URL', 'postgresql://postgres@/nexus_autoparts')


def log(msg):
    print(f"[{datetime.now().isoformat(timespec='seconds')}] {msg}", flush=True)


def _connect(dsn):
    return psycopg2.connect(dsn)


def _ensure_connection(dsn):
    try:
        return _connect(dsn)
    except psycopg2.OperationalError as exc:
        err = str(exc).lower()
        if 'peer' in err or 'authentication' in err:
            if os.geteuid() == 0:
                log("ERROR: PostgreSQL peer authentication failed.")
                log("       Run as postgres OS user: sudo -u postgres python3 " + __file__)
                sys.exit(1)
            log("Peer auth failed. Re-running with sudo -u postgres ...")
            cmd = ['sudo', '-u', 'postgres', sys.executable, __file__]
            env = os.environ.copy()
            env['MASTER_DB_URL'] = dsn
            for i, arg in enumerate(sys.argv[1:], start=1):
                if arg in ('--dsn', '-d') and i < len(sys.argv) - 1:
                    env['MASTER_DB_URL'] = sys.argv[i + 1]
            ret = subprocess.call(cmd, env=env)
            sys.exit(ret)
        raise


def main():
    parser = argparse.ArgumentParser(description='Refresh part_vehicle_preview MV')
    parser.add_argument('--dsn', '-d', default=DEFAULT_DSN, help='PostgreSQL DSN')
    args = parser.parse_args()

    log("Starting REFRESH MATERIALIZED VIEW CONCURRENTLY part_vehicle_preview ...")
    conn = _ensure_connection(args.dsn)
    conn.autocommit = True
    cur = conn.cursor()
    start = time.time()

    try:
        cur.execute("SET statement_timeout = 0;")
        cur.execute("REFRESH MATERIALIZED VIEW CONCURRENTLY part_vehicle_preview;")
        elapsed = time.time() - start
        log(f"Refresh completed in {elapsed:.1f}s")
    except psycopg2.Error as exc:
        log(f"ERROR: {exc}")
        sys.exit(1)
    finally:
        cur.close()
        conn.close()


if __name__ == '__main__':
    main()
