// ImposterShield offscreen document: hosts the on-device detector.
// MV3 service workers cannot use dynamic import() or spawn workers, both of
// which the ONNX runtime needs, so the model lives here (a hidden page) and
// the service worker talks to it over runtime messaging.

import { pipeline, env } from './vendor/transformers.min.js';

env.allowLocalModels = false;
env.remoteHost = 'https://models.impostershield.com';
env.backends.onnx.wasm.wasmPaths = chrome.runtime.getURL('vendor/');

var MODEL_ID = 'impostershield/detector-v1';
var clsPromise = null;

function report(state, pct, error) {
  chrome.runtime.sendMessage({
    target: 'sw', type: 'IS_MODEL_STATE',
    state: state, pct: pct || 0, error: error || null
  }).catch(function () {});
}

function trackProgress(p) {
  if (p && p.status === 'progress' && p.total) {
    report('loading', Math.round((p.loaded / p.total) * 100));
  }
}

function getClassifier() {
  if (!clsPromise) {
    report('loading', 0);
    clsPromise = pipeline('image-classification', MODEL_ID, {
      device: 'webgpu', dtype: 'q8', progress_callback: trackProgress
    }).catch(function () {
      return pipeline('image-classification', MODEL_ID, {
        device: 'wasm', dtype: 'q8', progress_callback: trackProgress
      });
    }).then(function (p) {
      report('ready', 100);
      return p;
    }).catch(function (e) {
      report('failed', 0, String(e && e.message || e).slice(0, 300));
      throw e;
    });
  }
  return clsPromise;
}

chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
  if (!msg || msg.target !== 'offscreen') return;

  if (msg.type === 'IS_WARM') {
    getClassifier().catch(function () {});
    return;
  }

  if (msg.type === 'IS_CLASSIFY') {
    getClassifier().then(function (pipe) {
      return pipe(msg.url, { top_k: 2 });
    }).then(function (results) {
      var aiScore = null;
      (results || []).forEach(function (r) {
        var l = (r.label || '').toLowerCase();
        if (l.indexOf('artificial') !== -1 || l.indexOf('fake') !== -1 || l.indexOf('ai') === 0) {
          aiScore = r.score;
        }
      });
      sendResponse(aiScore === null ? { error: 'labels' } : { score: aiScore });
    }).catch(function (e) {
      sendResponse({ error: String(e && e.message || e).slice(0, 200) });
    });
    return true;
  }
});

getClassifier().catch(function () {});
