"""Repair Odoo sale-order references accidentally stored as customer names.

v4.9.25.3 fixes the source of the issue. This script repairs rows already
created by older v4.9.25.x builds where customers.name became S00xxx although
metadata.raw_customer_payload.partner_name contains the real fiscal customer.

Dry-run by default. Use --apply to update rows.
"""
from __future__ import annotations

import argparse
from typing import Any, Dict, List

from sqlalchemy import text

from app.db import engine


def _partner_name_from_metadata(metadata: Any) -> str:
    if not isinstance(metadata, dict):
        return ""
    raw = metadata.get("raw_customer_payload")
    if not isinstance(raw, dict):
        return ""
    partner_name = str(raw.get("partner_name") or "").strip()
    if partner_name:
        return partner_name
    partner_id = raw.get("partner_id")
    if isinstance(partner_id, (list, tuple)) and len(partner_id) > 1:
        return str(partner_id[1] or "").strip()
    return ""


def find_rows() -> List[Dict[str, Any]]:
    with engine.begin() as conn:
        rows = conn.execute(text("""
            SELECT id::text, name, tax_id, email, metadata
            FROM customers
            WHERE name ~ '^S[0-9]{4,}'
              AND metadata->>'source_system' = 'odoo'
            ORDER BY updated_at DESC
        """)).mappings().all()
    result: List[Dict[str, Any]] = []
    for row in rows:
        partner_name = _partner_name_from_metadata(row.get("metadata"))
        if partner_name and not partner_name.upper().startswith("S00"):
            data = dict(row)
            data["new_name"] = partner_name
            result.append(data)
    return result


def apply(rows: List[Dict[str, Any]]) -> int:
    updated = 0
    with engine.begin() as conn:
        for row in rows:
            conn.execute(text("""
                UPDATE customers
                SET name = :new_name,
                    metadata = COALESCE(metadata, '{}'::jsonb) || jsonb_build_object(
                        'odoo_sale_order_name_repaired', true,
                        'previous_customer_name', CAST(:old_name AS TEXT)
                    ),
                    updated_at = now()
                WHERE id = CAST(:id AS UUID)
            """), {"id": row["id"], "old_name": row["name"], "new_name": row["new_name"]})
            updated += 1
    return updated


def main() -> None:
    parser = argparse.ArgumentParser(description="Repair Odoo S00xxx customer names.")
    parser.add_argument("--apply", action="store_true", help="Apply updates. Default is dry-run.")
    args = parser.parse_args()

    rows = find_rows()
    print(f"Clientes Odoo com nome S00xxx reparáveis: {len(rows)}")
    for row in rows[:50]:
        print(f"- {row['name']} -> {row['new_name']} | NIF {row.get('tax_id') or '-'} | email {row.get('email') or '-'}")
    if len(rows) > 50:
        print(f"... mais {len(rows)-50}")
    if not args.apply:
        print("Dry-run. Para aplicar: repetir com --apply")
        return
    print(f"Atualizados: {apply(rows)}")


if __name__ == "__main__":
    main()
