# -*- coding: utf-8 -*-

from fastapi import APIRouter, Depends, Query, Request

from odoo_api.core.connection import execute, sanitize_model
from odoo_api.core.limiter import limiter, route_limit
from odoo_api.dependencies.token import AuthenticatedUser, get_logged_in_user
from odoo_api.models.request import (
    SearchDataModel, CreateDataModel, UpdateDataModel,
    DeleteDataModel, ExecuteFunctionModel,
)

router = APIRouter(tags=["Models"])


@router.get('/api/models/{model}/{record_id}', summary="Read record", description="Read a single record by ID from an Odoo model.")
@limiter.limit(route_limit("/api/models/{model}/{record_id}"))
async def retrieve(request: Request,
                   model: str,
                   record_id: int,
                   fields: str = Query(default='id'),
                   user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    kwargs = dict(uid=user.uid, password=user.password, host=user.host, db=user.db, fields=fields.split(','))
    args = [[record_id]]
    res = await execute(model, "read", args, kwargs, additional_context=True)
    return {
        "data": res
    }


@router.post('/api/models/{model}/search', summary="Search records", description="Search and list records from an Odoo model with filtering, pagination, and field selection.")
@limiter.limit(route_limit("/api/models/{model}/search"))
async def search(request: Request,
                 model: str,
                 request_data: SearchDataModel = None,
                 user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    args = []
    if not request_data:
        request_data = SearchDataModel()
    kwargs = dict(uid=user.uid, password=user.password, host=user.host, db=user.db, context=request_data.context)

    param_keys = ['domain', 'fields', 'offset', 'limit', 'order']
    domain, fields, offset, limit, order = map(lambda k: getattr(request_data, k, None), param_keys)
    kwargs.update(dict(domain=domain, fields=fields, offset=offset, limit=limit, order=order))
    res = await execute(model, 'search_read', args, kwargs, additional_context=True)
    return {
        "data": res
    }


@router.post('/api/models/{model}', status_code=201, summary="Create records", description="Create one or more records in an Odoo model.")
@limiter.limit(route_limit("/api/models/{model}"))
async def create(request: Request,
                 request_data: CreateDataModel,
                 model: str,
                 user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    values = request_data.values
    args = [values]
    kwargs = dict(uid=user.uid, password=user.password, host=user.host, db=user.db, context=request_data.context)
    res = await execute(model, 'create', args, kwargs)
    return {
        "data": res
    }


@router.put('/api/models/{model}', summary="Update records", description="Update one or more records in an Odoo model by IDs.")
@limiter.limit(route_limit("/api/models/{model}"))
async def update(request: Request,
                 request_data: UpdateDataModel,
                 model: str,
                 user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    ids = request_data.ids
    values = request_data.values
    args = [ids, values]
    kwargs = dict(uid=user.uid, password=user.password, host=user.host, db=user.db, context=request_data.context)
    res = await execute(model, 'write', args, kwargs)
    return {
        "data": res
    }


@router.delete('/api/models/{model}', summary="Delete records", description="Delete one or more records from an Odoo model by IDs.")
@limiter.limit(route_limit("/api/models/{model}"))
async def delete(request: Request,
                 request_data: DeleteDataModel,
                 model: str,
                 user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    ids = request_data.ids
    args = [ids]
    kwargs = dict(uid=user.uid, password=user.password, host=user.host, db=user.db, context=request_data.context)
    res = await execute(model, 'unlink', args, kwargs)
    return {
        "data": res
    }


@router.post('/api/models/{model}/execute/{func_name}', summary="Execute function", description="Execute a custom function on an Odoo model.")
@limiter.limit(route_limit("/api/models/{model}/execute/{func_name}"))
async def execute_func(request: Request,
                       request_data: ExecuteFunctionModel,
                       model: str,
                       func_name: str,
                       user: AuthenticatedUser = Depends(get_logged_in_user)):
    model = sanitize_model(model)
    args = request_data.args
    kwargs = request_data.kwargs
    kwargs.update(dict(uid=user.uid, password=user.password, host=user.host, db=user.db, context=request_data.context))
    res = await execute(model, func_name, args, kwargs)
    return {
        "data": res
    }
