"""Manifest scaffold generation tools for Airbyte connectors."""

import logging
from enum import Enum
from typing import Annotated

from pydantic import Field

from connector_builder_mcp.validation_testing import validate_manifest


logger = logging.getLogger(__name__)


class AuthenticationType(str, Enum):
    """Valid authentication types for connector manifests."""

    NO_AUTH = "NoAuth"
    API_KEY = "ApiKeyAuthenticator"
    BEARER_TOKEN = "BearerAuthenticator"
    BASIC_HTTP = "BasicHttpAuthenticator"
    OAUTH = "OAuthAuthenticator"


def _generate_manifest_yaml_directly(
    connector_name: str,
    api_base_url: str,
    initial_stream_name: str,
    initial_stream_path: str,
    authentication_type: AuthenticationType,
    http_method: str,
) -> str:
    """Generate the complete manifest YAML directly with inline comments."""
    auth_yaml = _generate_authenticator_yaml(authentication_type)
    spec_yaml = _generate_connection_spec_yaml(connector_name, authentication_type)

    return f"""# This manifest was generated by the create_connector_manifest_scaffold tool

version: "4.6.2"
type: DeclarativeSource

definitions:
  authenticator:
{auth_yaml}

check:
  type: CheckStream
  stream_names:
    - {initial_stream_name}

streams:
  - type: DeclarativeStream
    name: {initial_stream_name}
    primary_key:
      - TODO  # TODO: Update with actual primary key field from your API
    retriever:
      type: SimpleRetriever
      requester:
        type: HttpRequester
        url_base: {api_base_url}
        path: {initial_stream_path}
        http_method: {http_method}
        authenticator:
          $ref: "#/definitions/authenticator"
      record_selector:
        type: RecordSelector
        extractor:
          type: DpathExtractor
          field_path: []  # TODO: Update after examining API response structure
      paginator:
        type: NoPagination
      # TODO: Uncomment and configure pagination when known
      # paginator:
      #   type: DefaultPaginator
      #   page_token_option:
      #     type: RequestOption
      #     inject_into: request_parameter
      #     field_name: page
      #   pagination_strategy:
      #     type: PageIncrement
      #     start_from_page: 1
      schema_loader:
        type: DynamicSchemaLoader  # TODO: Consider switching to static schema for production performance
    # TODO: Uncomment and configure incremental sync when known
    # incremental_sync:
    #   type: DatetimeBasedCursor
    #   cursor_field: updated_at  # TODO: Replace with actual timestamp field
    #   datetime_format: "%Y-%m-%dT%H:%M:%S%z"
    #   start_datetime:
    #     type: MinMaxDatetime
    #     datetime: "{{ config['start_date'] }}"
    #     datetime_format: "%Y-%m-%d"
    #   end_datetime:
    #     type: MinMaxDatetime
    #     datetime: "{{ now_utc() }}"
    #     datetime_format: "%Y-%m-%dT%H:%M:%S%z"

spec:
  type: Spec
  documentation_url: https://docs.airbyte.com/integrations/sources/{connector_name}
  connection_specification:
{spec_yaml}
"""


def _generate_authenticator_yaml(auth_type: AuthenticationType) -> str:
    """Generate authenticator YAML configuration with proper indentation."""
    if auth_type == AuthenticationType.NO_AUTH:
        return "    type: NoAuth"
    elif auth_type == AuthenticationType.API_KEY:
        return """    type: ApiKeyAuthenticator
    api_token: "{{ config['api_key'] }}"
    inject_into:
      type: RequestOption
      inject_into: header
      field_name: Authorization"""
    elif auth_type == AuthenticationType.BEARER_TOKEN:
        return """    type: BearerAuthenticator
    api_token: "{{ config['api_token'] }}\""""
    elif auth_type == AuthenticationType.BASIC_HTTP:
        return """    type: BasicHttpAuthenticator
    username: "{{ config['username'] }}"
    password: "{{ config['password'] }}\""""
    elif auth_type == AuthenticationType.OAUTH:
        return """    type: OAuthAuthenticator
    client_id: "{{ config['client_id'] }}"
    client_secret: "{{ config['client_secret'] }}"
    refresh_token: "{{ config['refresh_token'] }}"
    token_refresh_endpoint: "{{ config['token_refresh_endpoint'] }}\""""

    valid_auth_types = [at.value for at in AuthenticationType]
    raise ValueError(
        f"Unsupported authentication type: {auth_type}. Must be one of: {valid_auth_types}"
    )


