// File: src/services/API/SiteService.js

import ApiClient from "./ApiClient";

/**
 * SiteService - Handles WordPress Site Management API requests
 *
 * Backend API:
 * - POST /api/v1/sites (Create WordPress Site)
 * - GET /api/v1/sites (List WordPress Sites)
 * - GET /api/v1/sites/{id} (Get WordPress Site)
 * - DELETE /api/v1/sites/{id} (Delete WordPress Site)
 * - POST /api/v1/sites/{id}/rotate-api-key (Rotate Site API Key)
 *
 * Documentation: cloud/maplepress-backend/docs/API.md (lines 805-1085)
 *
 * Purpose: Manage WordPress sites and their API credentials for the MaplePress plugin.
 * Sites are scoped to tenants (determined from JWT token).
 */

/**
 * Create a new WordPress site and generate API credentials
 *
 * @param {Object} siteData - Site creation data
 * @param {string} siteData.siteUrl - Full WordPress site URL (e.g., https://example.com)
 * @returns {Promise<Object>} Created site data with API key
 * @throws {Error} If creation fails or validation errors occur
 *
 * Note: Backend automatically extracts the domain from siteUrl
 *
 * Response format (transformed to camelCase):
 * {
 *   id: string,                       // Site ID (UUID)
 *   domain: string,                   // Site domain (extracted by backend)
 *   siteUrl: string,                  // Full site URL
 *   apiKey: string,                   // API key (shown only once!)
 *   verificationToken: string,        // Token for DNS verification
 *   verificationInstructions: string, // DNS setup instructions
 *   status: string,                   // Site status (e.g., "pending")
 *   searchIndexName: string           // Meilisearch index name
 * }
 */
async function createSite(siteData) {
  // NO frontend validation - let backend handle all validation
  // This allows backend to return RFC 9457 validation errors

  // Backend will extract domain from site_url automatically
  // Prepare request body (snake_case for backend)
  // Send whatever the user provided, even if empty
  const requestBody = {
    site_url: siteData.siteUrl || "",
  };

  try {
    // Make authenticated API request
    const response = await ApiClient.post("/api/v1/sites", requestBody);

    // Transform response to camelCase for frontend
    return {
      id: response.id,
      domain: response.domain,
      siteUrl: response.site_url,
      apiKey: response.api_key,
      verificationToken: response.verification_token,
      verificationInstructions: response.verification_instructions,
      status: response.status,
      searchIndexName: response.search_index_name,
    };
  } catch (error) {
    // If error has RFC 9457 validation errors, preserve them
    if (error.validationErrors) {
      console.log("[SiteService] 📋 Preserving RFC 9457 validation errors:", error.validationErrors);
      // Re-throw the original error with validation data intact
      throw error;
    }

    // Map other backend errors to user-friendly messages
    const message = error.message?.toLowerCase() || "";

    if (message.includes("unauthorized") || message.includes("401")) {
      throw new Error(
        "Authentication required. Please log in to continue."
      );
    }

    if (message.includes("conflict") || message.includes("409") || message.includes("already registered")) {
      throw new Error(
        "Domain already registered by another user."
      );
    }

    // Generic error
    throw new Error(
      error.message || "Failed to create site. Please try again."
    );
  }
}

/**
 * List all WordPress sites for the authenticated user's tenant
 *
 * @param {Object} options - List options
 * @param {number} options.pageSize - Number of results per page (default: 20, max: 100)
 * @param {string} options.pageState - Pagination token from previous response
 * @returns {Promise<Object>} List of sites with pagination
 * @throws {Error} If retrieval fails
 *
 * Response format (transformed to camelCase):
 * {
 *   sites: Array<{
 *     id: string,
 *     domain: string,
 *     status: string,
 *     isVerified: boolean,
 *     createdAt: Date
 *   }>,
 *   pageState: string|null  // Pagination token for next page
 * }
 */
