// Contact / Get a quote page

function ContactDetails() {
  const bp = useBP();
  const channels = [
    { i: 'phone',    title: 'Call us',     v: '+91 6238 983 511', sub: 'Mon–Sat, 9 AM – 7 PM IST', href: 'tel:+916238983511', accent: TNF.green },
    { i: 'whatsapp', title: 'WhatsApp',    v: '+91 6238 983 511', sub: 'Typically reply within an hour',  href: 'https://wa.me/916238983511', accent: '#25D366' },
    { i: 'mail',     title: 'Email',       v: 'info@tripsnflys.com', sub: 'For longer enquiries',         href: 'mailto:info@tripsnflys.com', accent: TNF.turqDk },
    { i: 'pin',      title: 'Visit',       v: 'Piravom, Ernakulam', sub: 'First Floor Vattuthottam Complex', href: '#map', accent: TNF.blueDk },
  ];
  return (
    <section style={{ padding: secPad(bp, 80, 56), background: TNF.cream }}>
      <div style={{ maxWidth: 1200, margin: '0 auto' }}>
        <div style={{ display: 'grid', gridTemplateColumns: bpv(bp, '1fr', 'repeat(2, 1fr)', 'repeat(4, 1fr)'), gap: 16 }}>
          {channels.map(c => {
            const Ic = Icon[c.i];
            return (
              <a key={c.title} href={c.href} className="tnf-card-hover" style={{
                background: '#fff', padding: 24, borderRadius: 18, textDecoration: 'none',
                color: 'inherit', display: 'flex', flexDirection: 'column', gap: 16,
                border: `1px solid ${TNF.lineSoft}`,
              }}>
                <div style={{
                  width: 48, height: 48, borderRadius: 12, background: c.accent,
                  color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>
                  <Ic width={22} height={22}/>
                </div>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 11, color: TNF.inkSoft, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase' }}>{c.title}</div>
                  <div style={{ fontFamily: 'var(--tnf-display)', fontSize: 21, color: TNF.blueDk, marginTop: 4, fontWeight: 500, letterSpacing: '-0.005em', wordBreak: 'break-word' }}>{c.v}</div>
                  <div style={{ fontSize: 13, color: TNF.inkSoft, marginTop: 4 }}>{c.sub}</div>
                </div>
              </a>
            );
          })}
        </div>
      </div>
    </section>
  );
}

function ContactFormSection() {
  const bp = useBP();
  const mob = bp === 'mobile';
  const SERVICE_OPTS = ['Packages', 'Flights', 'Hotels', 'Visa', 'Other'];
  const BUDGET_OPTS = ['Under 50k', '50k – 1L', '1L – 2L', '2L – 5L', '5L+'];
  const EMPTY = { name: '', email: '', countryCode: 'IN', phone: '', service: '', destination: '', travelers: 2, when: '', budget: '', message: '' };
  const [form, setForm] = React.useState(EMPTY);
  const [errors, setErrors] = React.useState({});
  const [done, setDone] = React.useState(false);
  const [notice, setNotice] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const captchaRef = React.useRef(null);
  const captcha = useHCaptcha(captchaRef, !done);
  // Abuse deterrents: honeypot + min fill time + max 3 submits / minute.
  const guard = useFormGuard('contact', { maxPerWindow: 3, windowMs: 60000, minFillMs: 1500 });

  // Sanitize every keystroke by field type — strips control chars / markup,
  // enforces allow-lists, clamps numbers, caps length.
  const clean = (k, v) => {
    switch (k) {
      case 'name':
      case 'destination': return InputGuard.line(v, 80);
      case 'email':       return InputGuard.email(v);
      case 'phone':       return InputGuard.phone(v);
      case 'message':     return InputGuard.text(v, 1000);
      case 'travelers':   return v === '' ? '' : InputGuard.int(v, 1, 30, 1);
      case 'when':        return /^\d{0,4}(-\d{0,2})?$/.test(String(v)) ? v : form.when;
      case 'service':     return InputGuard.oneOf(v, SERVICE_OPTS);
      case 'budget':      return InputGuard.oneOf(v, BUDGET_OPTS);
      case 'countryCode': return InputGuard.oneOf(v, COUNTRY_CODES.map(c => c.c), 'IN');
      default:            return InputGuard.line(v, 120);
    }
  };
  const update = (k, v) => {
    const cv = clean(k, v);
    setForm(f => ({ ...f, [k]: cv }));
    setErrors(e => { if (!e[k]) return e; const n = { ...e }; delete n[k]; return n; });
  };
  // Reject invalid data: required + strict type checks before "submission".
  const validate = () => {
    const er = {};
    if (!isFilledName(form.name)) er.name = 'Please enter your name (2+ characters).';
    if (!isPhone(form.phone)) er.phone = 'Enter a valid phone number.';
    if (!isEmail(form.email)) er.email = 'Enter a valid email address.';
    if (!InputGuard.int(form.travelers, 1, 30, 0)) er.travelers = 'Enter 1–30 travellers.';
    return er;
  };
  const submit = async (e) => {
    e.preventDefault();
    const er = validate();
    if (Object.keys(er).length) { setErrors(er); return; }
    // Abuse checks AFTER field validation.
    const g = guard.evaluate();
    if (!g.ok) {
      if (g.bot) { setDone(true); return; }            // honeypot tripped → silently soak it up
      if (g.reason === 'too-fast') { setNotice('That was quick — take a moment and submit again.'); return; }
      if (g.reason === 'rate') {
        const s = Math.ceil((g.retryInMs || 0) / 1000);
        setNotice(`Too many submissions. Please wait ${s}s and try again.`);
        return;
      }
      return;
    }
    // Require hCaptcha to be completed before submitting.
    const captchaToken = captcha.getToken();
    if (!captchaToken) { setNotice('Please complete the captcha and submit again.'); return; }
    setNotice('');
    // Send to Web3Forms. Final normalised, strictly-typed payload.
    const dial = (COUNTRY_CODES.find(c => c.c === form.countryCode) || {}).code || '';
    setSending(true);
    try {
      await window.submitWeb3Form(window.WEB3FORMS.contact, {
        subject: `New enquiry from ${form.name || 'website visitor'} — Trips N Flys`,
        from_name: 'Trips N Flys Website',
        form_name: 'Contact — Customer Enquiry',
        name: InputGuard.line(form.name, 80),
        email: form.email,
        phone: `${dial} ${form.phone}`.trim(),
        service: form.service || '—',
        destination: form.destination || '—',
        travel_month: form.when || '—',
        travelers: InputGuard.int(form.travelers, 1, 30, 1),
        budget_per_person: form.budget || '—',
        message: form.message || '—',
        'h-captcha-response': captchaToken,
      });
    } catch (err) {
      setSending(false);
      captcha.reset();
      setNotice('Something went wrong sending your enquiry. Please try again, or call/WhatsApp us.');
      return;
    }
    captcha.reset();
    guard.accept();
    setSending(false);
    setDone(true);
    window.scrollTo({ top: window.scrollY, behavior: 'smooth' });
  };
  const errStyle = (k) => ({ ...inpC, borderColor: errors[k] ? '#D14343' : TNF.line });

  return (
    <section id="enquiry" style={{ padding: secPad(bp, 80, 56), background: '#fff', scrollMarginTop: 80 }}>
      <div style={{ maxWidth: 1200, margin: '0 auto', display: 'grid', gridTemplateColumns: bpv(bp, '1fr', '1fr 1.3fr', '1fr 1.4fr'), gap: bpv(bp, 32, 48, 80), alignItems: 'flex-start' }}>
        <div>
          <SectionEyebrow>Get in touch</SectionEyebrow>
          <H2 style={{ fontWeight: 700 }}>Tell us about<br/>your dream.</H2>
          <p style={{ fontSize: 16, color: TNF.inkSoft, marginTop: 24, lineHeight: 1.7, maxWidth: 420 }}>
            A travel consultant will reach out within the next 24 business hours.
          </p>

          <div style={{ marginTop: 40, padding: 24, background: TNF.cream, borderRadius: 16, border: `1px solid ${TNF.lineSoft}` }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
              <div style={{ width: 44, height: 44, borderRadius: 12, background: TNF.green, color: TNF.blueXdk, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon.clock width={20} height={20}/>
              </div>
              <div>
                <div style={{ fontWeight: 600, color: TNF.ink, fontSize: 15 }}>Office hours</div>
                <div style={{ fontSize: 13, color: TNF.inkSoft }}>Mon–Sat · 9 AM – 7 PM IST</div>
              </div>
            </div>
            <div style={{ marginTop: 16, paddingTop: 16, borderTop: `1px dashed ${TNF.line}`, fontSize: 13, color: TNF.inkSoft, lineHeight: 1.6 }}>
              On-trip support is <strong style={{ color: TNF.ink }}>24/7</strong> for active travellers — call or WhatsApp anytime.
            </div>
          </div>
        </div>

        <div style={{ background: TNF.cream, borderRadius: 22, padding: mob ? 22 : 40, border: `1px solid ${TNF.lineSoft}` }}>
          {done ? (
            <div style={{ textAlign: 'center', padding: '40px 0' }}>
              <div style={{ width: 64, height: 64, borderRadius: '50%', background: TNF.green, color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20 }}>
                <Icon.check width={32} height={32}/>
              </div>
              <h3 style={{ fontFamily: 'var(--tnf-display)', fontSize: 28, color: TNF.blueDk, margin: 0, fontWeight: 500 }}>
                We’re on it, {form.name.split(' ')[0] || 'traveler'}!
              </h3>
              <p style={{ color: TNF.inkSoft, fontSize: 15, lineHeight: 1.65, marginTop: 12, maxWidth: 460, marginLeft: 'auto', marginRight: 'auto' }}>
                A travel consultant will reach out within the next 24 business hours.
              </p>
              <button onClick={() => { setDone(false); setForm(EMPTY); setErrors({}); setNotice(''); guard.reset(); }}
                style={{ ...btnOutline({ small: true }), marginTop: 24 }}>
                Send another enquiry
              </button>
            </div>
          ) : (
            <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
              <HoneypotField value={guard.hp} onChange={guard.setHp}/>
              <div style={{ display: 'grid', gridTemplateColumns: mob ? '1fr' : '1fr 1fr', gap: 14 }}>
                <Field label="Full name *" error={errors.name}>
                  <input required value={form.name} onChange={e => update('name', e.target.value)} placeholder="Your name" maxLength={80} autoComplete="name" style={errStyle('name')}/>
                </Field>
                <Field label="Phone *" error={errors.phone}>
                  <div style={{ display: 'flex', gap: 8 }}>
                    <CountryCodePicker value={form.countryCode} onChange={v => update('countryCode', v)} triggerStyle={inpC}/>
                    <input required value={form.phone} onChange={e => update('phone', e.target.value)} placeholder="Phone number" inputMode="tel" autoComplete="tel" maxLength={24} style={{ ...errStyle('phone'), flex: 1 }}/>
                  </div>
                </Field>
              </div>
              <Field label="Email *" error={errors.email}>
                <input required type="email" value={form.email} onChange={e => update('email', e.target.value)} placeholder="you@email.com" maxLength={254} autoComplete="email" style={errStyle('email')}/>
              </Field>
              <Field label="Which service can we help with?">
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  {['Packages', 'Flights', 'Hotels', 'Visa', 'Other'].map(s => (
                    <button key={s} type="button" onClick={() => update('service', s)} style={qChipC(form.service === s)}>{s}</button>
                  ))}
                </div>
              </Field>
              <div style={{ display: 'grid', gridTemplateColumns: mob ? '1fr' : '1.4fr 1fr 1fr', gap: 14 }}>
                <Field label="Destination">
                  <input value={form.destination} onChange={e => update('destination', e.target.value)} placeholder="Sultanate of Oman" maxLength={80} style={inpC}/>
                </Field>
                <Field label="Travel month">
                  <input type="month" value={form.when} onChange={e => update('when', e.target.value)} min="2024-01" max="2030-12" style={inpC}/>
                </Field>
                <Field label="Travelers" error={errors.travelers}>
                  <input type="number" min={1} max={30} step={1} inputMode="numeric" value={form.travelers} onChange={e => update('travelers', e.target.value)} onBlur={e => update('travelers', e.target.value === '' ? 1 : e.target.value)} style={errStyle('travelers')}/>
                </Field>
              </div>
              <Field label="Budget per person (₹)">
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  {['Under 50k', '50k – 1L', '1L – 2L', '2L – 5L', '5L+'].map(b => (
                    <button key={b} type="button" onClick={() => update('budget', b)} style={qChipC(form.budget === b)}>{b}</button>
                  ))}
                </div>
              </Field>
              <Field label="Anything else we should know?">
                <textarea rows={4} value={form.message} onChange={e => update('message', e.target.value)} maxLength={1000} placeholder="Travel preferences, special occasions, must-do experiences..." style={{ ...inpC, resize: 'vertical', fontFamily: 'inherit' }}/>
              </Field>
              {notice && (
                <div role="alert" style={{ display: 'flex', alignItems: 'center', gap: 10, background: '#FBEAEA', color: '#9B2C2C', border: '1px solid #F0C9C9', borderRadius: 10, padding: '10px 14px', fontSize: 13, fontWeight: 500 }}>
                  <Icon.alert width={16} height={16}/> {notice}
                </div>
              )}
              <div ref={captchaRef} className="h-captcha" data-captcha="true"></div>
              <button type="submit" disabled={guard.cooldown > 0 || sending} style={{ ...btn(TNF.blueDk), marginTop: 8, justifyContent: 'center', width: '100%', padding: '16px 26px', opacity: (guard.cooldown > 0 || sending) ? 0.55 : 1, cursor: (guard.cooldown > 0 || sending) ? 'not-allowed' : 'pointer' }}>
                {sending ? 'Sending…' : guard.cooldown > 0 ? `Please wait ${guard.cooldown}s…` : <>Send enquiry <Icon.send width={16} height={16}/></>}
              </button>
              <div style={{ fontSize: 12, color: TNF.inkSoft, textAlign: 'center' }}>
                By submitting you agree to be contacted by Trips N Flys regarding your enquiry.
              </div>
            </form>
          )}
        </div>
      </div>
    </section>
  );
}

function Field({ label, children, error }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{ fontSize: 11, fontWeight: 600, color: error ? '#D14343' : TNF.inkSoft, letterSpacing: '0.08em', textTransform: 'uppercase' }}>{label}</span>
      {children}
      {error && <span role="alert" style={{ fontSize: 12, color: '#D14343', fontWeight: 500, textTransform: 'none', letterSpacing: 0 }}>{error}</span>}
    </label>
  );
}
const inpC = {
  width: '100%', padding: '12px 14px', border: `1px solid ${TNF.line}`,
  borderRadius: 10, fontSize: 14, fontFamily: 'inherit', outline: 'none',
  background: '#fff', color: TNF.ink, boxSizing: 'border-box',
};
function qChipC(active) {
  return {
    padding: '9px 16px', borderRadius: 999, minHeight: 40,
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    background: active ? TNF.blueDk : '#fff',
    color: active ? '#fff' : TNF.ink,
    border: `1px solid ${active ? TNF.blueDk : TNF.line}`,
    fontFamily: 'inherit', fontSize: 13, cursor: 'pointer', fontWeight: 500,
  };
}

const MAPS_QUERY = 'Vattuthottam+Complex,+Ernakulam+Road,+Piravom,+Ernakulam,+Kerala+686664';

function MapEmbed() {
  const R = (typeof window !== 'undefined' && window.__resources) || {};
  // Bundled OSM tile grid (3×3), inlined in the standalone/offline build. Always-safe base layer.
  const tiles = [];
  for (let row = 0; row < 3; row++) {
    for (let col = 0; col < 3; col++) {
      tiles.push({ col, row, src: R[`tile_${col}_${row}`] || null });
    }
  }
  const hasTiles = tiles.some(t => t.src);
  const [iframeOk, setIframeOk] = React.useState(false);
  // Only attempt the live iframe when the browser reports a connection.
  // Offline (e.g. the downloaded standalone file with no internet) we keep the bundled tiles.
  const online = typeof navigator === 'undefined' ? true : navigator.onLine;

  // Office point sits at (276, 271) within the 768×768 tile grid (tile 1,1 + offset).
  // Center it horizontally and place it ~vertically centered in the 460px viewport.
  const gridShiftX = 384 - 276; // +108: move marker to horizontal centre after translateX(-50%)
  const gridTop = 230 - 271;    // -41: bring marker to vertical centre of the 460px box

  return (
    <div style={{ height: 460, position: 'relative', background: TNF.cream, overflow: 'hidden' }}>
      {/* Base layer: composed static map (works offline). Clicking opens Google Maps. */}
      {hasTiles ? (
        <a
          href={`https://www.google.com/maps/search/?api=1&query=${MAPS_QUERY}`}
          target="_blank" rel="noopener"
          style={{ position: 'absolute', inset: 0, display: 'block' }}
          title="Open in Google Maps"
        >
          <div style={{
            position: 'absolute', width: 768, height: 768, top: gridTop, left: '50%',
            transform: `translateX(calc(-50% + ${gridShiftX}px))`,
          }}>
            {tiles.map(t => t.src ? (
              <img key={`${t.col}_${t.row}`} src={t.src} alt="" width={256} height={256}
                style={{ position: 'absolute', left: t.col * 256, top: t.row * 256, display: 'block' }}/>
            ) : null)}
          </div>
          {/* Marker pin at the office point (container centre, vertical centre) */}
          <div style={{ position: 'absolute', left: '50%', top: 230, transform: 'translate(-50%, -100%)', pointerEvents: 'none' }}>
            <svg width="34" height="44" viewBox="0 0 34 44" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ filter: 'drop-shadow(0 4px 6px rgba(11,38,48,0.35))' }}>
              <path d="M17 0C7.6 0 0 7.6 0 17c0 11.9 17 27 17 27s17-15.1 17-27C34 7.6 26.4 0 17 0z" fill={TNF.blueDk}/>
              <circle cx="17" cy="17" r="6.5" fill="#fff"/>
            </svg>
          </div>
          {/* OSM attribution (required) */}
          <div style={{ position: 'absolute', right: 6, bottom: 4, fontSize: 9, color: '#3A5560', background: 'rgba(255,255,255,0.7)', padding: '1px 5px', borderRadius: 4, pointerEvents: 'none' }}>
            © OpenStreetMap
          </div>
        </a>
      ) : (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', color: TNF.inkSoft, fontSize: 14 }}>
          Loading map…
        </div>
      )}
      {/* Enhancement layer: live, interactive Google map. Reveals only once it actually loads (i.e. online). */}
      {online ? (
        <iframe
          title="Trips N Flys office location"
          src={`https://www.google.com/maps?q=${MAPS_QUERY}&z=15&output=embed`}
          onLoad={() => setIframeOk(true)}
          style={{
            position: 'absolute', inset: 0, width: '100%', height: '100%', border: 0,
            opacity: iframeOk ? 1 : 0, transition: 'opacity 0.4s ease',
            pointerEvents: iframeOk ? 'auto' : 'none',
          }}
          loading="lazy"
          referrerPolicy="no-referrer-when-downgrade"
          allowFullScreen
        />
      ) : null}
    </div>
  );
}

function MapSection() {
  const bp = useBP();
  return (
    <section id="map" style={{ padding: secPad(bp, 80, 56), background: TNF.cream }}>
      <div style={{ maxWidth: 1200, margin: '0 auto' }}>
        <div style={{ textAlign: 'center', marginBottom: 32 }}>
          <SectionEyebrow>Visit us</SectionEyebrow>
          <H2 style={{ fontWeight: 700 }}>Find our office<br/>in Piravom.</H2>
        </div>
        <div style={{
          background: '#fff', borderRadius: 22, overflow: 'hidden',
          border: `1px solid ${TNF.lineSoft}`,
          display: 'grid', gridTemplateColumns: bpv(bp, '1fr', '1.3fr 1fr', '1.4fr 1fr'),
        }}>
          {/* Map: bundled static image as offline-safe base; live Google iframe layered on top when online */}
          <MapEmbed/>
          <div style={{ padding: bp === 'mobile' ? '28px 24px' : '40px 36px', display: 'flex', flexDirection: 'column', gap: 18 }}>
            <div>
              <div style={{ fontSize: 11, color: TNF.greenDk, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase' }}>Office address</div>
              <div style={{ fontFamily: 'var(--tnf-display)', fontSize: 26, color: TNF.blueDk, marginTop: 8, fontWeight: 500, lineHeight: 1.25 }}>
                First Floor<br/>
                Vattuthottam Complex
              </div>
              <div style={{ fontSize: 14, color: TNF.inkSoft, marginTop: 8, lineHeight: 1.6 }}>
                Ernakulam Road, Piravom<br/>
                Ernakulam – 686664<br/>
                Kerala, India
              </div>
            </div>
            <div style={{ borderTop: `1px dashed ${TNF.line}`, paddingTop: 18, display: 'flex', flexDirection: 'column', gap: 10, fontSize: 14 }}>
              <a href="tel:+916238983511" style={{ color: TNF.ink, textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 10 }}>
                <Icon.phone width={14} height={14} style={{ color: TNF.blueDk }}/> +91 6238 983 511
              </a>
              <a href="mailto:info@tripsnflys.com" style={{ color: TNF.ink, textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 10 }}>
                <Icon.mail width={14} height={14} style={{ color: TNF.blueDk }}/> info@tripsnflys.com
              </a>
              <div style={{ color: TNF.ink, display: 'flex', alignItems: 'center', gap: 10 }}>
                <Icon.clock width={14} height={14} style={{ color: TNF.blueDk }}/> Mon–Sat · 9 AM – 7 PM IST
              </div>
            </div>
            <a href="https://www.google.com/maps/search/?api=1&query=Vattuthottam+Complex,+Ernakulam+Road,+Piravom,+Ernakulam,+Kerala+686664" target="_blank" rel="noopener" style={{ ...btn(TNF.blueDk, { small: true }), alignSelf: 'flex-start' }}>
              Open in Google Maps <Icon.arrowDiag width={14} height={14}/>
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

function ContactPage() {
  // Arriving from another page at contact.html#enquiry (e.g. the Destinations CTAs):
  // React renders the DOM after load, so the browser's native hash scroll misses the
  // target. Scroll to it ourselves once mounted, and on later hash changes.
  React.useEffect(() => {
    const scrollToHash = () => {
      const id = (window.location.hash || '').slice(1);
      if (!id) return;
      const el = document.getElementById(id);
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };
    requestAnimationFrame(scrollToHash);
    window.addEventListener('hashchange', scrollToHash);
    return () => window.removeEventListener('hashchange', scrollToHash);
  }, []);

  return (
    <SiteShell active="Contact" overHero={true}>
      <PageHero
        eyebrow="Get in touch"
        title={<>Let’s plan<br/>something special.</>}
        lede="Reach us however you like — phone, WhatsApp, email, or a walk-in. We typically respond within an hour during business hours."
        photo="desk"
        height={480}
      />
      <ContactDetails/>
      <ContactFormSection/>
      <MapSection/>
      <FAQSection/>
    </SiteShell>
  );
}
window.ContactPage = ContactPage;
