// primitives.jsx — Diaz Hauling shared components
// Logo, PhotoPlaceholder, icons. Exported to window for cross-script use.

const { useState, useEffect, useRef, useMemo } = React;

/* ───────── Asset base (works locally + under /diazhauling-vN/ on 510tech.dev) ───────── */
const ASSET_BASE = (() => {
  if (typeof window === 'undefined') return '/assets/';
  const m = window.location.pathname.match(/^(\/diazhauling-v\d+)\//);
  return (m ? m[1] : '') + '/assets/';
})();
const BRAND_LOGO = ASSET_BASE + 'brand/diaz-logo.png';

/* ───────── Logo (real brand asset) ───────── */
function Logo({ size = 'md', dark = false }) {
  const className = `logo logo-${size} ${dark ? 'on-dark' : ''}`.trim();
  return (
    <a href="#top" className={className} aria-label="Diaz Hauling — home">
      <img className="logo-img" src={BRAND_LOGO} alt="Diaz Hauling" />
    </a>
  );
}

/* ───────── Photo manifest + base path ─────────
   Maps a substring of the photoCue/label to a real photo file.
   First matching entry wins. Falls back to the striped placeholder
   if no entry matches. Substrings are case-insensitive. */
const PHOTO_BASE = (() => {
  if (typeof window === 'undefined') return '/assets/photos/';
  const m = window.location.pathname.match(/^(\/diazhauling-v\d+)\//);
  return (m ? m[1] : '') + '/assets/photos/';
})();

const PHOTO_MAP = [
  // Owner portrait + wrapped-truck shots for the About/"real contractor" blocks
  // (2026-07-19 rebrand — new green-arrow wrap + José portrait). Kept first so
  // they outrank the generic 'truck' fallback further down.
  ['jose smiling',              'jose-smiling.png'],
  ['wrapped diaz truck',        'job-truck-services.jpg'],

  // Live-site hero images (pulled from diazhauling.com Slider Revolution, 2026-07-09).
  // First match wins, so these outrank the generic entries below.
  ['hero · diaz green truck on east bay',  'new-truck-arrow.jpg'],
  ['hero · diaz job in oakland',           'live-hero-oakland.jpg'],
  ['hero · diaz job in berkeley',          'live-hero-berkeley.jpg'],
  ['hero · diaz job in emeryville',        'live-hero-emeryville.jpg'],
  ['hero · diaz job in hayward',           'live-hero-hayward.jpg'],

  // City TILE photos (CityTileGrid uses `Diaz job · ${city}`) — real per-city
  // shots from /Media/2024/Used (the old site's city page images).
  ['diaz job · oakland',        'city2024-oakland.jpg'],
  ['diaz job · piedmont',       'city2024-piedmont.jpg'],
  ['diaz job · alameda',        'city2024-alameda.jpg'],
  ['diaz job · berkeley',       'city2024-berkeley.jpg'],
  ['diaz job · albany',         'city2024-albany.jpg'],
  ['diaz job · el cerrito',     'city2024-el-cerrito.jpg'],
  ['diaz job · emeryville',     'city2024-emeryville.jpg'],
  ['diaz job · san leandro',    'city2024-san-leandro.jpg'],
  ['diaz job · castro valley',  'city2024-castro-valley.jpg'],
  ['diaz job · hayward',        'city2024-hayward.jpg'],
  ['diaz job · san lorenzo',    'city2024-san-lorenzo.jpg'],
  ['diaz job · fremont',        'city2024-fremont.jpg'],
  ['diaz job · union city',     'city2024-union-city.webp'],
  ['diaz job · newark',         'city2024-newark.jpg'],

  // City-specific heroes (CityPageBody uses `HERO · Diaz job in ${city} ...`)
  ['diaz job in oakland',       'city-oakland.jpg'],
  ['diaz job in berkeley',      'city-berkeley.jpg'],
  ['diaz job in alameda',       'city-alameda.jpg'],
  ['diaz job in hayward',       'city-hayward.jpg'],
  ['diaz job in fremont',       'city-fremont.jpg'],
  ['diaz job in emeryville',    'city-emeryville.jpg'],

  // Service card photoCues (HomePageBody / ServicesIndexBody)
  ['green truck in residential',      'job-residential.jpg'],
  ['commercial cleanout',             'job-commercial.jpg'],
  ['commercial loading dock',         'job-commercial.jpg'],
  ['construction site haul',          'job-truck-services.jpg'],
  ['bobcat skid steer',               'job-bobcat-demo.jpg'],
  ['action · bobcat',                 'job-bobcat-demo.jpg'],

  // Dumpster Rentals photo strip (3 distinct shots across the top of
  // /dumpster-rentals/, 2026-07-20) — kept above the generic 'dumpster'
  // entries below so first-match-wins resolves each to its own file
  // instead of all three collapsing onto job-dumpster-street.jpg.
  ['dumpster strip a · dropped bin',    'job-dumpster-street.jpg'],
  ['dumpster strip b · roll-off truck', 'new-truck-arrow.jpg'],
  ['dumpster strip c · roll-off haul',  'job-truck-sunset.jpg'],

  ['green diaz dumpster',             'job-dumpster-street.jpg'],
  ['dumpster',                        'job-dumpster-street.jpg'],

  // Hero variants
  ['hero · diaz green truck loaded',          'job-truck-services.jpg'],
  ['hero · wide shot',                        'job-truck-sunset.jpg'],
  ['hero · diaz green truck on east bay',     'job-truck-sunset.jpg'],
  ['hero · diaz crew',                        'job-truck-sunset.jpg'],

  // Mid-CTA city photoCues
  ['diaz crew + truck',         'job-truck-services.jpg'],

  // Generic city fallback (any city not listed above)
  ['hero · diaz job in',        'new-truck-arrow.jpg'],
  ['diaz job site',             'new-truck-arrow.jpg'],

  // Detail shots
  ['detail · family',           'job-truck-services.jpg'],
  ['detail · hands',             'job-residential.jpg'],

  // Service-detail "Recent jobs" galleries (ServiceDetailBody uses `${name} · East Bay job N`)
  // REAL photos only — this section sits under "No stock imagery, no AI mockups" copy.
  // (residential.jpg / commercial.jpg / construction.jpg / bobcat.jpg are AI illustrations; city2024-* are stylized aerials — do NOT use here.)
  ['residential hauling · east bay job 1',  'job-residential.jpg'],
  ['residential hauling · east bay job 2',  'job-residential-junk.jpg'],
  ['residential hauling · east bay job 3',  'job-truck-services.jpg'],
  ['residential hauling · east bay job 4',  'job-truck-services.jpg'],
  ['residential hauling · east bay job 5',  'live-hero-oakland.jpg'],
  ['residential hauling · east bay job 6',  'job-dumpster-street.jpg'],
  ['commercial hauling · east bay job 1',   'job-commercial.jpg'],
  ['commercial hauling · east bay job 2',   'job-truck-sunset.jpg'],
  ['commercial hauling · east bay job 3',   'new-truck-arrow.jpg'],
  ['commercial hauling · east bay job 4',   'live-hero-emeryville.jpg'],
  ['commercial hauling · east bay job 5',   'job-truck-services.jpg'],
  ['commercial hauling · east bay job 6',   'job-dumpster-street.jpg'],
  ['construction hauling · east bay job 1', 'job-truck-services.jpg'],
  ['construction hauling · east bay job 2', 'job-construction-debris.jpg'],
  ['construction hauling · east bay job 3', 'job-bobcat-demo.jpg'],
  ['construction hauling · east bay job 4', 'live-hero-hayward.jpg'],
  ['construction hauling · east bay job 5', 'job-truck-sunset.jpg'],
  ['construction hauling · east bay job 6', 'new-truck-arrow.jpg'],
  ['bobcat services · east bay job 1',      'job-bobcat-demo.jpg'],
  ['bobcat services · east bay job 2',      'job-construction-debris.jpg'],
  ['bobcat services · east bay job 3',      'job-truck-services.jpg'],
  ['bobcat services · east bay job 4',      'live-hero-berkeley.jpg'],
  ['bobcat services · east bay job 5',      'new-truck-arrow.jpg'],
  ['bobcat services · east bay job 6',      'new-truck-arrow.jpg'],
  // Final generic fallbacks
  ['truck',                     'new-truck-arrow.jpg'],
  ['crew',                      'job-truck-sunset.jpg'],
];

function findPhotoSrc(label) {
  if (!label) return null;
  const needle = String(label).toLowerCase();
  for (const [pattern, file] of PHOTO_MAP) {
    if (needle.includes(pattern)) return PHOTO_BASE + file;
  }
  return null;
}

/* ───────── Photo placeholder ─────────
   Renders a real photo if the label matches an entry in PHOTO_MAP.
   Otherwise falls back to a striped SVG placeholder with the label as caption. */
function PhotoPlaceholder({ label = 'photo', tone = 'default', stripes = true, children }) {
  const toneClass =
    tone === 'dark' ? 'photo-ph dark' :
    tone === 'sage' ? 'photo-ph tint-sage' :
    tone === 'warm' ? 'photo-ph tint-warm' :
    'photo-ph';

  const src = findPhotoSrc(label);

  if (src) {
    return (
      <div className={`${toneClass} photo-real`} role="img" aria-label={label}>
        <img src={src} alt={label} loading="lazy" />
        {children}
      </div>
    );
  }

  return (
    <div className={toneClass} role="img" aria-label={`Placeholder for: ${label}`}>
      {stripes && (
        <svg className="stripes" preserveAspectRatio="none" viewBox="0 0 100 100" aria-hidden="true">
          <defs>
            <pattern id={`p-${label.replace(/\s+/g, '-')}`} width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
              <line x1="0" y1="0" x2="0" y2="6" stroke="currentColor" strokeOpacity="0.18" strokeWidth="3"/>
            </pattern>
          </defs>
          <rect width="100" height="100" fill={`url(#p-${label.replace(/\s+/g, '-')})`} />
        </svg>
      )}
      <div className="ph-label">{label}</div>
      {children}
    </div>
  );
}

/* ───────── Tiny icons (kept extremely minimal) ───────── */
function PhoneIcon({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/>
    </svg>
  );
}
function ArrowIcon({ size = 14 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
      <line x1="5" y1="12" x2="19" y2="12"/>
      <polyline points="13 5 20 12 13 19"/>
    </svg>
  );
}
function CheckIcon({ size = 12 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="20 6 9 17 4 12"/>
    </svg>
  );
}
function StarIcon({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
      <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
    </svg>
  );
}

/* ───────── Stars row ───────── */
function Stars({ n = 5 }) {
  return (
    <div className="stars" aria-label={`${n} out of 5 stars`}>
      {Array.from({length: n}).map((_, i) => <StarIcon key={i} size={16} />)}
    </div>
  );
}

/* ───────── Data ───────── */
const SERVICES = [
  {
    id: 'residential',
    name: 'Residential Hauling',
    tag: 'Homes & garages',
    blurb: 'Garage cleanouts, yard waste, mattresses, appliances. We arrive on time, in uniform, and clean up after ourselves.',
    photo: 'green truck in residential driveway · Oakland',
    span: 2
  },
  {
    id: 'commercial',
    name: 'Commercial Hauling',
    tag: 'Properties & businesses',
    blurb: 'Office cleanouts, property management debris removal, retail buildouts. Scheduled or on-call service.',
    photo: 'commercial loading dock cleanout · Berkeley',
    span: 2
  },
  {
    id: 'construction',
    name: 'Construction Hauling',
    tag: 'Job sites & buildouts',
    blurb: 'Pre-construction site clearance, post-build cleanup, drywall, framing scrap. We coordinate with your GC.',
    photo: 'construction site haul-away · Alameda',
    span: 2
  },
  {
    id: 'bobcat',
    name: 'Bobcat Services',
    tag: 'Specialty · Differentiator',
    blurb: 'Skid steer for jobs a truck and crew can\'t touch — grading, demolition, dirt and aggregate moves, debris piles in tight lots.',
    photo: 'Bobcat skid steer at work · job site',
    span: 3, featured: true
  },
  {
    id: 'junk',
    name: 'Junk Removal Specialists',
    tag: 'Same-day service',
    blurb: 'Single-item pickups through full estate cleanouts. Mattresses, furniture, e-waste, hot tubs — we take what other haulers won\'t.',
    photo: 'crew loading furniture · Hayward',
    span: 3
  }
];

const SUB_SERVICES = [
  'Light demolition (sheds · decks · fences)',
  'Estate cleanouts',
  'Yard waste removal',
  'E-waste pickup',
  'Mattress & carpet removal',
  'Dumpster rentals',
  'Pre & post-construction cleanup',
  'Hot tub & spa removal',
  'Appliance haul-away',
  'Garage cleanouts',
  'Office & retail cleanouts',
  'Foreclosure & eviction cleanouts',
  'Storage unit cleanouts',
  'Furniture removal',
  'Concrete & rubble haul',
  'Dirt & aggregate moves',
  'Roofing tear-off haul-away',
  'Tenant-improvement debris',
  'Tree & brush removal'
];

const AREAS = [
  { region: 'East Bay', primary: true, cities: ['Oakland','Piedmont','Emeryville','Alameda','Berkeley','Albany','San Leandro','San Lorenzo','Ashland','Cherryland','Fairview','Hayward','Castro Valley','Union City','Newark','Fremont','Sunol','Dublin','Pleasanton'] }
];

const REVIEWS = [
  {
    name: 'Marisol R.',
    city: 'Oakland, CA',
    initial: 'M',
    text: 'Texted a photo of our garage pile Sunday night, had a quote by Monday morning, and the truck was gone by Wednesday lunch. José himself answered the phone. This is how it should work.'
  },
  {
    name: 'Daniel K.',
    city: 'Berkeley, CA',
    initial: 'D',
    text: 'Three other haulers ghosted me on a demo + haul job. Diaz showed up on time, brought the Bobcat, and finished it in a day. They\'ve handled two more jobs since.'
  },
  {
    name: 'Janelle T.',
    city: 'Alameda, CA',
    initial: 'J',
    text: 'Estate cleanout after my dad passed. They were kind, careful, and didn\'t toss anything without asking. Real family operation — and they recycled almost everything.'
  }
];

const TRUST = [
  { num: '15+',    lbl: 'Years in the East Bay' },
  { num: '608+',   lbl: 'Yelp reviews · verified' },
  { num: '100%',   lbl: 'Family-owned' }
];

const WORKFLOW = [
  { num: '01', title: 'Text us a photo', blurb: 'Snap the pile. Text (510) 825-4218 with your zip code. No forms, no callbacks, no salesman.' },
  { num: '02', title: 'Get a quote right back', blurb: 'A flat, all-in price texted right back — usually within the hour. No hidden fees, no up-charges on arrival.' },
  { num: '03', title: 'Pick your slot', blurb: 'Confirm by text or book online. Same-day service available across the East Bay and Alameda County.' }
];

const DUMPSTER_SIZES = [
  { yards: '15', tag: 'Compact',            dims: '14\' x 7\' x 53"', price: '$649/wk', weight: '2,000 lbs included', desc: 'No dirt, concrete, brick, or other heavy material.' },
  { yards: '20', tag: 'Most popular',       dims: '16\' x 7\' x 56"', price: '$725/wk', weight: '3,000 lbs included', desc: 'No dirt, concrete, brick, or other heavy material.' },
  { yards: '25', tag: 'Heavy-duty',         dims: '16\' x 7\' x 70"', price: '$749/wk', weight: '3,000 lbs included', desc: 'No dirt, concrete, brick, or other heavy material.' },
  { yards: '30', tag: 'Job-site',           dims: '16\' x 7\' x 90"', price: '$849/wk', weight: '4,000 lbs included', desc: 'No dirt, concrete, brick, or other heavy material.' },
  { yards: '7',  tag: 'Heavy material only', dims: '12\' x 7\' x 25"', price: '$899/wk', weight: 'Heavy-material only', desc: 'Clean concrete (no big chunks/rebar), clean dirt, clean tile, clean brick. No mixed materials.' }
];

const WORKIZ_SLOTS = [
  { day: 'Tue', date: '12', month: 'May', time: '8–10 AM' },
  { day: 'Wed', date: '13', month: 'May', time: '10–12 PM' },
  { day: 'Thu', date: '14', month: 'May', time: '1–3 PM'  },
  { day: 'Fri', date: '15', month: 'May', time: '8–10 AM' },
  { day: 'Sat', date: '16', month: 'May', time: '9–11 AM' },
  { day: 'Mon', date: '18', month: 'May', time: '8–10 AM' }
];

// Expose
function TextIcon({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>
    </svg>
  );
}
function CameraIcon({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
      <circle cx="12" cy="13" r="4"/>
    </svg>
  );
}

const SMS_HREF = 'sms:+15108254218?&body=Hi%20Diaz%20Hauling%20%E2%80%94%20here%27s%20a%20photo%20of%20the%20pile%20I%20need%20hauled.%20Zip%3A%20';

Object.assign(window, {
  Logo, PhotoPlaceholder, BRAND_LOGO,
  PhoneIcon, ArrowIcon, CheckIcon, StarIcon, Stars, TextIcon, CameraIcon,
  SERVICES, SUB_SERVICES, AREAS, REVIEWS, TRUST, WORKFLOW,
  DUMPSTER_SIZES, WORKIZ_SLOTS, SMS_HREF
});
