import { UrlCheckResult, UrlVerdict, ThreatInfo, BackgroundMessage, MessageType, SubscriptionTier, PhishingReport, ExtensionSettings } from '../types';
import { urlCache, CACHE_TTL } from '../lib/cache';
import { phishingDetector } from '../lib/phishing-detector';
import { settingsManager } from '../lib/settings';
import { shieldApiClient } from '../lib/api-client';

let threatsBlockedToday = 0;
let urlsCheckedToday = 0;
let lastThreat: ThreatInfo | null = null;

chrome.runtime.onInstalled.addListener(async () => {
  await urlCache.loadFromStorage();
  await settingsManager.load();

  const stats = await chrome.storage.local.get('dailyStats');
  if (stats.dailyStats && stats.dailyStats.date === new Date().toDateString()) {
    threatsBlockedToday = stats.dailyStats.threatsBlocked;
    urlsCheckedToday = stats.dailyStats.urlsChecked;
  } else {
    threatsBlockedToday = 0;
    urlsCheckedToday = 0;
    await saveDailyStats();
  }

  chrome.declarativeNetRequest.onRuleMatchedDebug.addListener((details) => {
    chrome.storage.local.get('blockedRequests').then((data) => {
      const blocked = data.blockedRequests || [];
      blocked.push({ ruleId: details.rule?.ruleId || 0, url: details.request?.url || '', timestamp: Date.now() });
      if (blocked.length > 100) blocked.shift();
      chrome.storage.local.set({ blockedRequests: blocked });
    });
  });
});

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
  if (changeInfo.status !== 'loading' || !tab.url) return;

  const enabled = await settingsManager.isProtectionEnabled();
  if (!enabled) return;

  const url = tab.url;
  if (url.startsWith('chrome://') || url.startsWith('chrome-extension://')) return;

  await analyzeAndAct(url, tabId);
});

async function analyzeAndAct(url: string, tabId: number): Promise<void> {
  urlsCheckedToday++;
  const startTime = Date.now();

  const allowed = await isShieldAIUrl(url);
  if (allowed) return;

  const blocked = await settingsManager.isDomainBlocked(extractDomain(url));
  if (blocked) {
    threatsBlockedToday++;
    await showBlockedPage(tabId, url);
    await saveDailyStats();
    return;
  }

  const cached = await urlCache.get(url);
  if (cached) {
    broadcastResult(cached, tabId);
    if (cached.verdict === UrlVerdict.PHISHING) {
      const features = await settingsManager.getFeatures();
      if (features.activeBlocking) {
        threatsBlockedToday++;
        await showBlockedPage(tabId, url);
      } else {
        showWarningNotification(cached);
      }
    }
    await saveDailyStats();
    return;
  }

  const heuristic = phishingDetector.analyzeUrl(url);
  let result: UrlCheckResult = {
    url,
    domain: extractDomain(url),
    verdict: heuristic.verdict,
    confidence: heuristic.score / 100,
    threats: heuristic.threats,
    cached: false,
    latencyMs: Date.now() - startTime,
    timestamp: Date.now(),
  };

  const apiResult = await shieldApiClient.checkUrl(url);
  if (apiResult && apiResult.threats.length > 0) {
    result = apiResult;
  }

  const darkWatchEnabled = await settingsManager.get();
  if (darkWatchEnabled.darkWatchEnabled) {
    const exposure = await shieldApiClient.checkDomainExposure(result.domain);
    if (exposure && exposure.exposed) {
      result.threats.push({
        type: 'credential_exposure' as any,
        severity: 4,
        source: 'darkwatch',
        description: `Credentials for ${result.domain} found in ${exposure.sources.length} breach(es)`,
      });
      if (result.verdict === UrlVerdict.SAFE) {
        result.verdict = UrlVerdict.EXPOSED_CREDENTIALS;
      }
    }
  }

  await urlCache.set(url, result);
  broadcastResult(result, tabId);

  if (result.verdict === UrlVerdict.PHISHING) {
    const features = await settingsManager.getFeatures();
    if (features.activeBlocking) {
      threatsBlockedToday++;
      await showBlockedPage(tabId, url);
    } else {
      showWarningNotification(result);
    }
  }

  if (result.threats.length > 0) {
    lastThreat = result.threats[0];
  }

  await saveDailyStats();
}

