#!/usr/bin/env python3
import sys, os, ast
import xmlrpc.client
from argparse import ArgumentParser, RawTextHelpFormatter
from urllib.parse import urlparse

example_text = """
# Create a new partner with name and email
odoocli --method 'create' --model 'res.partner' --value "{'name': 'User', 'email': 'user@example.com'}"
# Update the name of the partner with id 66
odoocli --method 'write' --model 'res.partner' --domain "[('id', '=', 66)]" --field 'name' --value 'New Name'
# Read the 'name' field of the partner with id 66
odoocli --method 'read' --model 'res.partner' --domain "[('id', '=', 66)]" --field 'name'
# Count the number of partners with email domain 'example.com'
odoocli --method 'search_count' --model 'res.partner' --domain "[('email', 'like', '%example.com%')]"
# Find the id of the first partner with email 'user@example.com'
odoocli --method 'search_one' --model 'res.partner' --domain "[('email', '=', 'user@example.com')]"
# Delete the partner with id 66
odoocli --method 'unlink' --model 'res.partner' --domain "[('id', '=', 66)]"
# List selected model fields
odoocli --method 'search_read' --model 'ir.model' --domain "[]" --fields "['name','model']"
# Include archived records in search
odoocli --method 'search_read' --model 'res.partner' --domain "[('name', 'ilike', 'John')]" --fields "['name','active']" --include-archived
"""

# Create the argument parser
parser = ArgumentParser(
    prog="odoocli",
    description="Update Odoo records using the XML-RPC API.",
    formatter_class=RawTextHelpFormatter,
    epilog=example_text
)

# Define arguments
parser.add_argument('--method', help='The operation to perform: "create", "write", "read", "search_count", "search_one", or "unlink".')
parser.add_argument('--model', help='The Odoo model to interact with, e.g., "res.partner".')
parser.add_argument('--domain', help='The domain filter in the form of [("field", "operator", "value")], used to search for records.')
parser.add_argument('--field', help='The field name in the model to update or read.')
parser.add_argument('--fields', help='The fields to read when using the search_read method, e.g., ["name", "email"].')
parser.add_argument('--value', help='The value to write or create, or the field to read.')
parser.add_argument('--include-archived', action='store_true', help='Include archived (non-active) records in search operations.')

# Parse arguments
args = parser.parse_args()

# Show help if no command is given
if not any(vars(args).values()):
    parser.print_help()
    sys.exit()

# Get environment variables
url = os.environ.get("ODOO_URL") or "http://localhost:8069"
db = os.environ.get("ODOO_DATABASE") or "odoo"
username = os.getenv("ODOO_USERNAME") or "admin"
password = os.environ.get("ODOO_PASSWORD") or "admin"

# Connect to Odoo
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")

# Check if the user has access rights
models.execute_kw(db, uid, password, args.model, "check_access_rights", ["read"], {"raise_exception": False})

# Parse domain and value
if args.domain:
    domain = ast.literal_eval(args.domain)
if args.value:
    value = ast.literal_eval(args.value)
if args.fields:
    fields = ast.literal_eval(args.fields)

# Build context for archived records
context = {}
if args.include_archived:
    context['active_test'] = False

# Execute the selected method
if args.method == "create":
    models.execute_kw(db, uid, password, args.model, "create", [value])
elif args.method == "write":
    # Pass context inside 'context' key
    ids = models.execute_kw(db, uid, password, args.model, "search", [domain], {'context': context})
    models.execute_kw(db, uid, password, args.model, "write", [ids, {args.field: value}])
elif args.method == "read":
    # Pass context + limit inside 'context' key
    ids = models.execute_kw(db, uid, password, args.model, "search", [domain], {'context': {**context, 'limit': 1}})
    res = models.execute_kw(db, uid, password, args.model, "read", [ids])
    print(res[0][args.field])
elif args.method == "search_count":
    count = models.execute_kw(db, uid, password, args.model, "search_count", [domain], {'context': context})
    print(count)
elif args.method == "search_one":
    ids = models.execute_kw(db, uid, password, args.model, "search", [domain], {'context': context})
    print(ids[0])
elif args.method == "unlink":
    ids = models.execute_kw(db, uid, password, args.model, "search", [domain], {'context': context})
    models.execute_kw(db, uid, password, args.model, "unlink", [ids])
elif args.method == "search_read":
    res = models.execute_kw(db, uid, password, args.model, "search_read", [domain], {'context': context, 'fields': fields})
    print(res)