/**
 * Shop Data API - Unified REST API for E-commerce Data Access (Internal + User API Keys)
 *
 * Provides real-time access to customer, order, and product data from ALL connected
 * webshops using internal (non-user-based) API keys OR user-based API keys.
 *
 * Internal API Keys: System-level access to all webshops (not tied to specific user)
 * User API Keys: User-specific access (existing functionality)
 *
 * Related: Issue #50 - Implement non user based API keys
 *
 * Authentication: API Key (Bearer token)
 * - int_shopcall_xxx (internal keys - access all shops)
 * - api_shopcall_xxx (user keys - access only user's shops)
 *
 * Rate Limit: 200 requests/minute (internal), 100 requests/minute (user)
 *
 * Endpoints:
 * - GET /shop-data-api/stores - List all stores (internal only) or user's stores
 * - GET /shop-data-api/customers?store_id={uuid}&page=1&limit=25
 * - GET /shop-data-api/customers/{id}?store_id={uuid}
 * - GET /shop-data-api/orders?store_id={uuid}&status=completed&page=1
 * - GET /shop-data-api/orders/{id}?store_id={uuid}
 * - GET /shop-data-api/products?store_id={uuid}&page=1
 * - GET /shop-data-api/products/{id}?store_id={uuid}
 */

import { createClient } from "https://esm.sh/@supabase/supabase-js@2.39.7";
import { wrapHandler } from "../_shared/error-handler.ts";

// Import authentication for both API key types
import {
  requireApiKey,
  createApiKeyErrorResponse,
  addRateLimitHeaders,
  extractApiKey,
} from "../_shared/api-key-auth.ts";

import {
  requireInternalApiKey,
  createInternalApiKeyErrorResponse,
  addInternalRateLimitHeaders,
  extractInternalApiKey,
} from "../_shared/internal-api-key-auth.ts";

import { getAdapters } from "../_shared/platform-adapters.ts";
import {
  createSuccessResponse,
  createListResponse,
  createErrorResponse,
  toHttpResponse,
  calculateHasMore,
  generateRequestId,
  type UnifiedApiResponse,
} from "../_shared/unified-response.ts";

// Import platform-specific clients
import * as ShopifyClient from "../_shared/shopify-client.ts";
import * as WooCommerceClient from "../_shared/woocommerce-client.ts";
import * as ShopRenterClient from "../_shared/shoprenter-client.ts";

const FUNCTION_NAME = "shop-data-api";

interface AuthContext {
  type: "user" | "internal";
  userId?: string; // Only for user API keys
  apiKey: string;
}

/**
 * Authenticate request with either user or internal API key
 */
async function authenticateRequest(
  req: Request,
  supabaseAdmin: any
): Promise<{ context: AuthContext | null; errorResponse: Response | null }> {
  // Try internal API key first (int_shopcall_xxx)
  const internalKey = extractInternalApiKey(req);
  if (internalKey) {
    const result = await requireInternalApiKey(req, supabaseAdmin);
    if (!result.valid) {
      return { context: null, errorResponse: createInternalApiKeyErrorResponse(result) };
    }
    return {
      context: { type: "internal", apiKey: internalKey },
      errorResponse: null,
    };
  }

  // Try user API key (api_shopcall_xxx)
  const userKey = extractApiKey(req);
  if (userKey) {
    const result = await requireApiKey(req, supabaseAdmin, "webshop_data");
    if (!result.valid) {
      return { context: null, errorResponse: createApiKeyErrorResponse(result) };
    }
    return {
      context: { type: "user", userId: result.userId!, apiKey: userKey },
      errorResponse: null,
    };
  }

  // No valid API key found
  return {
    context: null,
    errorResponse: new Response(
      JSON.stringify({
        error: "Missing API key. Provide either int_shopcall_xxx or api_shopcall_xxx",
        code: "MISSING_API_KEY",
      }),
      { status: 401, headers: { "Content-Type": "application/json" } }
    ),
  };
}

/**
 * Main handler function
 */
