/**
 * Integration Service Factory
 *
 * Generates type-safe API service functions for integrations using metadata.
 * Eliminates repetitive code by creating services dynamically.
 */

import { apiRequest } from './api';
import {
  IntegrationStatus,
  IntegrationConnection,
  CreateConnectionResponse,
  UpdateConnectionResponse,
  DeleteConnectionResponse,
} from '../types/integration';

/**
 * Credential configuration for an integration
 */
export interface CredentialConfig {
  /** Field name in the API request */
  field: string;
  /** Display label for the field */
  label: string;
  /** Placeholder text */
  placeholder?: string;
  /** Help text */
  help?: string;
}

/**
 * Resource configuration for data fetching
 */
export interface ResourceConfig {
  /** Resource name (e.g., 'lists', 'databases') */
  name: string;
  /** API endpoint path segment */
  endpoint: string;
  /** Whether this resource requires a parent ID */
  requiresParent?: boolean;
  /** Parent resource name if required */
  parentResource?: string;
}

/**
 * Integration metadata for service generation
 */
export interface IntegrationMetadata {
  /** Integration slug (e.g., 'mailchimp', 'notion') */
  slug: string;
  /** Display name */
  name: string;
  /** Description */
  description: string;
  /** Credential fields required for connection */
  credentials: CredentialConfig[];
  /** Available data resources */
  resources?: ResourceConfig[];
}

/**
 * Generated service interface for an integration
 */
export interface IntegrationService<TCredentials = Record<string, string>> {
  /** Get integration status and all connections */
  getStatus: () => Promise<IntegrationStatus>;

  // Connection management
  /** List all connections for this integration */
  listConnections: () => Promise<IntegrationConnection[]>;
  /** Create a new connection with label and credentials */
  createConnection: (label: string, credentials: TCredentials) => Promise<CreateConnectionResponse>;
  /** Update an existing connection */
  updateConnection: (
    connectionId: string,
    data: { label?: string; credentials?: TCredentials },
  ) => Promise<UpdateConnectionResponse>;
  /** Delete a connection (pass confirmDeactivateWorkflows: true to confirm deactivating affected workflows) */
  deleteConnection: (
    connectionId: string,
    options?: { confirmDeactivateWorkflows?: boolean },
  ) => Promise<DeleteConnectionResponse>;

  // Data fetching (requires connection ID)
  /** Get data from a resource for a specific connection */
  getDataForConnection: <T = unknown>(
    connectionId: string,
    resource: string,
    parentId?: string,
    childResource?: string,
  ) => Promise<T>;
}

/**
 * Create an integration service from metadata
 *
 * @param metadata Integration metadata
 * @returns Generated service object
 *
 * @example
 * ```typescript
 * const mailchimp = createIntegrationService({
 *   slug: 'mailchimp',
 *   name: 'Mailchimp',
 *   credentials: [{ field: 'api_key', label: 'API Key' }],
 *   resources: [{ name: 'lists', endpoint: 'lists' }]
 * });
 *
 * const status = await mailchimp.getStatus();
 * const lists = await mailchimp.getData<MCList[]>('lists');
 * ```
 */
export function createIntegrationService<TCredentials = Record<string, string>>(
  metadata: IntegrationMetadata,
): IntegrationService<TCredentials> {
  const basePath = `/integrations/${metadata.slug}`;
  const connectionsPath = `${basePath}/connections`;

  return {
    getStatus: () => apiRequest<IntegrationStatus>(basePath),

    // Connection management
    listConnections: () => apiRequest<IntegrationConnection[]>(connectionsPath),

    createConnection: (label: string, credentials: TCredentials) =>
      apiRequest<CreateConnectionResponse>(connectionsPath, {
        method: 'POST',
        body: JSON.stringify({ label, ...credentials }),
      }),

    updateConnection: (
      connectionId: string,
      data: { label?: string; credentials?: TCredentials },
    ) =>
      apiRequest<UpdateConnectionResponse>(`${connectionsPath}/${connectionId}`, {
        method: 'PUT',
        body: JSON.stringify(data),
      }),

    deleteConnection: (connectionId: string, options?: { confirmDeactivateWorkflows?: boolean }) => {
      const url = options?.confirmDeactivateWorkflows
        ? `${connectionsPath}/${connectionId}?confirm_deactivate_workflows=1`
        : `${connectionsPath}/${connectionId}`;
      return apiRequest<DeleteConnectionResponse>(url, {
        method: 'DELETE',
      });
    },

    // Data fetching with connection ID
    getDataForConnection: <T = unknown>(
      connectionId: string,
      resource: string,
      parentId?: string,
      childResource?: string,
    ) => {
      let endpoint = `${connectionsPath}/${connectionId}/${resource}`;

      if (parentId) {
        endpoint = `${connectionsPath}/${connectionId}/${resource}/${parentId}`;
        if (childResource) {
          endpoint = `${endpoint}/${childResource}`;
        }
      }

      return apiRequest<T>(endpoint);
    },
  };
}

// ============================================================================
// Integration Metadata Definitions
// ============================================================================

export const INTEGRATION_METADATA: Record<string, IntegrationMetadata> = {
  notion: {
    slug: 'notion',
    name: 'Notion',
    description: 'Connect your workflows to Notion pages and databases.',
    credentials: [
      {
        field: 'api_key',
        label: 'Internal Integration Token',
        placeholder: 'secret_...',
        help: 'Create an internal integration at notion.so/my-integrations',
      },
    ],
    resources: [
      {
        name: 'databases',
        endpoint: 'databases',
      },
    ],
  },
};

// ============================================================================
// Pre-generated Integration Services
// ============================================================================

/**
 * Get all integration metadata
 */
export function getAllIntegrationMetadata(): IntegrationMetadata[] {
  return Object.values(INTEGRATION_METADATA);
}

/**
 * Get metadata for a specific integration
 */
export function getIntegrationMetadata(slug: string): IntegrationMetadata | undefined {
  return INTEGRATION_METADATA[slug];
}

/**
 * Get a service for a specific integration by slug
 */
export function getIntegrationService(slug: string): IntegrationService {
  const metadata = INTEGRATION_METADATA[slug] ?? {
    slug,
    name: slug,
    description: '',
    credentials: [],
  };
  return createIntegrationService(metadata);
}
