// Reusable URL validator
function isValidHttpUrl(urlString) {
  try {
    const url = new URL(urlString);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch (_) {
    return false;
  }
}

// Reusable Base URL normalizer
function normalizeBaseUrl(url) {
  let normalized = url.trim();
  if (normalized.endsWith('/')) {
    normalized = normalized.slice(0, -1);
  }
  return normalized;
}

// Extract first URL from highlighted text
function extractFirstUrlFromText(text) {
  if (!text) return null;
  const urlRegex = /(https?:\/\/[^\s]+)/gi;
  const match = text.match(urlRegex);
  if (match && match.length > 0) {
    let url = match[0];
    // Strip trailing common punctuation
    url = url.replace(/[.,;:!?)]+$/, '');
    return url;
  }
  return null;
}

// Determine target URL from context info
function getTargetUrlFromContext(info, tab) {
  if (info.linkUrl) return info.linkUrl;
  if (info.selectionText) {
    return extractFirstUrlFromText(info.selectionText);
  }
  if (info.srcUrl) return info.srcUrl;
  return info.pageUrl || tab?.url;
}

// Safe JSON parser to strip PHP errors/warnings prepended to JSON responses
function parseSafeJson(text) {
  try {
    return JSON.parse(text);
  } catch (err) {
    const jsonStartIndex = text.indexOf('{');
    const jsonEndIndex = text.lastIndexOf('}');
    if (jsonStartIndex !== -1 && jsonEndIndex !== -1 && jsonEndIndex > jsonStartIndex) {
      const potentialJson = text.substring(jsonStartIndex, jsonEndIndex + 1);
      try {
        return JSON.parse(potentialJson);
      } catch (nestedErr) {
        console.debug('Failed to parse extracted JSON:', nestedErr);
      }
    }
    
    if (text.includes('Warning:') || text.includes('Notice:') || text.includes('Fatal error:') || text.includes('Error:')) {
      throw new Error('Server returned invalid response (PHP errors or warnings prepended).');
    }
    
    throw new Error('Server returned invalid JSON format.');
  }
}

// Map to store generated short URLs for notification click handler
const notificationUrls = new Map();

// Helper to show Chrome notification and track click-through URLs
function showNotification(title, message, clickUrl = null) {
  const notificationId = 'jkz-notification-' + Date.now() + '-' + Math.random().toString(36).slice(2, 11);
  
  if (clickUrl) {
    notificationUrls.set(notificationId, clickUrl);
    // Cleanup old keys after 5 minutes
    setTimeout(() => {
      notificationUrls.delete(notificationId);
    }, 5 * 60 * 1000);
  }
  
  chrome.notifications.create(notificationId, {
    type: 'basic',
    iconUrl: 'icon128.png',
    title: title,
    message: message,
    priority: 1,
    buttons: [
      { title: 'Open short link' },
      { title: 'Open dashboard' }
    ]
  });
}

// Copy to clipboard using offscreen document in MV3
async function copyToClipboard(text) {
  try {
    const hasDocument = await chrome.offscreen.hasDocument();
    if (hasDocument) {
      await chrome.offscreen.closeDocument();
    }
  } catch (_) {
    // ignore
  }

  try {
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: [chrome.offscreen.Reason.CLIPBOARD],
      justification: 'Copy shortened URL to clipboard.'
    });
  } catch (err) {
    console.error('Failed to create offscreen document:', err);
    return false;
  }
  
  try {
    const response = await chrome.runtime.sendMessage({
      target: 'offscreen-doc',
      type: 'copy-to-clipboard',
      data: text
    });
    return response?.success;
  } catch (err) {
    console.error('Message to offscreen document failed:', err);
    return false;
  } finally {
    try {
      await chrome.offscreen.closeDocument();
    } catch (_) {
      // ignore
    }
  }
}

// Duplicate cache prevention settings (10 minutes)
const DUPLICATE_CACHE_MINUTES = 10;

// Save to local recent history (max 10)
async function saveRecentLink(originalUrl, shortUrl, source) {
  const timestamp = Date.now();
  
  // Update last link info
  await chrome.storage.local.set({
    last_short_link: shortUrl,
    last_short_link_created_at: timestamp,
    last_short_link_original_url: originalUrl
  });

  // Update rolling history
  let { recent_links } = await chrome.storage.local.get(['recent_links']);
  if (!Array.isArray(recent_links)) {
    recent_links = [];
  }
  
  recent_links.unshift({
    short_url: shortUrl,
    original_url: originalUrl,
    created_at: timestamp,
    source: source
  });
  
  if (recent_links.length > 10) {
    recent_links = recent_links.slice(0, 10);
  }
  
  await chrome.storage.local.set({ recent_links });
}