async function handler(req: Request): Promise<Response> {
  const supabaseUrl = Deno.env.get("SUPABASE_URL");
  const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");

  if (!supabaseUrl || !supabaseServiceKey) {
    return new Response(
      JSON.stringify({ error: "Server configuration error" }),
      { status: 500, headers: { "Content-Type": "application/json" } }
    );
  }

  const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey);

  // Only allow GET requests
  if (req.method !== "GET") {
    return createErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", undefined, 405);
  }

  // Authenticate request
  const { context, errorResponse } = await authenticateRequest(req, supabaseAdmin);
  if (errorResponse) {
    return errorResponse;
  }

  const authContext = context!;

  // Parse URL and query parameters
  const url = new URL(req.url);
  const pathParts = url.pathname.split("/").filter((p) => p);

  // Expected path: /shop-data-api/{resource}/{id?}
  if (pathParts[0] !== "shop-data-api") {
    return createErrorResponse("INVALID_ENDPOINT", "Invalid endpoint", undefined, 404);
  }

  const resource = pathParts[1]; // 'stores', 'customers', 'orders', or 'products'
  const resourceId = pathParts[2]; // Optional ID

  // Handle special endpoint: list stores
  if (resource === "stores") {
    const response = await handleListStores(supabaseAdmin, authContext);
    return addRateLimitHeadersToResponse(response, authContext);
  }

  // Get query parameters
  const storeId = url.searchParams.get("store_id");
  const page = parseInt(url.searchParams.get("page") || "1");
  const limit = parseInt(url.searchParams.get("limit") || "25");
  const status = url.searchParams.get("status"); // For orders

  // Validate required parameters
  if (!storeId) {
    return createErrorResponse(
      "MISSING_STORE_ID",
      "Missing required parameter: store_id",
      undefined,
      400
    );
  }

  if (!["customers", "orders", "products"].includes(resource)) {
    return createErrorResponse(
      "INVALID_RESOURCE",
      "Invalid resource. Must be stores, customers, orders, or products",
      undefined,
      400
    );
  }

  // Validate pagination parameters
  if (page < 1 || limit < 1 || limit > 100) {
    return createErrorResponse(
      "INVALID_PAGINATION",
      "Invalid pagination parameters. Page must be >= 1, limit must be 1-100",
      undefined,
      400
    );
  }

  // Fetch store and verify access (include sync config for access policies)
  let storeQuery = supabaseAdmin
    .from("stores")
    .select(`
      *,
      store_sync_config (
        products_access_policy,
        customers_access_policy,
        orders_access_policy
      )
    `)
    .eq("id", storeId)
    .eq("is_active", true);

  // For user API keys, restrict to user's stores
  if (authContext.type === "user") {
    storeQuery = storeQuery.eq("user_id", authContext.userId);
  }

  const { data: store, error: storeError } = await storeQuery.single();

  if (storeError || !store) {
    return createErrorResponse(
      "STORE_NOT_FOUND",
      "Store not found or access denied",
      undefined,
      404
    );
  }

  // Check data access policies (only for user keys, internal keys have full access)
  if (authContext.type === "user") {
    const syncConfig = store.store_sync_config?.[0] || {};
    const policyKey = `${resource.slice(0, -1)}s_access_policy`; // customers_access_policy, orders_access_policy, products_access_policy
    const policy = syncConfig[policyKey] || 'not_allowed';

    if (policy === 'not_allowed') {
      return createErrorResponse(
        "ACCESS_DENIED",
        `Access to ${resource} is not enabled for this store`,
        { hint: "Enable access in store settings" },
        403
      );
    }
  }

  // Fetch data based on resource and platform
  let responseData: UnifiedApiResponse<any>;

  try {
    switch (store.platform_name.toLowerCase()) {
      case "shopify":
        responseData = await fetchShopifyData(
          store,
          resource,
          resourceId,
          page,
          limit,
          status,
          authContext
        );
        break;
      case "woocommerce":
        responseData = await fetchWooCommerceData(
          store,
          resource,
          resourceId,
          page,
          limit,
          status,
          authContext
        );
        break;
      case "shoprenter":
        responseData = await fetchShopRenterData(
          store,
          resource,
          resourceId,
          page,
          limit,
          status,
          authContext
        );
        break;
      default:
        return createErrorResponse(
          "UNSUPPORTED_PLATFORM",
          `Unsupported platform: ${store.platform_name}`,
          undefined,
          400
        );
    }

    const response = toHttpResponse(responseData, 200);

    // Add rate limit headers
    return addRateLimitHeadersToResponse(response, authContext);
  } catch (error) {
    console.error(`Error fetching ${resource}:`, error);

    return createErrorResponse(
      "FETCH_ERROR",
      error instanceof Error ? error.message : "Failed to fetch data",
      error instanceof Error ? { stack: error.stack } : undefined,
      500
    );
  }
}