function broadcastResult(result: UrlCheckResult, tabId: number): void {
  chrome.tabs.sendMessage(tabId, {
    type: MessageType.CHECK_URL_RESPONSE,
    payload: result,
  }).catch(() => {});
}

async function showBlockedPage(tabId: number, url: string): Promise<void> {
  const blockedUrl = chrome.runtime.getURL(`popup.html?blocked=${encodeURIComponent(url)}`);
  await chrome.tabs.update(tabId, { url: blockedUrl });
}

async function showWarningNotification(result: UrlCheckResult): Promise<void> {
  const settings = await settingsManager.get();
  if (!settings.showNotifications) return;
  await chrome.notifications.create({
    type: 'basic',
    iconUrl: 'icons/icon48.png',
    title: 'ShieldAI Warning',
    message: `${result.verdict.toUpperCase()}: ${result.domain}`,
    priority: result.verdict === UrlVerdict.PHISHING ? 2 : 0,
  });
}

async function saveDailyStats(): Promise<void> {
  await chrome.storage.local.set({
    dailyStats: {
      date: new Date().toDateString(),
      threatsBlocked: threatsBlockedToday,
      urlsChecked: urlsCheckedToday,
    },
  });
  await urlCache.persistToStorage();
}

function extractDomain(url: string): string {
  try {
    return new URL(url).hostname;
  } catch {
    return url;
  }
}

async function isShieldAIUrl(url: string): Promise<boolean> {
  const settings = await settingsManager.get();
  const domain = extractDomain(url);
  const apiDomain = new URL(settings.apiBaseUrl).hostname;
  return domain === apiDomain || await settingsManager.isDomainAllowed(domain);
}

chrome.runtime.onMessage.addListener(
  (message: BackgroundMessage, sender, sendResponse) => {
    handleMessage(message, sender).then((res) => {
      if (res) sendResponse(res);
    });
    return true;
  }
);

async function handleMessage(
  message: BackgroundMessage,
  sender: chrome.runtime.MessageSender
): Promise<Record<string, unknown> | void> {
  switch (message.type) {
    case MessageType.CHECK_URL: {
      const url = message.payload?.url as string;
      if (!url) return;
      const tabId = sender.tab?.id || 0;
      await analyzeAndAct(url, tabId);
      break;
    }

    case MessageType.GET_SETTINGS:
      return { settings: await settingsManager.get() };

    case MessageType.UPDATE_SETTINGS:
      return { settings: await settingsManager.update(message.payload as Partial<ExtensionSettings>) };

    case MessageType.REPORT_PHISHING: {
      const payload = message.payload as Record<string, unknown> | undefined;
      if (!payload || typeof payload.url !== 'string' || typeof payload.pageTitle !== 'string') {
        return { success: false, error: 'Missing url or pageTitle' };
      }
      const report: PhishingReport = {
        url: payload.url,
        pageTitle: payload.pageTitle,
        tabId: (payload.tabId as number) || 0,
        timestamp: (payload.timestamp as number) || Date.now(),
        reason: (payload.reason as string) || 'Manual report',
        heuristics: (payload.heuristics as Record<string, unknown>) || {},
      };
      const success = await shieldApiClient.submitPhishingReport(report);
      return { success };
    }

    case MessageType.GET_POPUP_DATA:
      return {
        protectionEnabled: await settingsManager.isProtectionEnabled(),
        tier: await settingsManager.getTier(),
        threatsBlockedToday,
        urlsCheckedToday,
        lastThreat,
        isLoggedIn: await settingsManager.isLoggedIn(),
      };

    case MessageType.TOGGLE_PROTECTION: {
      const enabled = await settingsManager.toggleProtection();
      return { enabled };
    }

    case MessageType.AUTH_LOGOUT: {
      await settingsManager.update({ authToken: null, userId: null, tier: null });
      return { success: true };
    }
  }
}
