import type { Request, Response } from "express";

import { handleNonStreaming, handleStreaming } from "../handlers/gemini.js";
import type { Provider, ValidationResult, HandlerConfig } from "./types.js";

/**
 * Google GenAI (Gemini) Generate Content API Provider (v1beta)
 */
export const geminiGenerateProvider: Provider = {
  id: "gemini-generate",
  label: "Gemini Generate (v1beta)",
  routePath: "/v1beta/models/:model\\:generateContent",
  method: "POST",

  validateRequest(req: Request): ValidationResult {
    const body = req.body;

    if (
      !body.contents ||
      !Array.isArray(body.contents) ||
      body.contents.length === 0
    ) {
      return {
        valid: false,
        message: "contents is required and must be a non-empty array",
        field: "contents",
      };
    }

    return { valid: true };
  },

  isStreamingRequest(): boolean {
    return false; // This endpoint is always non-streaming
  },

  formatRateLimitError(): unknown {
    return {
      error: {
        code: 429,
        message: "Resource exhausted. Please try again later.",
        status: "RESOURCE_EXHAUSTED",
      },
    };
  },

  formatValidationError(message: string): unknown {
    return {
      error: {
        code: 400,
        message,
        status: "INVALID_ARGUMENT",
      },
    };
  },

  formatServerError(message = "Internal server error"): unknown {
    return {
      error: {
        code: 500,
        message,
        status: "INTERNAL",
      },
    };
  },

  formatAuthenticationError(
    message = "API key not valid. Please pass a valid API key."
  ): unknown {
    return {
      error: {
        code: 401,
        message,
        status: "UNAUTHENTICATED",
      },
    };
  },

  formatPermissionDeniedError(
    message = "Permission denied on resource"
  ): unknown {
    return {
      error: {
        code: 403,
        message,
        status: "PERMISSION_DENIED",
      },
    };
  },

  formatDisabledError(): unknown {
    return {
      error: {
        code: 503,
        message: "This endpoint is currently disabled",
        status: "UNAVAILABLE",
      },
    };
  },

  async handleNonStreaming(
    req: Request,
    config: HandlerConfig
  ): Promise<unknown> {
    const modelParam = req.params.model;
    const model =
      typeof modelParam === "string" ? modelParam : (modelParam?.[0] ?? "");
    const body = req.body;
    const serverConfig = {
      ...config,
      port: 0,
      rateLimitEnabled: false,
      rateLimitRequests: 0,
      rateLimitWindowMs: 0,
      rateLimitFailureMode: "after_n" as const,
      rateLimitRandomProbability: 0,
      rateLimitAfterN: 0,
    };
    return await handleNonStreaming(model, body, serverConfig);
  },

  async handleStreaming(): Promise<void> {
    throw new Error(
      "Streaming not supported on this endpoint. Use streamGenerateContent."
    );
  },
};

/**
 * Google GenAI (Gemini) Stream Generate Content API Provider (v1beta)
 */
export const geminiStreamProvider: Provider = {
  id: "gemini-stream",
  label: "Gemini Stream (v1beta)",
  routePath: "/v1beta/models/:model\\:streamGenerateContent",
  method: "POST",

  validateRequest(req: Request): ValidationResult {
    const body = req.body;

    if (
      !body.contents ||
      !Array.isArray(body.contents) ||
      body.contents.length === 0
    ) {
      return {
        valid: false,
        message: "contents is required and must be a non-empty array",
        field: "contents",
      };
    }

    return { valid: true };
  },

  isStreamingRequest(): boolean {
    return true; // This endpoint is always streaming
  },

  formatRateLimitError(): unknown {
    return {
      error: {
        code: 429,
        message: "Resource exhausted. Please try again later.",
        status: "RESOURCE_EXHAUSTED",
      },
    };
  },

  formatValidationError(message: string): unknown {
    return {
      error: {
        code: 400,
        message,
        status: "INVALID_ARGUMENT",
      },
    };
  },

  formatServerError(message = "Internal server error"): unknown {
    return {
      error: {
        code: 500,
        message,
        status: "INTERNAL",
      },
    };
  },

  formatAuthenticationError(
    message = "API key not valid. Please pass a valid API key."
  ): unknown {
    return {
      error: {
        code: 401,
        message,
        status: "UNAUTHENTICATED",
      },
    };
  },

  formatPermissionDeniedError(
    message = "Permission denied on resource"
  ): unknown {
    return {
      error: {
        code: 403,
        message,
        status: "PERMISSION_DENIED",
      },
    };
  },

  formatDisabledError(): unknown {
    return {
      error: {
        code: 503,
        message: "This endpoint is currently disabled",
        status: "UNAVAILABLE",
      },
    };
  },

  handleNonStreaming(): unknown {
    throw new Error(
      "Non-streaming not supported on this endpoint. Use generateContent."
    );
  },

  async handleStreaming(
    req: Request,
    res: Response,
    config: HandlerConfig
  ): Promise<void> {
    const modelParam = req.params.model;
    const model =
      typeof modelParam === "string" ? modelParam : (modelParam?.[0] ?? "");
    const body = req.body;
    const serverConfig = {
      ...config,
      port: 0,
      rateLimitEnabled: false,
      rateLimitRequests: 0,
      rateLimitWindowMs: 0,
      rateLimitFailureMode: "after_n" as const,
      rateLimitRandomProbability: 0,
      rateLimitAfterN: 0,
    };
    await handleStreaming(model, body, res, serverConfig);
  },
};

/**
 * Google GenAI (Gemini) Generate Content API Provider (v1)
 */
export const geminiGenerateV1Provider: Provider = {
  id: "gemini-generate-v1",
  label: "Gemini Generate (v1)",
  routePath: "/v1/models/:model\\:generateContent",
  method: "POST",

  validateRequest: geminiGenerateProvider.validateRequest,
  isStreamingRequest: geminiGenerateProvider.isStreamingRequest,
  formatRateLimitError: geminiGenerateProvider.formatRateLimitError,
  formatValidationError: geminiGenerateProvider.formatValidationError,
  formatServerError: geminiGenerateProvider.formatServerError,
  formatAuthenticationError: geminiGenerateProvider.formatAuthenticationError,
  formatPermissionDeniedError:
    geminiGenerateProvider.formatPermissionDeniedError,
  formatDisabledError: geminiGenerateProvider.formatDisabledError,
  handleNonStreaming: geminiGenerateProvider.handleNonStreaming,
  handleStreaming: geminiGenerateProvider.handleStreaming,
};

/**
 * Google GenAI (Gemini) Stream Generate Content API Provider (v1)
 */
export const geminiStreamV1Provider: Provider = {
  id: "gemini-stream-v1",
  label: "Gemini Stream (v1)",
  routePath: "/v1/models/:model\\:streamGenerateContent",
  method: "POST",

  validateRequest: geminiStreamProvider.validateRequest,
  isStreamingRequest: geminiStreamProvider.isStreamingRequest,
  formatRateLimitError: geminiStreamProvider.formatRateLimitError,
  formatValidationError: geminiStreamProvider.formatValidationError,
  formatServerError: geminiStreamProvider.formatServerError,
  formatAuthenticationError: geminiStreamProvider.formatAuthenticationError,
  formatPermissionDeniedError: geminiStreamProvider.formatPermissionDeniedError,
  formatDisabledError: geminiStreamProvider.formatDisabledError,
  handleNonStreaming: geminiStreamProvider.handleNonStreaming,
  handleStreaming: geminiStreamProvider.handleStreaming,
};