/**
 * Handle listing stores
 */
async function handleListStores(
  supabaseAdmin: any,
  authContext: AuthContext
): Promise<Response> {
  const query = supabaseAdmin
    .from("stores")
    .select("id, store_name, store_url, platform_name, is_active, connected_at, sync_status, user_id")
    .eq("is_active", true);

  // For user API keys, only show user's stores
  if (authContext.type === "user") {
    query.eq("user_id", authContext.userId);
  }

  const { data: stores, error } = await query;

  if (error) {
    return createErrorResponse(
      "FETCH_ERROR",
      "Failed to fetch stores",
      error,
      500
    );
  }

  const response = createListResponse(
    stores,
    {
      resource_type: "stores",
      auth_type: authContext.type,
      fetched_at: new Date().toISOString(),
      request_id: generateRequestId(),
    },
    {
      page: 1,
      limit: stores.length,
      total: stores.length,
      has_more: false,
    }
  );

  return toHttpResponse(response, 200);
}

/**
 * Add appropriate rate limit headers based on auth context
 */
function addRateLimitHeadersToResponse(response: Response, authContext: AuthContext): Response {
  if (authContext.type === "internal") {
    return addInternalRateLimitHeaders(response, authContext.apiKey);
  } else {
    return addRateLimitHeaders(response, authContext.apiKey);
  }
}

/**
 * Fetch data from Shopify
 */
async function fetchShopifyData(
  store: any,
  resource: string,
  resourceId: string | undefined,
  page: number,
  limit: number,
  status: string | null,
  authContext: AuthContext
): Promise<UnifiedApiResponse<any>> {
  const adapters = getAdapters("shopify");

  if (resourceId) {
    // Fetch single item
    const itemId = parseInt(resourceId);
    let data;

    if (resource === "customers") {
      const response = await ShopifyClient.shopifyApiRequest(
        store.id,
        `/customers/${itemId}.json`
      );
      data = adapters.customer(response.customer);
    } else if (resource === "orders") {
      const response = await ShopifyClient.shopifyApiRequest(
        store.id,
        `/orders/${itemId}.json`
      );
      data = adapters.order(response.order);
    } else if (resource === "products") {
      const response = await ShopifyClient.shopifyApiRequest(
        store.id,
        `/products/${itemId}.json`
      );
      data = adapters.product(response.product);
    }

    return createSuccessResponse(data, {
      platform: "shopify",
      store_id: store.id,
      resource_type: resource as any,
      auth_type: authContext.type,
      fetched_at: new Date().toISOString(),
      request_id: generateRequestId(),
    });
  } else {
    // Fetch list
    const sinceId = page > 1 ? undefined : undefined; // Shopify uses since_id for pagination
    let data;
    let rawData;

    if (resource === "customers") {
      rawData = await ShopifyClient.fetchCustomers(store.id, limit, sinceId);
      data = rawData.map((item: any) => adapters.customer(item));
    } else if (resource === "orders") {
      let endpoint = `/orders.json?limit=${limit}&status=${status || "any"}`;
      const response = await ShopifyClient.shopifyApiRequest(store.id, endpoint);
      rawData = response.orders || [];
      data = rawData.map((item: any) => adapters.order(item));
    } else if (resource === "products") {
      rawData = await ShopifyClient.fetchProducts(store.id, limit, sinceId);
      data = rawData.map((item: any) => adapters.product(item));
    }

    return createListResponse(
      data,
      {
        platform: "shopify",
        store_id: store.id,
        resource_type: resource as any,
        auth_type: authContext.type,
        fetched_at: new Date().toISOString(),
        request_id: generateRequestId(),
      },
      {
        page,
        limit,
        has_more: calculateHasMore(rawData?.length || 0, limit),
      }
    );
  }
}

