# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from typing import Any, Self

from keystoneauth1 import adapter

from openstack.common import tag
from openstack import exceptions
from openstack import resource
from openstack import utils


class Trunk(resource.Resource, tag.TagMixin):
    resource_key = 'trunk'
    resources_key = 'trunks'
    base_path = '/trunks'

    _allow_unknown_attrs_in_body = True

    # capabilities
    allow_create = True
    allow_fetch = True
    allow_commit = True
    allow_delete = True
    allow_list = True

    _query_mapping = resource.QueryParameters(
        'name',
        'description',
        'port_id',
        'status',
        'sub_ports',
        'project_id',
        is_admin_state_up='admin_state_up',
        **tag.TagMixin._tag_query_parameters,
    )

    # Properties
    #: Trunk name.
    name = resource.Body('name')
    #: The ID of the project who owns the trunk. Only administrative
    #: users can specify a project ID other than their own.
    project_id = resource.Body('project_id', alias='tenant_id')
    #: Tenant_id (deprecated attribute).
    tenant_id = resource.Body('tenant_id', deprecated=True)
    #: The trunk description.
    description = resource.Body('description')
    #: The administrative state of the port, which is up ``True`` or
    #: down ``False``. *Type: bool*
    is_admin_state_up = resource.Body('admin_state_up', type=bool)
    #: The ID of the trunk's parent port
    port_id = resource.Body('port_id')
    #: The status for the trunk. Possible values are ACTIVE, DOWN, BUILD,
    #: DEGRADED, and ERROR.
    status = resource.Body('status')
    #: A list of ports associated with the trunk.
    sub_ports = resource.Body('sub_ports', type=list)

    def add_subports(
        self, session: adapter.Adapter, subports: list[dict[str, Any]]
    ) -> Self:
        url = utils.urljoin('/trunks', self.id, 'add_subports')
        resp = session.put(url, json={'sub_ports': subports})
        exceptions.raise_from_response(resp)
        self._body.attributes.update(resp.json())
        return self

    def delete_subports(
        self, session: adapter.Adapter, subports: list[dict[str, Any]]
    ) -> Self:
        url = utils.urljoin('/trunks', self.id, 'remove_subports')
        resp = session.put(url, json={'sub_ports': subports})
        exceptions.raise_from_response(resp)
        self._body.attributes.update(resp.json())
        return self

    def get_subports(self, session: adapter.Adapter) -> dict[str, Any]:
        url = utils.urljoin('/trunks', self.id, 'get_subports')
        resp = session.get(url)
        exceptions.raise_from_response(resp)
        self._body.attributes.update(resp.json())
        return resp.json()  # type: ignore[no-any-return]