async function listSites(options = {}) {
  const { pageSize = 20, pageState } = options;

  // Validate page size
  if (pageSize < 1 || pageSize > 100) {
    throw new Error("Page size must be between 1 and 100");
  }

  try {
    // Build query parameters
    const params = {
      page_size: pageSize,
    };

    if (pageState) {
      params.page_state = pageState;
    }

    // Make authenticated GET request
    const response = await ApiClient.get("/api/v1/sites", { params });

    // Transform response to camelCase for frontend
    return {
      sites: response.sites.map(site => ({
        id: site.id,
        domain: site.domain,
        status: site.status,
        isVerified: site.is_verified,
        createdAt: new Date(site.created_at),
      })),
      pageState: response.page_state || null,
    };
  } catch (error) {
    // Map backend errors to user-friendly messages
    const message = error.message?.toLowerCase() || "";

    if (message.includes("unauthorized") || message.includes("401")) {
      throw new Error(
        "Authentication required. Please log in to continue."
      );
    }

    // Generic error
    throw new Error(
      error.message || "Failed to retrieve sites. Please try again."
    );
  }
}

/**
 * Get detailed information about a specific WordPress site
 *
 * @param {string} siteId - Site ID (UUID)
 * @returns {Promise<Object>} Detailed site data
 * @throws {Error} If retrieval fails or site not found
 *
 * Response format (transformed to camelCase):
 * {
 *   id: string,
 *   tenantId: string,
 *   domain: string,
 *   siteUrl: string,
 *   apiKeyPrefix: string,
 *   apiKeyLastFour: string,
 *   status: string,
 *   isVerified: boolean,
 *   searchIndexName: string,
 *   totalPagesIndexed: number,
 *   lastIndexedAt: Date,
 *   pluginVersion: string,
 *   storageUsedBytes: number,
 *   searchRequestsCount: number,
 *   monthlyPagesIndexed: number,
 *   lastResetAt: Date,
 *   createdAt: Date,
 *   updatedAt: Date
 * }
 */
async function getSiteById(siteId) {
  // Validate input
  if (!siteId || typeof siteId !== "string") {
    throw new Error("Site ID is required");
  }

  // Basic UUID validation
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
  if (!uuidPattern.test(siteId)) {
    throw new Error("Invalid site ID format");
  }

  try {
    // Make authenticated GET request
    const response = await ApiClient.get(`/api/v1/sites/${siteId}`);

    // Transform response to camelCase for frontend
    return {
      id: response.id,
      tenantId: response.tenant_id,
      domain: response.domain,
      siteUrl: response.site_url,
      apiKeyPrefix: response.api_key_prefix,
      apiKeyLastFour: response.api_key_last_four,
      status: response.status,
      isVerified: response.is_verified,
      searchIndexName: response.search_index_name,
      totalPagesIndexed: response.total_pages_indexed,
      lastIndexedAt: response.last_indexed_at ? new Date(response.last_indexed_at) : null,
      pluginVersion: response.plugin_version,
      storageUsedBytes: response.storage_used_bytes,
      searchRequestsCount: response.search_requests_count,
      monthlyPagesIndexed: response.monthly_pages_indexed,
      lastResetAt: response.last_reset_at ? new Date(response.last_reset_at) : null,
      createdAt: new Date(response.created_at),
      updatedAt: new Date(response.updated_at),
    };
  } catch (error) {
    // Map backend errors to user-friendly messages
    const message = error.message?.toLowerCase() || "";

    if (message.includes("unauthorized") || message.includes("401")) {
      throw new Error(
        "Authentication required. Please log in to continue."
      );
    }

    if (message.includes("not found") || message.includes("404")) {
      throw new Error("Site not found or doesn't belong to your organization.");
    }

    // Generic error
    throw new Error(
      error.message || "Failed to retrieve site. Please try again."
    );
  }
}

/**
 * Delete a WordPress site and all associated data
 *
 * @param {string} siteId - Site ID (UUID)
 * @returns {Promise<Object>} Deletion confirmation
 * @throws {Error} If deletion fails or site not found
 *
 * Response format:
 * {
 *   success: boolean,
 *   message: string
 * }
 */