/**
 * Fetch data from WooCommerce
 */
async function fetchWooCommerceData(
  store: any,
  resource: string,
  resourceId: string | undefined,
  page: number,
  limit: number,
  status: string | null,
  authContext: AuthContext
): Promise<UnifiedApiResponse<any>> {
  const adapters = getAdapters("woocommerce");

  if (resourceId) {
    // Fetch single item
    const itemId = parseInt(resourceId);
    let data;

    if (resource === "customers") {
      const rawData = await WooCommerceClient.fetchCustomer(store.id, itemId);
      data = adapters.customer(rawData);
    } else if (resource === "orders") {
      const rawData = await WooCommerceClient.fetchOrder(store.id, itemId);
      data = adapters.order(rawData);
    } else if (resource === "products") {
      const rawData = await WooCommerceClient.fetchProduct(store.id, itemId);
      data = adapters.product(rawData);
    }

    return createSuccessResponse(data, {
      platform: "woocommerce",
      store_id: store.id,
      resource_type: resource as any,
      auth_type: authContext.type,
      fetched_at: new Date().toISOString(),
      request_id: generateRequestId(),
    });
  } else {
    // Fetch list
    let data;
    let rawData;

    if (resource === "customers") {
      rawData = await WooCommerceClient.fetchCustomers(store.id, page, limit);
      data = rawData.map((item: any) => adapters.customer(item));
    } else if (resource === "orders") {
      rawData = await WooCommerceClient.fetchOrders(
        store.id,
        page,
        limit,
        status || undefined
      );
      data = rawData.map((item: any) => adapters.order(item));
    } else if (resource === "products") {
      rawData = await WooCommerceClient.fetchProducts(store.id, page, limit);
      data = rawData.map((item: any) => adapters.product(item));
    }

    return createListResponse(
      data,
      {
        platform: "woocommerce",
        store_id: store.id,
        resource_type: resource as any,
        auth_type: authContext.type,
        fetched_at: new Date().toISOString(),
        request_id: generateRequestId(),
      },
      {
        page,
        limit,
        has_more: calculateHasMore(rawData?.length || 0, limit),
      }
    );
  }
}

/**
 * Fetch data from ShopRenter
 */
async function fetchShopRenterData(
  store: any,
  resource: string,
  resourceId: string | undefined,
  page: number,
  limit: number,
  status: string | null,
  authContext: AuthContext
): Promise<UnifiedApiResponse<any>> {
  const adapters = getAdapters("shoprenter");

  if (resourceId) {
    // Fetch single item - ShopRenter client doesn't have individual fetch methods
    // So we'll fetch the list and filter (or implement individual fetches)
    throw new Error("Single item fetch not yet implemented for ShopRenter");
  } else {
    // Fetch list
    let data;
    let rawData;

    // ShopRenter uses 0-based pagination, so convert from 1-based (page 1 -> 0, page 2 -> 1, etc.)
    const shopRenterPage = Math.max(0, page - 1);

    if (resource === "customers") {
      const response = await ShopRenterClient.fetchCustomers(store.id, shopRenterPage, limit);
      rawData = response.items || [];
      data = rawData.map((item: any) => adapters.customer(item));
    } else if (resource === "orders") {
      const response = await ShopRenterClient.fetchOrders(store.id, shopRenterPage, limit);
      rawData = response.items || [];
      data = rawData.map((item: any) => adapters.order(item));
    } else if (resource === "products") {
      const response = await ShopRenterClient.fetchProducts(store.id, shopRenterPage, limit);
      rawData = response.items || [];
      data = rawData.map((item: any) => adapters.product(item));
    }

    return createListResponse(
      data,
      {
        platform: "shoprenter",
        store_id: store.id,
        resource_type: resource as any,
        auth_type: authContext.type,
        fetched_at: new Date().toISOString(),
        request_id: generateRequestId(),
      },
      {
        page,
        limit,
        has_more: calculateHasMore(rawData?.length || 0, limit),
      }
    );
  }
}

// Wrap handler with error handling
Deno.serve(wrapHandler(FUNCTION_NAME, handler));
