export type PlatformCategory = "cms" | "ecommerce" | "js_framework" | "static_site" | "other";

export interface PlatformCandidate {
  name: string;
  version?: string;
  confidence: number; // numeric weight used only for conflict resolution; stored as "high"/"medium"/"low"
  category: PlatformCategory;
}

export interface HostingCandidate {
  name: string;
}

interface PlatformSig {
  name: string;
  category: PlatformCategory;
  confidence: number;
  detect: (html: string) => PlatformCandidate | null;
}

interface HostingSig {
  name: string;
  detect: (html: string, headers?: Record<string, string>) => HostingCandidate | null;
}

// Weights match conflict resolution spec
const PLATFORM_SIGS: PlatformSig[] = [
  {
    name: "nextjs", category: "js_framework", confidence: 90,
    detect: (html) => {
      if (html.includes("/_next/static/") || html.includes("__NEXT_DATA__")) {
        return { name: "nextjs", category: "js_framework", confidence: 90 };
      }
      return null;
    },
  },
  {
    name: "remix", category: "js_framework", confidence: 85,
    detect: (html) => {
      if (html.includes("__remixContext") || html.includes("__remixManifest")) {
        return { name: "remix", category: "js_framework", confidence: 85 };
      }
      return null;
    },
  },
  {
    name: "woocommerce", category: "ecommerce", confidence: 80,
    detect: (html) => {
      if (/class="[^"]*woocommerce/.test(html) || html.includes("/woocommerce/assets/") || html.includes("woocommerce-js")) {
        return { name: "woocommerce", category: "ecommerce", confidence: 80 };
      }
      return null;
    },
  },
  {
    name: "shopify", category: "ecommerce", confidence: 80,
    detect: (html) => {
      if (html.includes("cdn.shopify.com") || /content="Shopify"/i.test(html) || html.includes("Shopify.theme")) {
        return { name: "shopify", category: "ecommerce", confidence: 80 };
      }
      return null;
    },
  },
  {
    name: "wix", category: "cms", confidence: 80,
    detect: (html) => {
      if (html.includes("static.wixstatic.com") || /content="Wix/i.test(html) || html.includes("data-wix-")) {
        return { name: "wix", category: "cms", confidence: 80 };
      }
      return null;
    },
  },
  {
    name: "bigcommerce", category: "ecommerce", confidence: 75,
    detect: (html) => {
      if (html.includes("cdn11.bigcommerce.com") || html.includes("bigcommerce.com/s-")) {
        return { name: "bigcommerce", category: "ecommerce", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "nuxt", category: "js_framework", confidence: 75,
    detect: (html) => {
      if (html.includes("/_nuxt/") || html.includes("__NUXT__") || /x-powered-by:\s*nuxt/i.test(html)) {
        return { name: "nuxt", category: "js_framework", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "webflow", category: "cms", confidence: 75,
    detect: (html) => {
      if (html.includes("webflow.com") || html.includes("data-wf-page") || html.includes("data-wf-site")) {
        return { name: "webflow", category: "cms", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "astro", category: "js_framework", confidence: 75,
    detect: (html) => {
      if (html.includes("data-astro-cid-") || html.includes("@astrojs/") || html.includes("astro-island")) {
        return { name: "astro", category: "js_framework", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "gatsby", category: "js_framework", confidence: 75,
    detect: (html) => {
      if (html.includes("___gatsby") || html.includes("gatsby-focus-wrapper") || html.includes("gatsby-image-")) {
        return { name: "gatsby", category: "js_framework", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "sveltekit", category: "js_framework", confidence: 75,
    detect: (html) => {
      if (html.includes("data-svelte-h") || html.includes("/__app.") || html.includes("svelte-kit")) {
        return { name: "sveltekit", category: "js_framework", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "squarespace", category: "cms", confidence: 75,
    detect: (html) => {
      if (html.includes("squarespace.com") || html.includes("squarespace-cdn.com") || html.includes("data-squarespace")) {
        return { name: "squarespace", category: "cms", confidence: 75 };
      }
      return null;
    },
  },
  {
    name: "wordpress", category: "cms", confidence: 70,
    detect: (html) => {
      const genMatch = html.match(/WordPress\s+(\d+\.\d+(?:\.\d+)?)/i);
      if (genMatch) return { name: "wordpress", version: genMatch[1], category: "cms", confidence: 70 };
      if (html.includes("/wp-content/") || html.includes("/wp-includes/") || html.includes("wp-block-")) {
        return { name: "wordpress", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "drupal", category: "cms", confidence: 70,
    detect: (html) => {
      if (html.includes("/sites/default/files/") || html.includes("drupal.js") || html.includes("data-drupal-")) {
        return { name: "drupal", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "joomla", category: "cms", confidence: 70,
    detect: (html) => {
      if (/content="Joomla!/i.test(html) || html.includes("/media/jui/") || html.includes("/components/com_")) {
        return { name: "joomla", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "ghost", category: "cms", confidence: 70,
    detect: (html) => {
      const genMatch = html.match(/Ghost\s+(\d+\.\d+(?:\.\d+)?)/i);
      if (genMatch) return { name: "ghost", version: genMatch[1], category: "cms", confidence: 70 };
      if (html.includes("ghost.io") || html.includes("@tryghost/")) {
        return { name: "ghost", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "magento", category: "ecommerce", confidence: 70,
    detect: (html) => {
      // Require 2 of 4 signals to avoid false positives from unrelated uses of "mage/" in other paths
      let signals = 0;
      if (/content="Magento/i.test(html)) signals++;
      if (html.includes("Mage.")) signals++;
      if (html.includes("/pub/static/version")) signals++;
      if (html.includes("cookies.checkPermission") || html.includes("requirejs-min-resolver")) signals++;
      if (signals >= 2) return { name: "magento", category: "ecommerce", confidence: 70 };
      return null;
    },
  },
  {
    name: "weebly", category: "cms", confidence: 70,
    detect: (html) => {
      if (html.includes("weebly.com") || html.includes("editmysite.com") || html.includes("weeblycloud.com")) {
        return { name: "weebly", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "duda", category: "cms", confidence: 70,
    detect: (html) => {
      if (html.includes("irp-cdn.multiscreensite.com") || html.includes("dudasite.com") || html.includes("dmss.multiscreensite.com")) {
        return { name: "duda", category: "cms", confidence: 70 };
      }
      return null;
    },
  },
  {
    name: "angular", category: "js_framework", confidence: 65,
    detect: (html) => {
      if (html.includes("ng-version=") || html.includes("ng-app") || html.includes("zone.min.js")) {
        return { name: "angular", category: "js_framework", confidence: 65 };
      }
      return null;
    },
  },
  {
    name: "jekyll", category: "static_site", confidence: 60,
    detect: (html) => {
      if (/content="Jekyll/i.test(html)) return { name: "jekyll", category: "static_site", confidence: 60 };
      return null;
    },
  },
  {
    name: "hugo", category: "static_site", confidence: 60,
    detect: (html) => {
      if (/content="Hugo/i.test(html)) return { name: "hugo", category: "static_site", confidence: 60 };
      return null;
    },
  },
  {
    name: "eleventy", category: "static_site", confidence: 60,
    detect: (html) => {
      if (/content="Eleventy/i.test(html) || /content="11ty/i.test(html)) {
        return { name: "eleventy", category: "static_site", confidence: 60 };
      }
      return null;
    },
  },
  {
    name: "vue", category: "js_framework", confidence: 50,
    detect: (html) => {
      if (html.includes("data-server-rendered") || html.includes("__VUE__") || html.includes("vue.config.")) {
        return { name: "vue", category: "js_framework", confidence: 50 };
      }
      return null;
    },
  },
  {
    name: "react", category: "js_framework", confidence: 40,
    detect: (html) => {
      if (html.includes("react-root") || html.includes("__REACT_ROOT__")) {
        return { name: "react", category: "js_framework", confidence: 40 };
      }
      return null;
    },
  },
];

export const HOSTING_SIGS: HostingSig[] = [
  {
    name: "vercel",
    detect: (html, headers) => {
      if (headers?.["x-vercel-id"] || html.includes("__vercel_toolbar") || html.includes("vercel.app")) {
        return { name: "vercel" };
      }
      return null;
    },
  },
  {
    name: "netlify",
    detect: (html, headers) => {
      if (headers?.["x-nf-request-id"] || html.includes("netlify.app") || html.includes("netlify-identity")) {
        return { name: "netlify" };
      }
      return null;
    },
  },
  {
    name: "github_pages",
    detect: (html) => {
      if (html.includes("github.io") || /content="GitHub Pages/i.test(html)) return { name: "github_pages" };
      return null;
    },
  },
  {
    // cf-ray and cf-cache-status are present on any site behind Cloudflare's network,
    // not only Cloudflare Pages. Distinguishing Pages from CDN requires DNS analysis
    // (CNAME to pages.cloudflare.com) which is not available at detection time.
    // TODO: upgrade detection when DNS resolver is available.
    name: "cloudflare_cdn",
    detect: (_, headers) => {
      if (headers?.["cf-cache-status"] && headers?.["cf-ray"]) return { name: "cloudflare_cdn" };
      return null;
    },
  },
  {
    name: "wpengine",
    detect: (_, headers) => {
      if (headers?.["x-cacheable"] || headers?.["x-cache-group"]) return { name: "wpengine" };
      return null;
    },
  },
  {
    name: "kinsta",
    detect: (_, headers) => {
      if (headers?.["x-kinsta-cache"]) return { name: "kinsta" };
      return null;
    },
  },
];

export function detectPlatformFromHtml(
  html: string,
  headers?: Record<string, string>,
): { platform: PlatformCandidate | null; hosting: HostingCandidate | null } {
  const candidates: PlatformCandidate[] = [];
  for (const sig of PLATFORM_SIGS) {
    const result = sig.detect(html);
    if (result) candidates.push(result);
  }

  const platform = resolvePlatform(candidates);

  let hosting: HostingCandidate | null = null;
  for (const sig of HOSTING_SIGS) {
    const result = sig.detect(html, headers);
    if (result) { hosting = result; break; }
  }

  return { platform, hosting };
}

export function resolvePlatform(candidates: PlatformCandidate[]): PlatformCandidate | null {
  if (!candidates.length) return null;
  return candidates.reduce((best, c) => (c.confidence > best.confidence ? c : best));
}
