/**
 * URL Validator
 * Validates and sanitizes social media URLs
 */

import { Platform, SUPPORTED_DOMAINS } from "@/types/download";

export interface ValidationResult {
  valid: boolean;
  error?: string;
  sanitizedUrl?: string;
  platform?: Platform;
}

const DANGEROUS_PATTERNS = [
  /javascript:/i,
  /data:/i,
  /vbscript:/i,
  /file:/i,
  /about:/i,
  /blob:/i,
  /\s+/g, // Whitespace
  /<[^>]*>/g, // HTML tags
  /%3C/gi, // Encoded <
  /%3E/gi, // Encoded >
  /%22/gi, // Encoded "
  /%27/gi, // Encoded '
];

/**
 * Validates a social media URL
 * @param url - The URL to validate
 * @returns ValidationResult with validation status and sanitized URL
 */
export function validateUrl(url: string): ValidationResult {
  // 1. Check if URL is provided
  if (!url || typeof url !== "string") {
    return { valid: false, error: "URL is required" };
  }

  // 2. Trim whitespace
  let sanitizedUrl = url.trim();

  // 3. Check for dangerous patterns (XSS prevention)
  for (const pattern of DANGEROUS_PATTERNS) {
    if (pattern.test(sanitizedUrl)) {
      return { valid: false, error: "Invalid URL format" };
    }
  }

  // 4. Add protocol if missing
  if (
    !sanitizedUrl.startsWith("http://") &&
    !sanitizedUrl.startsWith("https://")
  ) {
    sanitizedUrl = "https://" + sanitizedUrl;
  }

  // 5. Parse and validate URL structure
  let parsedUrl: URL;
  try {
    parsedUrl = new URL(sanitizedUrl);
  } catch {
    return { valid: false, error: "Invalid URL format" };
  }

  // 6. Enforce HTTPS only
  if (parsedUrl.protocol !== "https:") {
    // Allow http for localhost development
    if (!parsedUrl.hostname.includes("localhost")) {
      return { valid: false, error: "Only HTTPS URLs are allowed" };
    }
  }

  // 7. Check for valid hostname
  if (!parsedUrl.hostname || parsedUrl.hostname.length < 3) {
    return { valid: false, error: "Invalid hostname" };
  }

  // 8. Check against supported domains
  const hostname = parsedUrl.hostname.toLowerCase().replace("www.", "");
  let detectedPlatform: Platform | null = null;

  for (const [platform, domains] of Object.entries(SUPPORTED_DOMAINS) as [
    Platform,
    string[],
  ][]) {
    if (platform === "unknown") continue;

    for (const domain of domains) {
      if (hostname === domain || hostname.endsWith("." + domain)) {
        detectedPlatform = platform;
        break;
      }
    }
    if (detectedPlatform) break;
  }

  if (!detectedPlatform) {
    return {
      valid: false,
      error:
        "Unsupported platform. Supported: YouTube, Instagram, TikTok, Twitter/X, Facebook",
    };
  }

  // 9. Final sanitization
  sanitizedUrl = parsedUrl.toString();

  return {
    valid: true,
    sanitizedUrl,
    platform: detectedPlatform,
  };
}

/**
 * Sanitizes a URL by removing potentially dangerous characters
 */
export function sanitizeUrl(url: string): string {
  return url
    .trim()
    .replace(/\s+/g, "")
    .replace(/<[^>]*>/g, "")
    .replace(/javascript:/gi, "")
    .replace(/data:/gi, "")
    .replace(/vbscript:/gi, "");
}

/**
 * Checks if URL appears to be a valid social media video URL
 */
export function isVideoUrl(url: string): boolean {
  const videoPatterns = [
    /youtube\.com\/watch\?v=[\w-]+/i,
    /youtu\.be\/[\w-]+/i,
    /youtube\.com\/shorts\/[\w-]+/i,
    /instagram\.com\/reel\/[\w-]+/i,
    /instagram\.com\/tv\/[\w-]+/i,
    /tiktok\.com\/@[\w.]+\/video\/\d+/i,
    /vm\.tiktok\.com\/[\w-]+/i,
    /twitter\.com\/\w+\/status\/\d+/i,
    /x\.com\/\w+\/status\/\d+/i,
    /facebook\.com\/.*\/videos\/\d+/i,
    /fb\.watch\/[\w-]+/i,
  ];

  return videoPatterns.some((pattern) => pattern.test(url));
}

/**
 * Extracts video ID from URL (platform-specific)
 */
export function extractVideoId(url: string, platform: Platform): string | null {
  try {
    const urlObj = new URL(url);

    switch (platform) {
      case "youtube": {
        // youtu.be/VIDEO_ID
        if (urlObj.hostname === "youtu.be") {
          return urlObj.pathname.slice(1);
        }
        // youtube.com/watch?v=VIDEO_ID
        const vParam = urlObj.searchParams.get("v");
        if (vParam) return vParam;
        // youtube.com/shorts/VIDEO_ID
        if (urlObj.pathname.startsWith("/shorts/")) {
          return urlObj.pathname.replace("/shorts/", "");
        }
        return null;
      }

      case "instagram": {
        // instagram.com/p/POST_ID or /reel/REEL_ID
        const match = urlObj.pathname.match(/\/(p|reel|tv)\/([\w-]+)/);
        return match ? match[2] : null;
      }

      case "tiktok": {
        // tiktok.com/@user/video/VIDEO_ID
        const match = urlObj.pathname.match(/\/video\/(\d+)/);
        return match ? match[1] : null;
      }

      case "twitter": {
        // twitter.com/user/status/TWEET_ID
        const match = urlObj.pathname.match(/\/status\/(\d+)/);
        return match ? match[1] : null;
      }

      case "facebook": {
        // facebook.com/.../videos/VIDEO_ID
        const match = urlObj.pathname.match(/\/videos\/(\d+)/);
        return match ? match[1] : null;
      }

      default:
        return null;
    }
  } catch {
    return null;
  }
}
