<script>
  // Qibla direction — pure client-side great-circle bearing calculation from
  // the device's GPS to the Kaaba. No API, no key, no external service:
  // this is closed-form spherical trigonometry, not a lookup.
  import Disclaimer from './Disclaimer.svelte';
  import InfoPanel from './InfoPanel.svelte';

  const KAABA_LAT = 21.4225;
  const KAABA_LON = 39.8262;

  let status = $state('idle'); // idle | locating | ready | error
  let errorMsg = $state('');
  let bearing = $state(null); // degrees from true north, 0-360
  let distanceKm = $state(null);
  let compassHeading = $state(null); // device heading, if sensor available
  let compassSupported = $state(false);

  function toRad(deg) { return (deg * Math.PI) / 180; }
  function toDeg(rad) { return (rad * 180) / Math.PI; }

  function computeQibla(lat, lon) {
    const phi1 = toRad(lat), phi2 = toRad(KAABA_LAT);
    const dLambda = toRad(KAABA_LON - lon);
    const y = Math.sin(dLambda) * Math.cos(phi2);
    const x = Math.cos(phi1) * Math.sin(phi2) - Math.sin(phi1) * Math.cos(phi2) * Math.cos(dLambda);
    let theta = toDeg(Math.atan2(y, x));
    bearing = (theta + 360) % 360;

    // Haversine distance
    const R = 6371;
    const dPhi = toRad(KAABA_LAT - lat);
    const a = Math.sin(dPhi / 2) ** 2 + Math.cos(phi1) * Math.cos(phi2) * Math.sin(dLambda / 2) ** 2;
    distanceKm = Math.round(R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
  }

  let listenersAttached = false;

  function handleOrientation(e) {
    let heading = e.webkitCompassHeading;
    if (heading == null && e.alpha != null) {
      // Prefer a true geomagnetic reading when the browser provides one
      // (absolute: true), but don't require it — many Android browsers
      // never set absolute:true even though alpha is still a usable
      // heading, so requiring it strictly left the compass permanently
      // "undetected" on those devices.
      heading = 360 - e.alpha;
    }
    if (heading != null) { compassHeading = heading; compassSupported = true; }
  }

  function attachOrientationListeners() {
    if (listenersAttached) return;
    listenersAttached = true;
    window.addEventListener('deviceorientationabsolute', handleOrientation, true);
    window.addEventListener('deviceorientation', handleOrientation, true);
  }

  async function findQibla() {
    status = 'locating';
    errorMsg = '';
    compassSupported = false;
    compassHeading = null;

    // Request device-orientation permission (iOS 13+) synchronously here,
    // inside this click handler — Safari expires the user-activation grant
    // almost immediately, so requesting it *after* the async geolocation
    // round-trip (which can take several seconds) reliably fails silently
    // with no prompt ever shown. Registering listeners for everyone else
    // immediately too, so no early orientation events are missed while
    // still waiting on the GPS fix.
    if (typeof DeviceOrientationEvent !== 'undefined') {
      if (typeof DeviceOrientationEvent.requestPermission === 'function') {
        try {
          const perm = await DeviceOrientationEvent.requestPermission();
          if (perm === 'granted') attachOrientationListeners();
        } catch { /* denied or unsupported — static bearing still shown */ }
      } else {
        attachOrientationListeners();
      }
    }

    if (!navigator.geolocation) {
      status = 'error'; errorMsg = 'Geolocation is not available on this device/browser.';
      return;
    }
    navigator.geolocation.getCurrentPosition(
      (pos) => { computeQibla(pos.coords.latitude, pos.coords.longitude); status = 'ready'; },
      (err) => { status = 'error'; errorMsg = err.message || 'Could not get your location.'; },
      { enableHighAccuracy: true, timeout: 10000 }
    );
  }

  const needleRotation = $derived(compassSupported && compassHeading != null && bearing != null ? bearing - compassHeading : bearing);
</script>

<div class="module">
  <div class="module-header">
    <h2>Qibla</h2>
    <InfoPanel
      title="Qibla"
      what="The direction to face for prayer, calculated as the great-circle bearing from your current location to the Kaaba in Makkah — computed on your device, not looked up from a database."
      how="Tap to find your direction. If your device has a compass sensor and grants permission, the arrow rotates live as you turn; otherwise you'll see the bearing in degrees from true north to align with a separate compass."
      fields={[]}
    />
  </div>
  <p class="sub">Great-circle bearing to the Kaaba, calculated from your device's location.</p>

  {#if status === 'idle'}
    <button class="btn-primary" onclick={findQibla}>Find Qibla direction</button>
  {:else if status === 'locating'}
    <p class="status-text">Getting your location…</p>
  {:else if status === 'error'}
    <p class="error-text">{errorMsg}</p>
    <button class="btn-primary" onclick={findQibla}>Try again</button>
  {:else if status === 'ready'}
    <div class="compass-card">
      <div class="compass-rose">
        <div class="needle" style="transform: rotate({needleRotation}deg)">
          <div class="needle-tip">◆</div>
        </div>
        <span class="compass-n">N</span>
      </div>
      <div class="bearing-readout">
        <strong>{Math.round(bearing)}°</strong>
        <span>from true north</span>
      </div>
      {#if !compassSupported}
        <p class="static-note">No live compass sensor detected — hold a compass app or physical compass and align it to {Math.round(bearing)}°.</p>
      {/if}
      <p class="distance-note">~{distanceKm?.toLocaleString()} km to Makkah</p>
    </div>
    <button class="btn-secondary" onclick={findQibla}>Refresh location</button>
  {/if}

  <Disclaimer text="A calculated bearing, not a certified qibla marker. Verify against a known qibla direction (e.g. your local mosque) where precision matters." />
</div>

<style>
  .module { padding: 4px 0 40px; }
  .module-header { display: flex; align-items: center; margin-bottom: 4px; }
  h2 { font-family: 'DM Serif Display', serif; font-size: 24px; color: #E8E4DC; margin-bottom: 0; }
  .sub { font-size: 13px; color: #8A8478; margin-bottom: 18px; }
  .btn-primary { width: 100%; padding: 14px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; background: #C9A84C; color: #070A0D; }
  .btn-secondary { width: 100%; padding: 12px; border-radius: 8px; border: 1px solid rgba(201,168,76,0.3); font-weight: 600; cursor: pointer; background: rgba(255,255,255,0.05); color: #C9A84C; margin-top: 14px; }
  .status-text { font-size: 13px; color: #8A8478; text-align: center; padding: 30px 0; }
  .error-text { font-size: 13px; color: #EF4444; margin-bottom: 12px; }
  .compass-card { display: flex; flex-direction: column; align-items: center; padding: 20px; background: rgba(255,255,255,0.03); border-radius: 16px; }
  .compass-rose { position: relative; width: 200px; height: 200px; border-radius: 50%; border: 2px solid rgba(201,168,76,0.3); display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
  .needle { position: absolute; width: 4px; height: 90px; background: linear-gradient(#C9A84C, transparent); top: 10px; left: 50%; margin-left: -2px; transform-origin: bottom center; transition: transform 0.2s ease-out; }
  .needle-tip { position: absolute; top: -14px; left: -9px; font-size: 20px; color: #C9A84C; }
  .compass-n { position: absolute; top: 8px; font-size: 11px; color: #8A8478; }
  .bearing-readout { display: flex; flex-direction: column; align-items: center; margin-bottom: 8px; }
  .bearing-readout strong { font-family: 'DM Serif Display', serif; font-size: 32px; color: #C9A84C; }
  .bearing-readout span { font-size: 11px; color: #8A8478; }
  .static-note { font-size: 12px; color: #B8B2A6; text-align: center; margin-bottom: 8px; line-height: 1.5; }
  .distance-note { font-size: 11px; color: #8A8478; }
</style>
