const odoT = (en,ar) => document.documentElement.lang === 'ar' || document.documentElement.dir === 'rtl' ? ar : en;
function OdometerLocation({assessment}) {
  if (!assessment) return null;
  const outside = assessment.status === 'outside', inside = assessment.status === 'inside', p = assessment.point;
  return <div className={'odo-location '+(outside?'outside':inside?'inside':'unknown')} role={outside?'alert':'status'}>
    <b>{outside ? odoT('End location outside the 1 km customer area','موقع إنهاء الزيارة خارج نطاق كيلومتر من العميل') : inside ? odoT('Within the 1 km customer area','داخل نطاق كيلومتر من العميل') : odoT('Customer proximity could not be verified','تعذّر التحقق من القرب من العميل')}</b>
    {assessment.distanceMetres != null && <span> · {(assessment.distanceMetres/1000).toFixed(2)} {odoT('km from customer','كم من العميل')} · ±{assessment.accuracy} {odoT('m','م')}</span>}
    {outside && <small>{odoT('Warning only. Visit end is allowed; management can review the location.','تنبيه فقط: يمكن إنهاء الزيارة، ويظهر الموقع للإدارة للمراجعة.')}</small>}
    {p && <a href={'https://www.google.com/maps?q='+p.latitude+','+p.longitude} target="_blank" rel="noopener noreferrer">{odoT('Recorded end location','موقع نهاية الزيارة المسجّل')}</a>}
  </div>;
}
function OdometerVisitPanel({type,start,geo,onChange,onPending=()=>{}}) {
  const [enabled,setEnabled] = React.useState(false), [ctx,setCtx] = React.useState(null), [camera,setCamera] = React.useState(false);
  const [photo,setPhoto] = React.useState(''), [value,setValue] = React.useState(''), [ocr,setOcr] = React.useState('');
  const [unit,setUnit] = React.useState('km'), [vehicle,setVehicle] = React.useState(''), [accepted,setAccepted] = React.useState(false);
  const [busy,setBusy] = React.useState(false), [error,setError] = React.useState(''), [crop,setCrop] = React.useState(0.28);
  const video = React.useRef(null), stream = React.useRef(null), alive = React.useRef(true), generation = React.useRef(0);
  const O = window.HydorOdometerModel, end = type === 'visit_end', first = ctx?.readings?.find(r=>r.phase === 'visit_start');
  const stop = () => { if(stream.current) stream.current.getTracks().forEach(t=>t.stop()); stream.current=null; };
  React.useEffect(()=>{
    let live=true;alive.current=true;
    HydorAPI.get('/odometer/status').then(s=>{if(live)setEnabled(s.enabled===true);}).catch(()=>{});
    if(start && window.HydorOdometer) HydorOdometer.context(start).then(c=>{if(live){setCtx(c);const a=c.readings.find(r=>r.phase==='visit_start');if(a){setUnit(a.unit);setVehicle(a.vehicle);}}});
    return()=>{live=false;alive.current=false;generation.current++;stop();};
  },[]);
  React.useEffect(()=>{
    if(!camera)return;
    let live=true;
    Promise.resolve().then(()=>navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:'environment'},width:{ideal:1280}},audio:false})).then(s=>{
      if(!live){s.getTracks().forEach(t=>t.stop());return;} stream.current=s;
      if(video.current){video.current.srcObject=s;video.current.play().catch(()=>{});}
    }).catch(()=>{if(live){setError(odoT('Camera unavailable. You may skip this trial.','تعذّر فتح الكاميرا. يمكنك تجاوز التجربة.'));setCamera(false);}});
    return()=>{live=false;stop();};
  },[camera]);
  React.useEffect(()=>{onPending((!!photo || camera) && !accepted);},[photo,camera,accepted]);
  const change = fn => {fn();setAccepted(false);onChange(null);};
  async function capture(){
    const v=video.current;if(!v?.videoWidth)return;
    const c=document.createElement('canvas'), w=v.videoWidth*.8,h=v.videoHeight*crop;
    c.width=Math.min(960,Math.round(w));c.height=Math.round(h*c.width/w);
    c.getContext('2d').drawImage(v,v.videoWidth*.1,(v.videoHeight-h)/2,w,h,0,0,c.width,c.height);
    const data=c.toDataURL('image/jpeg',.8);
    if(data.length>280000){setError(odoT('Image too large; move closer and retake.','الصورة كبيرة؛ اقترب من العداد وأعد التصوير.'));return;}
    stop();setCamera(false);setPhoto(data);setValue('');setOcr('');setAccepted(false);onChange(null);setBusy(true);setError('');const gen=++generation.current;
    try {const r=await HydorOdometer.recognize(data);if(alive.current && gen===generation.current){setOcr(r.text);setValue(r.value);}}
    catch {if(alive.current && gen===generation.current)setError(odoT('Automatic reading unavailable. Enter the number from the image.','تعذّرت القراءة التلقائية. أدخل الرقم الظاهر في الصورة.'));}
    finally{if(alive.current && gen===generation.current)setBusy(false);}
  }
  const n=O?.reading(value), diff=O?.difference(first,{reading_milli:n,unit,vehicle});
  const assessment=end && ctx ? O.endpoint(geo && Date.now()-geo.capturedAt<120000?{lat:geo.lat,lon:geo.lon,accuracy:geo.acc}:null,ctx.destination):null;
  const valid=!!photo && n!=null && vehicle.trim() && !busy;
  function confirmReading(){
    if(!valid)return;
    setAccepted(true);onChange({photo,reading:value,unit,vehicle:vehicle.trim(),ocrText:ocr,confirmed:true,
      confirmedMetres:end && diff.status==='confirmed'?diff.metres:null});
  }
  if(!enabled)return null;
  return <section className="odo-panel" aria-label={odoT('Optional odometer trial','تجربة العداد الاختيارية')}>
    <h3>{odoT('Odometer · optional trial','عداد السيارة · تجربة اختيارية')}</h3>
    <p>{odoT('Use the TOTAL odometer, not the resettable trip meter. Photograph only while safely parked.','صوّر عداد المسافة الكلي، وليس عداد الرحلة القابل للتصفير. التصوير والسيارة متوقفة بأمان فقط.')}</p>
    <OdometerLocation assessment={assessment}/>
    {!photo && !camera && <button type="button" className="btn" onClick={()=>{setCamera(true);setError('');}}>{odoT('Open odometer camera','فتح كاميرا العداد')}</button>}
    {camera && <><div className="odo-camera"><video ref={video} muted playsInline/><div className="odo-frame" style={{height:(crop*100)+'%',top:((1-crop)*50)+'%'}}/></div>
      <label>{odoT('Frame height','ارتفاع إطار العداد')}<input type="range" min="0.15" max="0.55" step="0.01" value={crop} onChange={e=>setCrop(Number(e.target.value))}/></label>
      <button type="button" className="btn" onClick={capture}>{odoT('Capture digits','التقاط أرقام العداد')}</button></>}
    {photo && <><img className="odo-crop" src={photo} alt={odoT('Cropped odometer','صورة العداد المقصوصة')}/>
      <div className="odo-fields"><label>{odoT('Vehicle reference / plate','السيارة / رقم اللوحة')}<input className="inp" maxLength={80} value={vehicle} onChange={e=>change(()=>setVehicle(e.target.value))}/></label>
      <label>{odoT('Odometer reading','قراءة العداد')}<input className="inp" inputMode="decimal" maxLength={11} value={value} onChange={e=>change(()=>setValue(e.target.value))}/></label>
      <label>{odoT('Unit shown on odometer','الوحدة الظاهرة على العداد')}<select className="sel" value={unit} onChange={e=>change(()=>setUnit(e.target.value))}><option value="km">km</option><option value="mi">mi</option></select></label></div>
      {busy && <p role="status">{odoT('Reading digits… You can skip the trial.','جارٍ قراءة الأرقام… يمكنك تجاوز التجربة.')}</p>}
      {end && <p className="odo-difference">{diff.status==='confirmed'?<>{odoT('Visit distance','مسافة الزيارة')}: <b>{(diff.metres/1000).toFixed(3)} {odoT('km','كم')}</b></>:odoT('The start/end readings are incomplete or inconsistent; distance needs review.','قراءات البداية والنهاية ناقصة أو غير متطابقة؛ المسافة تحتاج مراجعة.')}</p>}
      <button type="button" className="btn" disabled={!valid || accepted} onClick={confirmReading}>{accepted?odoT('Confirmed','تم التأكيد'):end && diff.status==='confirmed'?odoT('I confirm this visit distance','أوافق على عدد كيلومترات هذه الزيارة'):odoT('I confirm this reading','أؤكد صحة قراءة العداد')}</button>
      <button type="button" className="btn sm" onClick={()=>{generation.current++;setBusy(false);change(()=>setPhoto(''));setCamera(true);}}>{odoT('Retake','إعادة التصوير')}</button></>}
    {error && <p role="alert">{error}</p>}
    {(photo || camera) && <button type="button" className="btn sm" onClick={()=>{generation.current++;setBusy(false);stop();setCamera(false);setPhoto('');setAccepted(false);onChange(null);}}>{odoT('Skip odometer for this visit','تجاوز العداد لهذه الزيارة')}</button>}
    <small>{odoT('Confirm the reading or choose Skip to continue without it. The odometer trial is optional.','أكّد القراءة أو اختر تجاوز للمتابعة دونها. تجربة العداد اختيارية.')}</small>
  </section>;
}
function OdometerQueueStatus(){
  const [rows,setRows]=React.useState([]);
  React.useEffect(()=>{if(!window.HydorOdometer)return;let live=true;const read=()=>HydorOdometer.list().then(r=>{if(live)setRows(r);}).catch(()=>{});read();const off=HydorOdometer.subscribe(read);return()=>{live=false;off();};},[]);
  if(!rows.length)return null;
  return <div className="odo-location unknown" role="status">{odoT('Odometer/location evidence awaiting server sync','إثباتات العداد/الموقع بانتظار المزامنة مع الخادم')}: {rows.length} <button className="btn sm" onClick={()=>HydorOdometer.flush()}>{odoT('Retry','إعادة المحاولة')}</button></div>;
}
function OdometerEvidence({data,assessment,paid=false}){
  const [images,setImages]=React.useState({}),[error,setError]=React.useState('');
  if(!data && !assessment)return null;
  const load=async id=>{try{const r=await HydorAPI.get('/odometer/image/'+encodeURIComponent(id));setImages(v=>({...v,[id]:r.photo}));}catch{setError(odoT('Image unavailable or already deleted after payment','الصورة غير متاحة أو حُذفت بعد الدفع'));}};
  return <div><OdometerLocation assessment={assessment}/>{data && <details><summary>{odoT('Odometer evidence','إثبات العداد')} · {data.confirmed?odoT('Employee confirmed','مؤكد من الموظف'):odoT('Incomplete / review needed','ناقص / يحتاج مراجعة')}</summary>
    {data.readings.map(r=><div key={r.attendance_id}><p>{r.phase==='visit_start'?odoT('Start','البداية'):odoT('End','النهاية')}: {(Number(r.reading_milli)/1000).toFixed(3)} {r.unit} · {r.vehicle}</p><small>{odoT('Original OCR','القراءة التلقائية الأصلية')}: {r.ocr_text || '—'}</small>{!paid && <button type="button" className="btn sm" onClick={()=>load(r.attendance_id)}>{odoT('Review image','مراجعة الصورة')}</button>}{!paid && images[r.attendance_id] && <img className="odo-crop" src={images[r.attendance_id]} alt={odoT('Odometer evidence','إثبات العداد')}/>}</div>)}
    {paid && <p>{odoT('Odometer images deleted after payment; confirmed readings retained.','حُذفت صور العداد بعد الدفع؛ القراءات المؤكدة محفوظة.')}</p>}
    {!data.readings.length && <p>{odoT('No odometer readings attached','لا توجد قراءات عداد مرفقة')}</p>}{error && <p role="alert">{error}</p>}</details>}</div>;
}
function OdometerEndWarnings({date,onRows}){
  const [rows,setRows]=React.useState([]),[stale,setStale]=React.useState(false);
  React.useEffect(()=>{setRows([]);setStale(false);let live=true,pending=false;const run=async()=>{if(pending || document.hidden)return;pending=true;try{const r=await HydorAPI.get('/odometer/end-locations?day='+date);if(live){setRows(r.rows || []);setStale(false);}}catch{if(live)setStale(true);}finally{pending=false;}};run();const timer=setInterval(run,30000);return()=>{live=false;clearInterval(timer);};},[date]);
  const outside=rows.filter(r=>r.assessment.status==='outside');
  React.useEffect(()=>{if(onRows)onRows(rows);},[rows,onRows]);
  if(!outside.length)return null;
  return <section className="odo-panel"><h3>{odoT('Visits ended outside customer area','زيارات انتهت خارج نطاق العميل')}</h3>{stale && <p>{odoT('Refresh unavailable; showing the last received warnings.','تعذّر التحديث؛ تُعرض آخر التنبيهات المستلمة.')}</p>}{outside.map(r=><div key={r.attendance_id}><b>{r.name}</b><OdometerLocation assessment={r.assessment}/></div>)}</section>;
}
function OdometerRecentEnd({entry}){
  const [assessment,setAssessment]=React.useState(null);
  React.useEffect(()=>{setAssessment(null);if(!entry || !window.HydorOdometer)return;let live=true,pending=false;const read=async()=>{if(pending)return;pending=true;try{const c=await HydorOdometer.context(entry);if(live)setAssessment(c.endLocation || null);}finally{pending=false;}};read();const off=HydorOdometer.subscribe(read);return()=>{live=false;off();};},[entry?.id]);
  return assessment?<section className="odo-panel"><b>{odoT('Last completed visit · recorded location','آخر زيارة مكتملة · الموقع المسجّل')}</b><OdometerLocation assessment={assessment}/></section>:null;
}