// Find existing matching recent link within duplicate window
async function findRecentLink(originalUrl) {
  const { recent_links } = await chrome.storage.local.get(['recent_links']);
  if (!Array.isArray(recent_links)) return null;
  
  const now = Date.now();
  const existing = recent_links.find(link => link.original_url === originalUrl);
  if (existing) {
    const elapsedMinutes = (now - existing.created_at) / (1000 * 60);
    if (elapsedMinutes <= DUPLICATE_CACHE_MINUTES) {
      return existing.short_url;
    }
  }
  return null;
}

// Background shortening execution
async function handleShortenRequest(url, source) {
  if (!url) {
    showNotification('JKZ Network Error', 'No URL selected to shorten.');
    return;
  }
  
  if (!isValidHttpUrl(url)) {
    showNotification('JKZ Network Error', 'This URL cannot be shortened. It must start with http:// or https://');
    return;
  }

  // Check duplicate prevention cache
  const existingShortUrl = await findRecentLink(url);
  if (existingShortUrl) {
    const copySuccess = await copyToClipboard(existingShortUrl);
    if (copySuccess) {
      showNotification('JKZ Network', `Existing short link copied: ${existingShortUrl}`, existingShortUrl);
    } else {
      showNotification('JKZ Network', `Existing short link found, but clipboard copy failed: ${existingShortUrl}`, existingShortUrl);
    }
    return;
  }
  
  // Retrieve settings
  const { api_url, api_key } = await chrome.storage.local.get(['api_url', 'api_key']);
  if (!api_url || !api_key) {
    showNotification('JKZ Network Error', 'JKZ Network is not configured. Open the extension settings and add your Base Site URL and API key.');
    return;
  }
  
  const baseUrl = normalizeBaseUrl(api_url);
  
  try {
    const params = new URLSearchParams();
    params.append('type', 'link');
    params.append('location_url', url);
    
    const response = await fetch(`${baseUrl}/api/links`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${api_key}`,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
      },
      body: params
    });
    
    if (response.status === 404) {
      showNotification('JKZ Network Error', 'Short link API endpoint was not found.');
      return;
    }
    
    const text = await response.text();
    let data;
    try {
      data = parseSafeJson(text);
    } catch (jsonErr) {
      showNotification('JKZ Network Error', 'The server returned an invalid API response.');
      return;
    }
    
    if (response.ok && data?.data?.url) {
      const shortUrl = `${baseUrl}/${data.data.url}`;
      
      // Save to recent links
      await saveRecentLink(url, shortUrl, source);
      
      // Copy to clipboard
      const copySuccess = await copyToClipboard(shortUrl);
      if (copySuccess) {
        showNotification('JKZ Network', `Short link copied: ${shortUrl}`, shortUrl);
      } else {
        showNotification('JKZ Network', `Short link created, but clipboard copy failed: ${shortUrl}`, shortUrl);
      }
    } else {
      let errMsg = 'Failed to shorten link.';
      if (data?.errors?.[0]?.title) {
        errMsg = data.errors[0].title;
        if (errMsg.includes('limits of your current plan')) {
          errMsg = 'Your account cannot create more short links right now.';
        } else if (errMsg === 'This custom URL already exists.') {
          errMsg = 'This custom alias is already taken.';
        } else if (errMsg.includes("Maybe you're missing the https://") || errMsg.includes('invalid format')) {
          errMsg = 'The destination URL is invalid.';
        }
      }
      showNotification('JKZ Network Error', errMsg);
    }
  } catch (err) {
    console.error('Background API Shorten error:', err);
    showNotification('JKZ Network Error', 'Network error. Check your Base Site URL and connection.');
  }
}

// Context Menu clicks listener
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  const { api_url } = await chrome.storage.local.get(['api_url']);
  const baseUrl = api_url ? normalizeBaseUrl(api_url) : '';

  switch (info.menuItemId) {
    case 'jkz-shorten-page': {
      const url = info.pageUrl || tab?.url;
      handleShortenRequest(url, 'context_menu');
      break;
    }
    case 'jkz-shorten-link': {
      handleShortenRequest(info.linkUrl, 'context_menu');
      break;
    }
    case 'jkz-shorten-selection': {
      const selectedText = info.selectionText;
      const url = extractFirstUrlFromText(selectedText);
      if (!url) {
        showNotification('JKZ Network Error', 'No valid URL found in the selected text.');
        return;
      }
      
      const urlRegex = /(https?:\/\/[^\s]+)/gi;
      const matches = selectedText.match(urlRegex);
      if (matches && matches.length > 1) {
        showNotification('JKZ Network', 'Multiple URLs found. Only the first one will be shortened.');
      }
      
      handleShortenRequest(url, 'context_menu');
      break;
    }
    case 'jkz-shorten-image': {
      if (!info.srcUrl) {
        showNotification('JKZ Network Error', 'No image URL found.');
        return;
      }
      handleShortenRequest(info.srcUrl, 'context_menu');
      break;
    }
    case 'jkz-shorten-media': {
      if (!info.srcUrl) {
        showNotification('JKZ Network Error', 'No media URL found.');
        return;
      }
      handleShortenRequest(info.srcUrl, 'context_menu');
      break;
    }
    case 'jkz-shorten-and-qr': {
      const url = getTargetUrlFromContext(info, tab);
      if (!url) {
        showNotification('JKZ Network Error', 'No URL found to shorten.');
        return;
      }
      if (!isValidHttpUrl(url)) {
        showNotification('JKZ Network Error', 'This URL cannot be shortened. It must start with http:// or https://');
        return;
      }
      // Open advanced options window and trigger auto-submit and QR checkbox
      chrome.windows.create({
        url: `context-shortener.html?url=${encodeURIComponent(url)}&auto=1&qr=1`,
        type: 'popup',
        width: 420,
        height: 560
      });
      break;
    }
    case 'jkz-shorten-with-options': {
      const url = getTargetUrlFromContext(info, tab);
      if (!url) {
        showNotification('JKZ Network Error', 'No URL found to shorten.');
        return;
      }
      if (!isValidHttpUrl(url)) {
        showNotification('JKZ Network Error', 'This URL cannot be shortened. It must start with http:// or https://');
        return;
      }
      // Open advanced options window
      chrome.windows.create({
        url: `context-shortener.html?url=${encodeURIComponent(url)}`,
        type: 'popup',
        width: 420,
        height: 560
      });
      break;
    }
    case 'jkz-copy-last-short-link': {
      const { last_short_link } = await chrome.storage.local.get(['last_short_link']);
      if (last_short_link) {
        const copySuccess = await copyToClipboard(last_short_link);
        if (copySuccess) {
          showNotification('JKZ Network', `Last short link copied: ${last_short_link}`, last_short_link);
        } else {
          showNotification('JKZ Network Error', 'Failed to copy last short link.');
        }
      } else {
        showNotification('JKZ Network', 'No short link history yet.');
      }
      break;
    }
    case 'jkz-open-dashboard': {
      if (baseUrl) {
        chrome.tabs.create({ url: `${baseUrl}/dashboard` });
      } else {
        showNotification('JKZ Network Error', 'JKZ Network is not configured. Open the extension settings and add your Base Site URL.');
      }
      break;
    }
  }
});

// Create parent-submenu items on install or update
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.removeAll(() => {
    // Parent root menu
    chrome.contextMenus.create({
      id: 'jkz-root-menu',
      title: 'JKZ Network',
      contexts: ['all']
    });
    
    // Submenu items
    chrome.contextMenus.create({
      id: 'jkz-shorten-page',
      parentId: 'jkz-root-menu',
      title: 'Shorten this page',
      contexts: ['page']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-link',
      parentId: 'jkz-root-menu',
      title: 'Shorten this link',
      contexts: ['link']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-selection',
      parentId: 'jkz-root-menu',
      title: 'Shorten selected URL',
      contexts: ['selection']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-image',
      parentId: 'jkz-root-menu',
      title: 'Shorten image URL',
      contexts: ['image']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-media',
      parentId: 'jkz-root-menu',
      title: 'Shorten media URL',
      contexts: ['video', 'audio']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-and-qr',
      parentId: 'jkz-root-menu',
      title: 'Shorten and generate QR',
      contexts: ['page', 'link', 'selection', 'image', 'video', 'audio']
    });
    chrome.contextMenus.create({
      id: 'jkz-shorten-with-options',
      parentId: 'jkz-root-menu',
      title: 'Shorten with options...',
      contexts: ['page', 'link', 'selection', 'image', 'video', 'audio']
    });
    chrome.contextMenus.create({
      id: 'jkz-copy-last-short-link',
      parentId: 'jkz-root-menu',
      title: 'Copy last short link',
      contexts: ['all']
    });
    chrome.contextMenus.create({
      id: 'jkz-open-dashboard',
      parentId: 'jkz-root-menu',
      title: 'Open JKZ Network dashboard',
      contexts: ['all']
    });
  });
});

// Click listener for Chrome notifications
chrome.notifications.onClicked.addListener((notificationId) => {
  const url = notificationUrls.get(notificationId);
  if (url) {
    chrome.tabs.create({ url: url });
    notificationUrls.delete(notificationId);
  }
});

// Click listener for Chrome notifications button actions
chrome.notifications.onButtonClicked.addListener(async (notificationId, buttonIndex) => {
  const url = notificationUrls.get(notificationId);
  if (buttonIndex === 0) {
    if (url) {
      chrome.tabs.create({ url: url });
    }
  } else if (buttonIndex === 1) {
    const { api_url } = await chrome.storage.local.get(['api_url']);
    if (api_url) {
      const baseUrl = normalizeBaseUrl(api_url);
      chrome.tabs.create({ url: `${baseUrl}/dashboard` });
    } else {
      showNotification('JKZ Network Error', 'Base URL is not configured.');
    }
  }
  notificationUrls.delete(notificationId);
});
