#!/usr/bin/env python3
"""
Migration: SaaS schema changes
- Update roles (ADMIN, OWNER, TALLER, BODEGA)
- Extend users table with business_name, is_active, created_at, last_login
- Create sessions, warehouse_inventory, inventory_uploads, inventory_column_mappings tables
- Add indexes
"""

import psycopg2
import sys

DB_URL = "postgresql://nexus:nexus_autoparts_2026@localhost/nexus_autoparts"

STATEMENTS = [
    # ── Roles: UPSERT to desired values ──
    """
    INSERT INTO roles (id_rol, name_rol) OVERRIDING SYSTEM VALUE VALUES (1, 'ADMIN')
    ON CONFLICT (id_rol) DO UPDATE SET name_rol = EXCLUDED.name_rol;
    """,
    """
    INSERT INTO roles (id_rol, name_rol) OVERRIDING SYSTEM VALUE VALUES (2, 'OWNER')
    ON CONFLICT (id_rol) DO UPDATE SET name_rol = EXCLUDED.name_rol;
    """,
    """
    INSERT INTO roles (id_rol, name_rol) OVERRIDING SYSTEM VALUE VALUES (3, 'TALLER')
    ON CONFLICT (id_rol) DO UPDATE SET name_rol = EXCLUDED.name_rol;
    """,
    """
    INSERT INTO roles (id_rol, name_rol) OVERRIDING SYSTEM VALUE VALUES (4, 'BODEGA')
    ON CONFLICT (id_rol) DO UPDATE SET name_rol = EXCLUDED.name_rol;
    """,

    # ── Extend users table ──
    "ALTER TABLE users ADD COLUMN IF NOT EXISTS business_name VARCHAR(200);",
    "ALTER TABLE users ADD COLUMN IF NOT EXISTS is_active BOOLEAN DEFAULT false;",
    "ALTER TABLE users ADD COLUMN IF NOT EXISTS created_at TIMESTAMP DEFAULT now();",
    "ALTER TABLE users ADD COLUMN IF NOT EXISTS last_login TIMESTAMP;",

    # ── Unique index on users(email) ──
    """
    CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email);
    """,

    # ── Sessions table ──
    """
    CREATE TABLE IF NOT EXISTS sessions (
        id_session   SERIAL PRIMARY KEY,
        user_id      INTEGER NOT NULL REFERENCES users(id_user) ON DELETE CASCADE,
        refresh_token VARCHAR(500) UNIQUE NOT NULL,
        expires_at   TIMESTAMP NOT NULL,
        created_at   TIMESTAMP DEFAULT now()
    );
    """,

    # ── Warehouse inventory table ──
    """
    CREATE TABLE IF NOT EXISTS warehouse_inventory (
        id_inventory       BIGSERIAL PRIMARY KEY,
        user_id            INTEGER NOT NULL REFERENCES users(id_user),
        part_id            INTEGER NOT NULL REFERENCES parts(id_part),
        price              NUMERIC(12,2),
        stock_quantity     INTEGER DEFAULT 0,
        min_order_quantity INTEGER DEFAULT 1,
        warehouse_location VARCHAR(100) DEFAULT 'Principal',
        updated_at         TIMESTAMP DEFAULT now(),
        UNIQUE(user_id, part_id, warehouse_location)
    );
    """,

    # ── Inventory uploads table ──
    """
    CREATE TABLE IF NOT EXISTS inventory_uploads (
        id_upload      SERIAL PRIMARY KEY,
        user_id        INTEGER NOT NULL REFERENCES users(id_user),
        filename       VARCHAR(200),
        status         VARCHAR(20) DEFAULT 'pending',
        rows_total     INTEGER,
        rows_imported  INTEGER,
        rows_errors    INTEGER,
        error_log      TEXT,
        created_at     TIMESTAMP DEFAULT now(),
        completed_at   TIMESTAMP
    );
    """,

    # ── Inventory column mappings table ──
    """
    CREATE TABLE IF NOT EXISTS inventory_column_mappings (
        id_mapping  SERIAL PRIMARY KEY,
        user_id     INTEGER NOT NULL UNIQUE REFERENCES users(id_user),
        mapping     JSONB DEFAULT '{}'::jsonb
    );
    """,

    # ── Indexes ──
    "CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(refresh_token);",
    "CREATE INDEX IF NOT EXISTS idx_sessions_user  ON sessions(user_id);",
    "CREATE INDEX IF NOT EXISTS idx_wi_part         ON warehouse_inventory(part_id);",
    "CREATE INDEX IF NOT EXISTS idx_wi_user         ON warehouse_inventory(user_id);",

    # ── Activate existing admin users ──
    "UPDATE users SET is_active = true WHERE id_rol = 1;",
]


def main():
    conn = psycopg2.connect(DB_URL)
    conn.autocommit = True
    cur = conn.cursor()

    for i, sql in enumerate(STATEMENTS, 1):
        label = sql.strip().split('\n')[0].strip()[:80]
        try:
            cur.execute(sql)
            print(f"  [{i:2d}/{len(STATEMENTS)}] OK  {label}")
        except Exception as e:
            print(f"  [{i:2d}/{len(STATEMENTS)}] ERR {label}\n       {e}")
            sys.exit(1)

    cur.close()
    conn.close()
    print(f"\nMigration complete — {len(STATEMENTS)} statements executed.")


if __name__ == "__main__":
    main()