async function deleteSite(siteId) {
  // Validate input
  if (!siteId || typeof siteId !== "string") {
    throw new Error("Site ID is required");
  }

  // Basic UUID validation
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
  if (!uuidPattern.test(siteId)) {
    throw new Error("Invalid site ID format");
  }

  try {
    // Make authenticated DELETE request
    const response = await ApiClient.delete(`/api/v1/sites/${siteId}`);

    return {
      success: response.success,
      message: response.message,
    };
  } catch (error) {
    // Map backend errors to user-friendly messages
    const message = error.message?.toLowerCase() || "";

    if (message.includes("unauthorized") || message.includes("401")) {
      throw new Error(
        "Authentication required. Please log in to continue."
      );
    }

    if (message.includes("not found") || message.includes("404")) {
      throw new Error("Site not found or doesn't belong to your organization.");
    }

    // Generic error
    throw new Error(
      error.message || "Failed to delete site. Please try again."
    );
  }
}

/**
 * Rotate a site's API key (use when the key is compromised)
 *
 * @param {string} siteId - Site ID (UUID)
 * @returns {Promise<Object>} New API key and rotation details
 * @throws {Error} If rotation fails or site not found
 *
 * Response format (transformed to camelCase):
 * {
 *   newApiKey: string,           // New API key (shown only once!)
 *   oldKeyLastFour: string,      // Last 4 chars of old key
 *   rotatedAt: Date              // Rotation timestamp
 * }
 */
async function rotateApiKey(siteId) {
  // Validate input
  if (!siteId || typeof siteId !== "string") {
    throw new Error("Site ID is required");
  }

  // Basic UUID validation
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
  if (!uuidPattern.test(siteId)) {
    throw new Error("Invalid site ID format");
  }

  try {
    // Make authenticated POST request
    const response = await ApiClient.post(`/api/v1/sites/${siteId}/rotate-api-key`);

    // Transform response to camelCase for frontend
    return {
      newApiKey: response.new_api_key,
      oldKeyLastFour: response.old_key_last_four,
      rotatedAt: new Date(response.rotated_at),
    };
  } catch (error) {
    // Map backend errors to user-friendly messages
    const message = error.message?.toLowerCase() || "";

    if (message.includes("unauthorized") || message.includes("401")) {
      throw new Error(
        "Authentication required. Please log in to continue."
      );
    }

    if (message.includes("not found") || message.includes("404")) {
      throw new Error("Site not found or doesn't belong to your organization.");
    }

    // Generic error
    throw new Error(
      error.message || "Failed to rotate API key. Please try again."
    );
  }
}

/**
 * Validate domain format
 *
 * @param {string} domain - Domain to validate
 * @returns {Object} { valid: boolean, error: string|null }
 */
function validateDomain(domain) {
  if (!domain || typeof domain !== "string") {
    return { valid: false, error: "Domain is required" };
  }

  const trimmedDomain = domain.trim();

  if (trimmedDomain.length === 0) {
    return { valid: false, error: "Domain cannot be empty" };
  }

  // Basic domain validation
  const domainPattern = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/i;
  if (!domainPattern.test(trimmedDomain)) {
    return { valid: false, error: "Invalid domain format" };
  }

  return { valid: true, error: null };
}

/**
 * Validate site URL format
 *
 * @param {string} url - URL to validate
 * @returns {Object} { valid: boolean, error: string|null }
 */
function validateSiteUrl(url) {
  if (!url || typeof url !== "string") {
    return { valid: false, error: "Site URL is required" };
  }

  const trimmedUrl = url.trim();

  if (trimmedUrl.length === 0) {
    return { valid: false, error: "Site URL cannot be empty" };
  }

  // Validate URL format
  try {
    const parsedUrl = new URL(trimmedUrl);

    // Must be http or https
    if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
      return { valid: false, error: "Site URL must use http or https protocol" };
    }

    return { valid: true, error: null };
  } catch (error) {
    return { valid: false, error: "Invalid URL format" };
  }
}

/**
 * Format storage bytes to human-readable format
 *
 * @param {number} bytes - Storage in bytes
 * @returns {string} Formatted string (e.g., "50 MB")
 */
function formatStorage(bytes) {
  if (bytes === 0) return "0 Bytes";

  const k = 1024;
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
}

// Export service
const SiteService = {
  createSite,
  listSites,
  getSiteById,
  deleteSite,
  rotateApiKey,
  validateDomain,
  validateSiteUrl,
  formatStorage,
};

export default SiteService;
