# This file was auto-generated by Fern from our API Definition.

import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from .raw_client import AsyncRawConstrueClient, RawConstrueClient
from .types.code_response import CodeResponse
from .types.construe_upload_code_system_response import ConstrueUploadCodeSystemResponse
from .types.delete_code_system_response import DeleteCodeSystemResponse
from .types.export_code_system_response import ExportCodeSystemResponse
from .types.extract_codes_result import ExtractCodesResult
from .types.extract_request_config import ExtractRequestConfig
from .types.extract_request_system import ExtractRequestSystem
from .types.feedback_response import FeedbackResponse
from .types.get_code_response import GetCodeResponse
from .types.get_code_system_detail_response import GetCodeSystemDetailResponse
from .types.list_code_systems_response import ListCodeSystemsResponse
from .types.list_codes_response import ListCodesResponse
from .types.semantic_search_response import SemanticSearchResponse
from .types.text_search_response import TextSearchResponse
from .types.upload_request_format import UploadRequestFormat

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class ConstrueClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawConstrueClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawConstrueClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawConstrueClient
        """
        return self._raw_client

    def upload_code_system(
        self,
        *,
        name: str,
        version: str,
        format: UploadRequestFormat,
        revision: typing.Optional[float] = OMIT,
        file: typing.Optional[str] = OMIT,
        code_col: typing.Optional[str] = OMIT,
        desc_col: typing.Optional[str] = OMIT,
        defn_col: typing.Optional[str] = OMIT,
        codes: typing.Optional[typing.Sequence[CodeResponse]] = OMIT,
        replace: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ConstrueUploadCodeSystemResponse:
        """
        Upload a custom medical code system with codes and descriptions for use in code extraction. Requires a paid plan.
        Returns 202 immediately; embedding generation runs asynchronously. Poll
        GET /construe/codes/systems/{codesystem}?version={version} to check when status
        transitions from "processing" to "ready" or "failed".

        Parameters
        ----------
        name : str
            Name of the code system. Names are case-insensitive and stored uppercase.
            Builtin system names (e.g. ICD-10-CM, SNOMED_CT_US_LITE, LOINC, CPT, etc.) are
            reserved and cannot be used for custom uploads; attempts return HTTP 403 Forbidden.

        version : str
            Version of the code system

        format : UploadRequestFormat
            Upload format

        revision : typing.Optional[float]
            Optional revision number

        file : typing.Optional[str]
            The file contents as a base64-encoded string.
            For CSV format, this is the CSV file contents.
            For JSON format, this is a base64-encoded JSON array; prefer using 'codes' instead.

        code_col : typing.Optional[str]
            Column name containing codes (required for CSV format)

        desc_col : typing.Optional[str]
            Column name containing descriptions (required for CSV format)

        defn_col : typing.Optional[str]
            Optional column name containing long definitions (for CSV format)

        codes : typing.Optional[typing.Sequence[CodeResponse]]
            The codes to upload as a JSON array (JSON format only).
            This is the preferred way to upload JSON codes, as it avoids unnecessary base64 encoding.
            If both 'codes' and 'file' are provided, 'codes' takes precedence.

        replace : typing.Optional[bool]
            If true, replaces an existing code system with the same name and version.
            Builtin systems cannot be replaced; attempts to do so return HTTP 403 Forbidden.
            When false (default), uploading a duplicate returns 409 Conflict.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ConstrueUploadCodeSystemResponse
            Upload accepted for asynchronous processing

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.upload_code_system(
            name="CUSTOM_CODES",
            version="1.0",
            format="csv",
        )
        """
        _response = self._raw_client.upload_code_system(
            name=name,
            version=version,
            format=format,
            revision=revision,
            file=file,
            code_col=code_col,
            desc_col=desc_col,
            defn_col=defn_col,
            codes=codes,
            replace=replace,
            request_options=request_options,
        )
        return _response.data

    def extract_codes(
        self,
        *,
        text: str,
        system: typing.Optional[ExtractRequestSystem] = OMIT,
        config: typing.Optional[ExtractRequestConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExtractCodesResult:
        """
        Converts natural language text into structured medical codes.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        text : str
            Natural language text to extract codes from

        system : typing.Optional[ExtractRequestSystem]

        config : typing.Optional[ExtractRequestConfig]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExtractCodesResult
            Successfully extracted codes

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.extract_codes(
            text="Patient is a 14-year-old female, previously healthy, who is here for evaluation of abnormal renal ultrasound with atrophic right kidney",
        )
        """
        _response = self._raw_client.extract_codes(
            text=text, system=system, config=config, request_options=request_options
        )
        return _response.data

    def list_available_code_systems(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> ListCodeSystemsResponse:
        """
        Returns the terminology server's catalog of available code systems, including both built-in standard terminologies and custom uploaded systems.

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCodeSystemsResponse
            List of available code systems

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.list_available_code_systems()
        """
        _response = self._raw_client.list_available_code_systems(request_options=request_options)
        return _response.data

    def get_code_system_detail(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetCodeSystemDetailResponse:
        """
        Returns full metadata for a single code system, including timestamps and builtin status.

        Parameters
        ----------
        codesystem : str
            Code system name (e.g., "ICD-10-CM", "SNOMED_CT_US_LITE")

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetCodeSystemDetailResponse
            Code system detail

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.get_code_system_detail(
            codesystem="ICD-10-CM",
            version="2025",
        )
        """
        _response = self._raw_client.get_code_system_detail(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    def delete_custom_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DeleteCodeSystemResponse:
        """
        Deletes a custom (non-builtin) code system and all its codes. Builtin systems cannot be deleted.
        Only available on dedicated instances. Large systems may take up to a minute to delete.

        Parameters
        ----------
        codesystem : str
            Code system name

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteCodeSystemResponse
            Code system deleted successfully

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.delete_custom_code_system(
            codesystem="CUSTOM_CODES",
            version="version",
        )
        """
        _response = self._raw_client.delete_custom_code_system(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    def export_custom_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExportCodeSystemResponse:
        """
        Exports a custom (non-builtin) code system as a JSON file compatible with the upload format.
        The exported file can be re-uploaded directly via POST /construe/upload with format "json".
        Only available on dedicated instances. Builtin systems cannot be exported.

        Parameters
        ----------
        codesystem : str
            Code system name

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExportCodeSystemResponse
            Exported code system as JSON file

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.export_custom_code_system(
            codesystem="CUSTOM_CODES",
            version="version",
        )
        """
        _response = self._raw_client.export_custom_code_system(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    def list_codes_in_a_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        cursor: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCodesResponse:
        """
        Returns a paginated list of all codes in the specified code system from the terminology server.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name (e.g., "ICD-10-CM", "SNOMED_CT_US_LITE")

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        cursor : typing.Optional[str]
            Pagination cursor from previous response

        limit : typing.Optional[int]
            Maximum number of codes to return (default 20)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCodesResponse
            Paginated list of codes

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.list_codes_in_a_code_system(
            codesystem="ICD-10-CM",
            version="2025",
            cursor="cursor",
            limit=1,
        )
        """
        _response = self._raw_client.list_codes_in_a_code_system(
            codesystem, version=version, cursor=cursor, limit=limit, request_options=request_options
        )
        return _response.data

    def get_a_specific_code(
        self,
        codesystem: str,
        code_id: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetCodeResponse:
        """
        Looks up a specific code in the terminology server and returns its details.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        code_id : str
            The code identifier

        version : typing.Optional[str]
            Specific version of the code system

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetCodeResponse
            Code details

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.get_a_specific_code(
            codesystem="ICD-10-CM",
            code_id="E11.65",
            version="version",
        )
        """
        _response = self._raw_client.get_a_specific_code(
            codesystem, code_id, version=version, request_options=request_options
        )
        return _response.data

    def semantic_search_embedding_based(
        self,
        codesystem: str,
        *,
        text: str,
        version: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SemanticSearchResponse:
        """
        Performs semantic similarity search using vector embeddings.

        **Availability**: This endpoint works for both **built-in and custom** code systems.

        **When to use**: Best for natural language queries where you want to find conceptually
        related codes, even when different terminology is used. The search understands meaning,
        not just keywords.

        **Examples**:
        - Query "trouble breathing at night" finds codes like "Sleep apnea", "Orthopnea",
          "Nocturnal dyspnea" — semantically related but no exact keyword matches
        - Query "heart problems" finds "Myocardial infarction", "Cardiac arrest", "Arrhythmia"

        **Trade-offs**: Slower than text search (requires embedding generation), but finds
        conceptually similar results that keyword search would miss.

        See also: `/search/text` for faster keyword-based lookup with typo tolerance.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        text : str
            Natural language text to find semantically similar codes for

        version : typing.Optional[str]
            Specific version of the code system

        limit : typing.Optional[int]
            Maximum number of results (default 10, max 50)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SemanticSearchResponse
            Semantic search results ordered by similarity

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.semantic_search_embedding_based(
            codesystem="ICD-10-CM",
            text="patient has trouble breathing at night and wakes up gasping",
            version="version",
            limit=1,
        )
        """
        _response = self._raw_client.semantic_search_embedding_based(
            codesystem, text=text, version=version, limit=limit, request_options=request_options
        )
        return _response.data

    def submit_feedback_on_extraction_results(
        self,
        *,
        text: str,
        received_result: ExtractCodesResult,
        expected_result: ExtractCodesResult,
        detail: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> FeedbackResponse:
        """
        Submits user feedback on results from the Construe extraction endpoint.
        Feedback includes the full extraction result received and the result the user expected.

        Parameters
        ----------
        text : str
            The natural language text that was used for code extraction

        received_result : ExtractCodesResult

        expected_result : ExtractCodesResult

        detail : typing.Optional[str]
            Optional details explaining the feedback

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        FeedbackResponse
            Feedback saved successfully

        Examples
        --------
        from phenoml import PhenomlClient
        from phenoml.construe import (
            ExtractCodesResult,
            ExtractedCodeResult,
            ExtractRequestSystem,
        )

        client = PhenomlClient()
        client.construe.submit_feedback_on_extraction_results(
            text="Patient has type 2 diabetes with hyperglycemia",
            received_result=ExtractCodesResult(
                system=ExtractRequestSystem(),
                codes=[
                    ExtractedCodeResult(
                        code="195967001",
                        description="Asthma",
                        valid=True,
                    )
                ],
            ),
            expected_result=ExtractCodesResult(
                system=ExtractRequestSystem(),
                codes=[
                    ExtractedCodeResult(
                        code="195967001",
                        description="Asthma",
                        valid=True,
                    )
                ],
            ),
        )
        """
        _response = self._raw_client.submit_feedback_on_extraction_results(
            text=text,
            received_result=received_result,
            expected_result=expected_result,
            detail=detail,
            request_options=request_options,
        )
        return _response.data

    def terminology_server_text_search(
        self,
        codesystem: str,
        *,
        q: str,
        version: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> TextSearchResponse:
        """
        Performs fast full-text search over code IDs and descriptions.

        **Availability**: This endpoint is only available for **built-in code systems**.
        Custom code systems uploaded via `/construe/upload` are not indexed for full-text search
        and will return empty results. Use `/search/semantic` to search custom code systems.

        **When to use**: Best for autocomplete UIs, code lookup, or when users know part of
        the code ID or specific keywords. Fast response times suitable for typeahead interfaces.

        **Features**:
        - Substring matching on code IDs (e.g., "11.65" finds "E11.65")
        - Typo tolerance on descriptions (not on code IDs)
        - Fast response times (~10-50ms)

        **Examples**:
        - Query "E11" finds all codes starting with E11 (diabetes codes)
        - Query "diabtes" (typo) still finds "diabetes" codes

        **Trade-offs**: Faster than semantic search, but only matches keywords/substrings.
        Won't find conceptually related codes with different terminology.

        See also: `/search/semantic` for finding conceptually similar codes.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        q : str
            Search query (searches code IDs and descriptions)

        version : typing.Optional[str]
            Specific version of the code system

        limit : typing.Optional[int]
            Maximum number of results (default 20, max 100)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        TextSearchResponse
            Text search results

        Examples
        --------
        from phenoml import PhenomlClient

        client = PhenomlClient()
        client.construe.terminology_server_text_search(
            codesystem="ICD-10-CM",
            q="E11.65",
            version="version",
            limit=1,
        )
        """
        _response = self._raw_client.terminology_server_text_search(
            codesystem, q=q, version=version, limit=limit, request_options=request_options
        )
        return _response.data


class AsyncConstrueClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawConstrueClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawConstrueClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawConstrueClient
        """
        return self._raw_client

    async def upload_code_system(
        self,
        *,
        name: str,
        version: str,
        format: UploadRequestFormat,
        revision: typing.Optional[float] = OMIT,
        file: typing.Optional[str] = OMIT,
        code_col: typing.Optional[str] = OMIT,
        desc_col: typing.Optional[str] = OMIT,
        defn_col: typing.Optional[str] = OMIT,
        codes: typing.Optional[typing.Sequence[CodeResponse]] = OMIT,
        replace: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ConstrueUploadCodeSystemResponse:
        """
        Upload a custom medical code system with codes and descriptions for use in code extraction. Requires a paid plan.
        Returns 202 immediately; embedding generation runs asynchronously. Poll
        GET /construe/codes/systems/{codesystem}?version={version} to check when status
        transitions from "processing" to "ready" or "failed".

        Parameters
        ----------
        name : str
            Name of the code system. Names are case-insensitive and stored uppercase.
            Builtin system names (e.g. ICD-10-CM, SNOMED_CT_US_LITE, LOINC, CPT, etc.) are
            reserved and cannot be used for custom uploads; attempts return HTTP 403 Forbidden.

        version : str
            Version of the code system

        format : UploadRequestFormat
            Upload format

        revision : typing.Optional[float]
            Optional revision number

        file : typing.Optional[str]
            The file contents as a base64-encoded string.
            For CSV format, this is the CSV file contents.
            For JSON format, this is a base64-encoded JSON array; prefer using 'codes' instead.

        code_col : typing.Optional[str]
            Column name containing codes (required for CSV format)

        desc_col : typing.Optional[str]
            Column name containing descriptions (required for CSV format)

        defn_col : typing.Optional[str]
            Optional column name containing long definitions (for CSV format)

        codes : typing.Optional[typing.Sequence[CodeResponse]]
            The codes to upload as a JSON array (JSON format only).
            This is the preferred way to upload JSON codes, as it avoids unnecessary base64 encoding.
            If both 'codes' and 'file' are provided, 'codes' takes precedence.

        replace : typing.Optional[bool]
            If true, replaces an existing code system with the same name and version.
            Builtin systems cannot be replaced; attempts to do so return HTTP 403 Forbidden.
            When false (default), uploading a duplicate returns 409 Conflict.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ConstrueUploadCodeSystemResponse
            Upload accepted for asynchronous processing

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.upload_code_system(
                name="CUSTOM_CODES",
                version="1.0",
                format="csv",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.upload_code_system(
            name=name,
            version=version,
            format=format,
            revision=revision,
            file=file,
            code_col=code_col,
            desc_col=desc_col,
            defn_col=defn_col,
            codes=codes,
            replace=replace,
            request_options=request_options,
        )
        return _response.data

    async def extract_codes(
        self,
        *,
        text: str,
        system: typing.Optional[ExtractRequestSystem] = OMIT,
        config: typing.Optional[ExtractRequestConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExtractCodesResult:
        """
        Converts natural language text into structured medical codes.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        text : str
            Natural language text to extract codes from

        system : typing.Optional[ExtractRequestSystem]

        config : typing.Optional[ExtractRequestConfig]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExtractCodesResult
            Successfully extracted codes

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.extract_codes(
                text="Patient is a 14-year-old female, previously healthy, who is here for evaluation of abnormal renal ultrasound with atrophic right kidney",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.extract_codes(
            text=text, system=system, config=config, request_options=request_options
        )
        return _response.data

    async def list_available_code_systems(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> ListCodeSystemsResponse:
        """
        Returns the terminology server's catalog of available code systems, including both built-in standard terminologies and custom uploaded systems.

        Parameters
        ----------
        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCodeSystemsResponse
            List of available code systems

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.list_available_code_systems()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_available_code_systems(request_options=request_options)
        return _response.data

    async def get_code_system_detail(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetCodeSystemDetailResponse:
        """
        Returns full metadata for a single code system, including timestamps and builtin status.

        Parameters
        ----------
        codesystem : str
            Code system name (e.g., "ICD-10-CM", "SNOMED_CT_US_LITE")

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetCodeSystemDetailResponse
            Code system detail

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.get_code_system_detail(
                codesystem="ICD-10-CM",
                version="2025",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_code_system_detail(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    async def delete_custom_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DeleteCodeSystemResponse:
        """
        Deletes a custom (non-builtin) code system and all its codes. Builtin systems cannot be deleted.
        Only available on dedicated instances. Large systems may take up to a minute to delete.

        Parameters
        ----------
        codesystem : str
            Code system name

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DeleteCodeSystemResponse
            Code system deleted successfully

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.delete_custom_code_system(
                codesystem="CUSTOM_CODES",
                version="version",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete_custom_code_system(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    async def export_custom_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExportCodeSystemResponse:
        """
        Exports a custom (non-builtin) code system as a JSON file compatible with the upload format.
        The exported file can be re-uploaded directly via POST /construe/upload with format "json".
        Only available on dedicated instances. Builtin systems cannot be exported.

        Parameters
        ----------
        codesystem : str
            Code system name

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ExportCodeSystemResponse
            Exported code system as JSON file

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.export_custom_code_system(
                codesystem="CUSTOM_CODES",
                version="version",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.export_custom_code_system(
            codesystem, version=version, request_options=request_options
        )
        return _response.data

    async def list_codes_in_a_code_system(
        self,
        codesystem: str,
        *,
        version: typing.Optional[str] = None,
        cursor: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListCodesResponse:
        """
        Returns a paginated list of all codes in the specified code system from the terminology server.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name (e.g., "ICD-10-CM", "SNOMED_CT_US_LITE")

        version : typing.Optional[str]
            Specific version of the code system. Required if multiple versions exist.

        cursor : typing.Optional[str]
            Pagination cursor from previous response

        limit : typing.Optional[int]
            Maximum number of codes to return (default 20)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListCodesResponse
            Paginated list of codes

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.list_codes_in_a_code_system(
                codesystem="ICD-10-CM",
                version="2025",
                cursor="cursor",
                limit=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list_codes_in_a_code_system(
            codesystem, version=version, cursor=cursor, limit=limit, request_options=request_options
        )
        return _response.data

    async def get_a_specific_code(
        self,
        codesystem: str,
        code_id: str,
        *,
        version: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GetCodeResponse:
        """
        Looks up a specific code in the terminology server and returns its details.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        code_id : str
            The code identifier

        version : typing.Optional[str]
            Specific version of the code system

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        GetCodeResponse
            Code details

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.get_a_specific_code(
                codesystem="ICD-10-CM",
                code_id="E11.65",
                version="version",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_a_specific_code(
            codesystem, code_id, version=version, request_options=request_options
        )
        return _response.data

    async def semantic_search_embedding_based(
        self,
        codesystem: str,
        *,
        text: str,
        version: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SemanticSearchResponse:
        """
        Performs semantic similarity search using vector embeddings.

        **Availability**: This endpoint works for both **built-in and custom** code systems.

        **When to use**: Best for natural language queries where you want to find conceptually
        related codes, even when different terminology is used. The search understands meaning,
        not just keywords.

        **Examples**:
        - Query "trouble breathing at night" finds codes like "Sleep apnea", "Orthopnea",
          "Nocturnal dyspnea" — semantically related but no exact keyword matches
        - Query "heart problems" finds "Myocardial infarction", "Cardiac arrest", "Arrhythmia"

        **Trade-offs**: Slower than text search (requires embedding generation), but finds
        conceptually similar results that keyword search would miss.

        See also: `/search/text` for faster keyword-based lookup with typo tolerance.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        text : str
            Natural language text to find semantically similar codes for

        version : typing.Optional[str]
            Specific version of the code system

        limit : typing.Optional[int]
            Maximum number of results (default 10, max 50)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SemanticSearchResponse
            Semantic search results ordered by similarity

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.semantic_search_embedding_based(
                codesystem="ICD-10-CM",
                text="patient has trouble breathing at night and wakes up gasping",
                version="version",
                limit=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.semantic_search_embedding_based(
            codesystem, text=text, version=version, limit=limit, request_options=request_options
        )
        return _response.data

    async def submit_feedback_on_extraction_results(
        self,
        *,
        text: str,
        received_result: ExtractCodesResult,
        expected_result: ExtractCodesResult,
        detail: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> FeedbackResponse:
        """
        Submits user feedback on results from the Construe extraction endpoint.
        Feedback includes the full extraction result received and the result the user expected.

        Parameters
        ----------
        text : str
            The natural language text that was used for code extraction

        received_result : ExtractCodesResult

        expected_result : ExtractCodesResult

        detail : typing.Optional[str]
            Optional details explaining the feedback

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        FeedbackResponse
            Feedback saved successfully

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient
        from phenoml.construe import (
            ExtractCodesResult,
            ExtractedCodeResult,
            ExtractRequestSystem,
        )

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.submit_feedback_on_extraction_results(
                text="Patient has type 2 diabetes with hyperglycemia",
                received_result=ExtractCodesResult(
                    system=ExtractRequestSystem(),
                    codes=[
                        ExtractedCodeResult(
                            code="195967001",
                            description="Asthma",
                            valid=True,
                        )
                    ],
                ),
                expected_result=ExtractCodesResult(
                    system=ExtractRequestSystem(),
                    codes=[
                        ExtractedCodeResult(
                            code="195967001",
                            description="Asthma",
                            valid=True,
                        )
                    ],
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.submit_feedback_on_extraction_results(
            text=text,
            received_result=received_result,
            expected_result=expected_result,
            detail=detail,
            request_options=request_options,
        )
        return _response.data

    async def terminology_server_text_search(
        self,
        codesystem: str,
        *,
        q: str,
        version: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> TextSearchResponse:
        """
        Performs fast full-text search over code IDs and descriptions.

        **Availability**: This endpoint is only available for **built-in code systems**.
        Custom code systems uploaded via `/construe/upload` are not indexed for full-text search
        and will return empty results. Use `/search/semantic` to search custom code systems.

        **When to use**: Best for autocomplete UIs, code lookup, or when users know part of
        the code ID or specific keywords. Fast response times suitable for typeahead interfaces.

        **Features**:
        - Substring matching on code IDs (e.g., "11.65" finds "E11.65")
        - Typo tolerance on descriptions (not on code IDs)
        - Fast response times (~10-50ms)

        **Examples**:
        - Query "E11" finds all codes starting with E11 (diabetes codes)
        - Query "diabtes" (typo) still finds "diabetes" codes

        **Trade-offs**: Faster than semantic search, but only matches keywords/substrings.
        Won't find conceptually related codes with different terminology.

        See also: `/search/semantic` for finding conceptually similar codes.

        Usage of CPT is subject to AMA requirements: see PhenoML Terms of Service.

        Parameters
        ----------
        codesystem : str
            Code system name

        q : str
            Search query (searches code IDs and descriptions)

        version : typing.Optional[str]
            Specific version of the code system

        limit : typing.Optional[int]
            Maximum number of results (default 20, max 100)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        TextSearchResponse
            Text search results

        Examples
        --------
        import asyncio

        from phenoml import AsyncPhenomlClient

        client = AsyncPhenomlClient()


        async def main() -> None:
            await client.construe.terminology_server_text_search(
                codesystem="ICD-10-CM",
                q="E11.65",
                version="version",
                limit=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.terminology_server_text_search(
            codesystem, q=q, version=version, limit=limit, request_options=request_options
        )
        return _response.data
