import type { ContentSample } from "../../audit/scrapers/firecrawl-content";
import type { PageData } from "../../audit/types";
import type { VoiceSearchGap, VoiceSearchRecommendation } from "../types";

export interface LocalPackSignalsResult {
  score: number;
  pagesChecked: number;
  pagesWithLocalBusinessSchema: number;
  pagesWithNap: number;
  pagesWithLocationSchema: number;
  pagesWithPhoneClick: number;
  gaps: VoiceSearchGap[];
  recommendations: VoiceSearchRecommendation[];
}

const LOCAL_BUSINESS_SCHEMA_RE = /"@type"\s*:\s*"(LocalBusiness|MedicalBusiness|DentalClinic|LegalService|RealEstateAgent|HomeAndConstructionBusiness|FoodEstablishment|ProfessionalService)"/;

// NAP: phone number in text (not just click-to-call links)
const PHONE_IN_TEXT_RE = /\b(\+?1[\s.-]?)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}\b/;
// Street address pattern
const ADDRESS_RE = /\d{1,5}\s+[A-Z][a-z]+\s+(St|Ave|Blvd|Dr|Rd|Ln|Way|Ct|Pl|Suite|Ste)\b/i;

function hasNap(markdown: string): boolean {
  return PHONE_IN_TEXT_RE.test(markdown) && ADDRESS_RE.test(markdown);
}

function hasLocalBusinessSchema(markdown: string): boolean {
  return LOCAL_BUSINESS_SCHEMA_RE.test(markdown);
}

export function checkLocalPackSignals(
  pages: PageData[],
  samples: ContentSample[],
): LocalPackSignalsResult {
  const sampleMap = new Map(samples.map((s) => [s.url, s]));

  let pagesWithLocalBusinessSchema = 0;
  let pagesWithNap = 0;
  let pagesWithLocationSchema = 0;
  let pagesWithPhoneClick = 0;
  const checked = Math.min(pages.length, samples.length);

  for (const page of pages) {
    const sample = sampleMap.get(page.url);
    if (!sample) continue;

    const md = sample.markdown ?? "";
    if (hasLocalBusinessSchema(md)) pagesWithLocalBusinessSchema++;
    if (hasNap(md)) pagesWithNap++;
    if (sample.hasLocationSchema) pagesWithLocationSchema++;
    if (sample.hasPhoneClick) pagesWithPhoneClick++;
  }

  const lbSchemaRatio = checked > 0 ? pagesWithLocalBusinessSchema / checked : 0;
  const napRatio = checked > 0 ? pagesWithNap / checked : 0;
  const locationSchemaRatio = checked > 0 ? pagesWithLocationSchema / checked : 0;
  const phoneClickRatio = checked > 0 ? pagesWithPhoneClick / checked : 0;

  // Score: LocalBusiness schema (35%) + NAP consistency (30%) + location schema (20%) + phone click (15%)
  const score = Math.round(
    (lbSchemaRatio * 35 + napRatio * 30 + locationSchemaRatio * 20 + phoneClickRatio * 15) * 100,
  ) / 100;

  const gaps: VoiceSearchGap[] = [];
  const recommendations: VoiceSearchRecommendation[] = [];

  if (lbSchemaRatio < 0.4) {
    gaps.push({
      dimension: "local-pack-signals",
      gap: "LocalBusiness schema absent or undercrawled",
      impactDescription: "LocalBusiness schema is the primary structured data signal voice assistants use to resolve entity identity for location-based queries such as 'hours', 'address', and 'phone number'.",
      implementationDifficulty: "moderate",
      estimatedScoreLift: 20,
    });
    recommendations.push({
      title: "Implement LocalBusiness (or vertical-specific) schema on homepage and contact pages",
      impact: "high",
      effort: "hour",
      rationale: "LocalBusiness schema directly answers the most common voice queries ('is X open', 'where is X', 'call X') and enables entity disambiguation in knowledge graphs.",
    });
  }

  if (napRatio < 0.3) {
    gaps.push({
      dimension: "local-pack-signals",
      gap: "Name/Address/Phone (NAP) not consistently present in page text",
      impactDescription: "Consistent NAP in page text reinforces entity disambiguation; absence weakens local pack eligibility and voice response confidence.",
      implementationDifficulty: "easy",
      estimatedScoreLift: 10,
    });
    recommendations.push({
      title: "Add full NAP to footer and contact page in plain text",
      impact: "medium",
      effort: "hour",
      rationale: "Plain-text NAP ensures crawlers can extract and cross-reference entity data without relying solely on schema markup.",
    });
  }

  if (phoneClickRatio < 0.3) {
    gaps.push({
      dimension: "local-pack-signals",
      gap: "Click-to-call phone links sparse across site",
      impactDescription: "Click-to-call links signal phone-call conversion intent to crawlers and reinforce NAP entity signals for local voice queries.",
      implementationDifficulty: "easy",
      estimatedScoreLift: 6,
    });
    recommendations.push({
      title: "Add tel: click-to-call links sitewide in header and contact sections",
      impact: "low",
      effort: "hour",
      rationale: "Click-to-call markup is a low-effort signal that improves both conversion tracking and local entity confidence.",
    });
  }

  return {
    score,
    pagesChecked: checked,
    pagesWithLocalBusinessSchema,
    pagesWithNap,
    pagesWithLocationSchema,
    pagesWithPhoneClick,
    gaps,
    recommendations,
  };
}