def _generate_connection_spec_yaml(connector_name: str, auth_type: AuthenticationType) -> str:
    """Generate connection specification YAML with proper indentation."""
    title = connector_name.replace("-", " ").title()

    # Base spec structure
    base_spec = f"""    $schema: http://json-schema.org/draft-07/schema#
    title: {title} Spec
    type: object
    additionalProperties: true"""

    auth_configs = {
        AuthenticationType.NO_AUTH: ("    properties: {}", "    required: []"),
        AuthenticationType.API_KEY: (
            """    properties:
      api_key:
        type: string
        airbyte_secret: true""",
            """    required:
      - api_key""",
        ),
        AuthenticationType.BEARER_TOKEN: (
            """    properties:
      api_token:
        type: string
        airbyte_secret: true""",
            """    required:
      - api_token""",
        ),
        AuthenticationType.BASIC_HTTP: (
            """    properties:
      username:
        type: string
      password:
        type: string
        airbyte_secret: true""",
            """    required:
      - username
      - password""",
        ),
        AuthenticationType.OAUTH: (
            """    properties:
      client_id:
        type: string
      client_secret:
        type: string
        airbyte_secret: true
      refresh_token:
        type: string
        airbyte_secret: true
      token_refresh_endpoint:
        type: string""",
            """    required:
      - client_id
      - client_secret
      - refresh_token
      - token_refresh_endpoint""",
        ),
    }

    if auth_type not in auth_configs:
        valid_auth_types = [at.value for at in AuthenticationType]
        raise ValueError(
            f"Unsupported authentication type: {auth_type}. Must be one of: {valid_auth_types}"
        )

    properties, required = auth_configs[auth_type]
    return f"""{base_spec}
{properties}
{required}"""


def create_connector_manifest_scaffold(
    connector_name: Annotated[
        str, Field(description="Connector name in kebab-case starting with 'source-'")
    ],
    api_base_url: Annotated[str, Field(description="Base URL for the API")],
    initial_stream_name: Annotated[str, Field(description="Name of the initial stream to create")],
    initial_stream_path: Annotated[
        str, Field(description="API endpoint path for the initial stream")
    ],
    authentication_type: Annotated[
        str,
        Field(
            description="Authentication method (NoAuth, ApiKeyAuthenticator, BearerAuthenticator, BasicHttpAuthenticator, OAuthAuthenticator)"
        ),
    ],
    *,
    http_method: Annotated[str, Field(description="HTTP method for requests")] = "GET",
) -> str:
    """Create a basic connector manifest scaffold with the specified configuration.

    This tool generates a complete, valid Airbyte connector manifest YAML file
    with proper authentication, pagination, and stream configuration.

    The generated manifest includes TODO placeholders with inline comments for fields
    that need to be filled in later, ensuring the manifest is valid even in its initial state.
    """
    logger.info(f"Creating connector manifest scaffold for {connector_name}")

    try:
        import re

        if not re.match(r"^source-[a-z0-9]+(-[a-z0-9]+)*$", connector_name):
            return "ERROR: Input validation error: Connector name must be in kebab-case starting with 'source-'"

        try:
            auth_type = AuthenticationType(authentication_type)
        except ValueError:
            valid_auth_types = [at.value for at in AuthenticationType]
            return f"ERROR: Input validation error: Invalid authentication_type. Must be one of: {valid_auth_types}"

        manifest_yaml = _generate_manifest_yaml_directly(
            connector_name=connector_name,
            api_base_url=api_base_url,
            initial_stream_name=initial_stream_name,
            initial_stream_path=initial_stream_path,
            authentication_type=auth_type,
            http_method=http_method.upper(),
        )

        validation_result = validate_manifest(manifest_yaml)

        if not validation_result.is_valid:
            error_details = "; ".join(validation_result.errors)
            return f"ERROR: Generated manifest failed validation: {error_details}"

        return manifest_yaml

    except Exception as e:
        logger.error(f"Error creating manifest scaffold: {e}")
        return f"ERROR: Manifest generation error: {str(e)}"
