// ===== Helper Dashboard =====

const HelperDashPage = ({ go, subscription, logout, me: sessionMe }) => {
  const { t } = window.useI18n();
  // Default landing section is 'profile' — the previous Overview page was
  // mostly mock stats with no real signal value, so it was removed.
  const [section, setSection] = React.useState('profile');
  const { jobs } = window.MOCK_DATA;
  const [candidateProfile, setCandidateProfile] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    const loadProfile = async () => {
      if (!window.HelperMatchApi?.getToken?.() || !window.HelperMatchApi?.getCandidateProfile) return;
      try {
        const profile = await window.HelperMatchApi.getCandidateProfile();
        if (!cancelled) setCandidateProfile(profile);
      } catch (error) {
        if (!cancelled && error?.status !== 401 && error?.status !== 403) {
          console.warn('Could not load candidate profile', error);
        }
      }
    };
    loadProfile();
    return () => { cancelled = true; };
  }, []);

  const profileName = candidateProfile?.display_name || sessionMe?.candidate?.display_name || getUserDisplayName(sessionMe, 'Helper');
  const me = {
    id: candidateProfile?.id || sessionMe?.candidate?.id || 'me',
    name: profileName,
    initials: getUserInitials(sessionMe, profileName.slice(0, 2).toUpperCase()),
    photoUrl: candidateProfile?.photo_data_url || null,
    birthday: candidateProfile?.birthday || '',
    age: candidateProfile?.age || '',
    flag: ({ Indonesia: '🇮🇩', Philippines: '🇵🇭' })[candidateProfile?.nationality] || '',
    nationality: candidateProfile?.nationality || '',
    city: candidateProfile?.city || '',
    position: candidateProfile?.position || 'Domestic Helper',
    jobTypes: candidateProfile?.job_types?.length ? candidateProfile.job_types : [candidateProfile?.position || 'Domestic Helper'],
    typedSkills: {
      languages: candidateProfile?.languages || [],
      mainSkills: candidateProfile?.main_skills || [],
      cookingSkills: candidateProfile?.cooking_skills || [],
      otherSkills: candidateProfile?.other_skills || [],
      personality: candidateProfile?.personality || [],
    },
    demographics: {
      maritalStatus: candidateProfile?.marital_status,
      kids: candidateProfile?.kids,
      religion: candidateProfile?.religion,
      education: candidateProfile?.education,
    },
    yearsExperience: candidateProfile?.years_experience,
    experience: candidateProfile?.years_experience ? `${candidateProfile.years_experience} years` : '',
    contractStatus: candidateProfile?.contract_status,
    availableDate: candidateProfile?.available_date,
    expectations: {
      salary: candidateProfile?.expected_salary,
      accommodation: candidateProfile?.accommodation,
      dayOff: candidateProfile?.day_off,
    },
    locationCountry: candidateProfile?.preferred_markets?.join(', '),
    workExperiences: candidateProfile?.work_experiences || [],
    bio: candidateProfile?.bio || '',
    introVideo: candidateProfile?.intro_video,
    completeness: candidateProfile?.completeness ?? sessionMe?.candidate?.completeness ?? 0,
    verification: 'self',
    color: '#48B8A0',
  };
  const applications = [];

  return (
    <div className="page container-wide dash-layout">
      {/* Sidebar */}
      <aside className="dash-side">
        <div style={{display:'flex', alignItems:'center', gap:10, padding:'12px 14px', marginBottom:12, background:'var(--t-paper)', border:'1px solid var(--t-line)', borderRadius:12}}>
          <Avatar person={me} size={40}/>
          <div style={{minWidth:0}}>
            <div style={{fontSize:13, fontWeight:600, display:'flex', alignItems:'center', gap:4}}>
              {me.name}
              <Icon name="verified" size={11} style={{color:'var(--trust)'}}/>
            </div>
            <div style={{fontSize:11, color:'var(--t-ink-muted)', display:'flex', alignItems:'center', gap:4}}>
              {[me.flag && me.nationality ? `${me.flag} ${me.nationality}` : '', 'Active now'].filter(Boolean).join(' · ')}
            </div>
          </div>
        </div>
        <div className="dash-nav">
          {[
            {id:'profile', label: t('helperDash.nav.profile'), icon:'user'},
            {id:'matches', label: t('helperDash.nav.matches'), icon:'sparkle'},
            {id:'applications', label: t('helperDash.nav.applications'), icon:'briefcase', count:applications.length},
            {id:'saved', label: t('helperDash.nav.savedJobs'), icon:'heart', count:3},
            {id:'earnings', label: t('helperDash.nav.earnings'), icon:'coin'},
            {id:'settings', label: t('helperDash.nav.settings'), icon:'settings'},
          ].map(n => (
            <button key={n.id} className={`dash-nav-item ${section===n.id?'active':''}`} onClick={()=>setSection(n.id)}>
              <Icon name={n.icon} size={16}/>
              {n.label}
              {n.count != null && <span className="badge-count">{n.count}</span>}
            </button>
          ))}
        </div>
        <div style={{marginTop:20, padding:16, background:'var(--trust-bg)', border:'1px solid var(--trust-soft)', borderRadius:12}}>
          <div style={{fontSize:12, fontWeight:700, color:'var(--trust-ink)', marginBottom:6, display:'flex', alignItems:'center', gap:6}}>
            <Icon name="shield" size={12}/> Helper Support
          </div>
          <div style={{fontSize:12, color:'var(--t-ink-muted)', lineHeight:1.5, marginBottom:10}}>
            Questions about your application or contract? Our team replies in Bahasa, Tagalog & English.
          </div>
          <button className="btn btn-outline btn-sm btn-block" style={{fontSize:12}}>Get help</button>
        </div>
        {logout && (
          <button
            onClick={logout}
            className="dash-nav-item"
            style={{marginTop:16, color:'var(--t-ink-muted)', justifyContent:'flex-start'}}
            title={t('dash.signOutTitle')}
          >
            <Icon name="arrowLeft" size={16}/>
            {t('dash.signOut')}
          </button>
        )}
      </aside>

      {/* Main content */}
      <div>
        {section === 'profile' && <HelperProfile me={me} go={go}/>}
        {section === 'matches' && <HelperMatches go={go} me={me} matchedJobs={jobs}/>}
        {section === 'applications' && <HelperApplications go={go} applications={applications}/>}
        {section === 'saved' && <HelperSaved go={go} jobs={jobs.slice(0, 3)}/>}
        {section === 'earnings' && <HelperEarnings/>}
        {section === 'settings' && <HelperAccount me={me}/>}
      </div>
    </div>
  );
};

// ===== Profile =====
const HelperProfile = ({ me, go }) => {
  const { t } = window.useI18n();
  const tax = window.SKILL_TAXONOMY;
  const d = me.demographics || {};
  const ts = me.typedSkills || {};
  const isOfficial = me.verification === 'official';
  const officialVideoCount = me.videos ? Object.values(me.videos).filter(Boolean).length : 0;
  const hasIntroVideo = !!me.introVideo;

  // Review status from CANDIDATE_REVIEW_FLOW.md. Read once + listen for the
  // hm-review-status-changed event so admin Approve/Reject in another tab
  // updates the banner live.
  const readStatus = () => {
    try { return localStorage.getItem('hm_review_status') || 'approved'; } catch(e) { return 'approved'; }
  };
  const [reviewStatus, setReviewStatus] = React.useState(readStatus);
  React.useEffect(() => {
    const sync = () => setReviewStatus(readStatus());
    window.addEventListener('storage', sync);
    window.addEventListener('hm-review-status-changed', sync);
    return () => { window.removeEventListener('storage', sync); window.removeEventListener('hm-review-status-changed', sync); };
  }, []);
  const rejectReason = (() => { try { return localStorage.getItem('hm_review_reject_reason') || ''; } catch(e) { return ''; } })();
  // Mirrors the ReqGroup component on the JobDetailPage / SkillsGroup on the
  // CandidateDetailPage. Section header: 40×40 disc + line-art SkillIcon at
  // 24 (uses `cat-X` dash ids so it falls through to the legacy monochrome
  // set, matching the public-facing detail pages). Chips: outline pill +
  // 26×26 disc + FlatIcon (or flag emoji for languages) + 13px label.
  const PILL_HEADER_ICON = {
    language: 'cat-language',
    main:     'cat-main',
    cooking:  'cat-cooking',
    other:    'cat-other',
    personality: 'cat-personality',
  };
  const PillGroup = ({title, category = 'main', items, lookup}) => {
    const c = window.SKILL_CAT_COLORS[category] || window.SKILL_CAT_COLORS.main;
    const enriched = (items || []).map(id => lookup?.find(x => x.id === id) || {id, label: id});
    if (enriched.length === 0) return null;
    const itemLabel = (x) => window.pickLocalised(x, 'label') || x.label || x.id;
    const headerIconKey = PILL_HEADER_ICON[category];
    return (
      <div>
        <div style={{display:'flex', alignItems:'center', gap:11, marginBottom:14}}>
          {headerIconKey && (
            <span style={{display:'grid', placeItems:'center', width:40, height:40, borderRadius:10, background:c.bg, color:c.fg, flexShrink:0}}>
              <window.SkillIcon name={headerIconKey} size={24}/>
            </span>
          )}
          <h4 className="display" style={{fontSize:15, fontWeight:600, letterSpacing:'-0.01em', color:'var(--t-ink)', margin:0}}>{title}</h4>
        </div>
        <div style={{display:'flex', flexWrap:'wrap', gap:7}}>
          {enriched.map(x => {
            const flatDef = window.FLAT_ICONS && window.FLAT_ICONS[x.id];
            const discBg = flatDef && window.CAT_BG ? (window.CAT_BG[flatDef.cat] || c.bg) : c.bg;
            const isLang = category === 'language';
            return (
              <div key={x.id} style={{
                display:'inline-flex', alignItems:'center', gap:8,
                padding:'4px 13px 4px 4px', background:'var(--t-paper)',
                border:'1px solid var(--t-line)', borderRadius:99, fontSize:13,
              }}>
                <span style={{
                  display:'grid', placeItems:'center', width:26, height:26, borderRadius:99,
                  background: discBg, color: c.fg, flexShrink:0,
                  fontSize: isLang ? 15 : undefined, lineHeight: 1,
                }}>
                  {isLang
                    ? (x.flag || null)
                    : (flatDef
                        ? <window.FlatIcon name={x.id} size={18}/>
                        : <window.SkillIcon name={x.id} size={14}/>)}
                </span>
                <span style={{fontWeight:500, whiteSpace:'nowrap'}}>{itemLabel(x)}</span>
              </div>
            );
          })}
        </div>
      </div>
    );
  };

  return (
    <div>
      <div className="dash-header" style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start'}}>
        <div>
          <h1>My profile</h1>
          <p>This is what families see when they view your profile. Keep it accurate and up-to-date.</p>
        </div>
        <button className="btn btn-trust btn-sm" onClick={()=>go && go('create-profile')}>
          <Icon name="edit" size={13}/> Edit resume
        </button>
      </div>

      {/* Review status banner — surfaces where the helper is in the
          approval pipeline (see CANDIDATE_REVIEW_FLOW.md). Hidden when
          status is 'approved' (no signal needed) or 'pending_resume'
          (the resume completion banner upstream covers it). */}
      {reviewStatus === 'pending_review' && (
        <div className="card-flat" style={{padding:18, marginBottom:16, display:'flex', gap:14, alignItems:'center', background:'linear-gradient(135deg, #FFF7E6, #FDECC8)', border:'1.5px solid #F0C674'}}>
          <div style={{width:40, height:40, borderRadius:99, background:'#F0C674', color:'#7A4F00', display:'grid', placeItems:'center', flexShrink:0}}>
            <Icon name="clock" size={18}/>
          </div>
          <div style={{flex:1, minWidth:0}}>
            <div style={{fontSize:14, fontWeight:700, color:'#7A4F00', marginBottom:2}}>Profile under review</div>
            <div style={{fontSize:12.5, color:'#7A4F00', opacity:0.85, lineHeight:1.5}}>Our team typically reviews new profiles within 24 hours. We'll email you the moment it's approved.</div>
          </div>
        </div>
      )}
      {reviewStatus === 'rejected' && (
        <div className="card-flat" style={{padding:18, marginBottom:16, display:'flex', gap:14, alignItems:'flex-start', background:'var(--coral-bg)', border:'1.5px solid var(--coral-light)'}}>
          <div style={{width:40, height:40, borderRadius:99, background:'var(--coral-dark)', color:'white', display:'grid', placeItems:'center', flexShrink:0}}>
            <Icon name="x" size={18}/>
          </div>
          <div style={{flex:1, minWidth:0}}>
            <div style={{fontSize:14, fontWeight:700, color:'var(--coral-dark)', marginBottom:2}}>Profile needs updates</div>
            <div style={{fontSize:12.5, color:'var(--t-ink-soft)', lineHeight:1.5, marginBottom:rejectReason ? 6 : 10}}>{rejectReason || 'Our team flagged a few items that need attention before you can apply to jobs.'}</div>
            <button className="btn btn-sm" style={{background:'var(--coral-dark)', color:'white', borderColor:'var(--coral-dark)', padding:'6px 14px', fontSize:12.5, fontWeight:600, borderRadius:8}} onClick={()=>go && go('create-profile')}>
              Edit and resubmit
            </button>
          </div>
        </div>
      )}
      {reviewStatus === 'approved' && (() => {
        // Show the "approved" banner once and stash a flag so it doesn't
        // sit forever — once the helper has dismissed it, it stays gone
        // until status flips back to non-approved.
        let dismissed = false;
        try { dismissed = localStorage.getItem('hm_review_approved_seen') === '1'; } catch(e) {}
        if (dismissed) return null;
        return (
          <div className="card-flat" style={{padding:18, marginBottom:16, display:'flex', gap:14, alignItems:'center', background:'var(--mint-light, #DCF5EE)', border:'1.5px solid var(--mint, #48B8A0)'}}>
            <div style={{width:40, height:40, borderRadius:99, background:'var(--mint, #48B8A0)', color:'white', display:'grid', placeItems:'center', flexShrink:0}}>
              <Icon name="check" size={18}/>
            </div>
            <div style={{flex:1, minWidth:0}}>
              <div style={{fontSize:14, fontWeight:700, color:'var(--mint-dark, #1F7D6A)', marginBottom:2}}>Profile approved</div>
              <div style={{fontSize:12.5, color:'var(--t-ink-soft)', lineHeight:1.5}}>You can now apply to jobs and receive employer messages.</div>
            </div>
            <button
              className="btn btn-ghost btn-sm"
              onClick={() => { try { localStorage.setItem('hm_review_approved_seen', '1'); } catch(e) {} setReviewStatus(s => s); }}
              style={{flexShrink:0}}
              aria-label="Dismiss"
            >
              <Icon name="x" size={14}/>
            </button>
          </div>
        );
      })()}

      {/* Identity card */}
      <div className="card-flat" style={{padding:24, marginBottom:16, display:'flex', gap:20, alignItems:'center'}}>
        <Avatar person={me} size={84}/>
        <div style={{flex:1}}>
          <div style={{display:'flex', alignItems:'center', gap:8, marginBottom:4}}>
            <h2 style={{fontSize:22, fontWeight:700, letterSpacing:'-0.01em'}}>{me.name}</h2>
            {/* Verified badge is reserved for HelperMatch-official assessed
                helpers — agency/self-registered profiles render without it. */}
            {isOfficial && <Icon name="verified" size={16} style={{color:'var(--trust)'}}/>}
          </div>
          <div style={{fontSize:13, color:'var(--t-ink-muted)'}}>
            {[me.age, me.flag && me.nationality ? `${me.flag} ${me.nationality}` : '', me.city].filter(Boolean).join(' · ') || 'Complete your profile to add personal details'}
          </div>
        </div>
      </div>

      {/* Personal details — demographic grid + short bio captured from the
          resume form's Bio step. */}
      <div className="card-flat" style={{padding:24, marginBottom:16}}>
        <h3 style={{fontSize:15, fontWeight:700, marginBottom:18}}>Personal details</h3>
        <div style={{display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:20}}>
          {[
            {label:'Gender', value:d.gender || 'Female'},
            {label:'Birthday', value:me.birthday || '—'},
            {label:'Marital', value:d.maritalStatus || '—'},
            {label:'Children', value:d.kids || '—'},
            {label:'Religion', value:d.religion || '—'},
            {label:'Height', value:d.height || '—'},
            {label:'Weight', value:d.weight || '—'},
            {label:'Education', value:d.education || '—'},
            {label:'Experience', value: me.experience || '—'},
          ].map((x, i) => (
            <div key={i}>
              <div style={{fontSize:11, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.06em', fontWeight:600, marginBottom:4}}>{x.label}</div>
              <div style={{fontSize:14, fontWeight:500}}>{x.value}</div>
            </div>
          ))}
        </div>
        {(window.pickLocalised(me, 'bio') || me.bio) && (
          <div style={{marginTop:22, paddingTop:18, borderTop:'1px solid var(--t-line)'}}>
            <div style={{fontSize:11, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.06em', fontWeight:600, marginBottom:6}}>Short bio</div>
            <p style={{fontSize:14, lineHeight:1.6, color:'var(--t-ink-soft)', margin:0}}>{window.pickLocalised(me, 'bio') || me.bio}</p>
          </div>
        )}
      </div>

      {/* Skills & languages — tags mirror the public single-helper page */}
      <div className="card-flat" style={{padding:24, marginBottom:16}}>
        <h3 style={{fontSize:15, fontWeight:700, marginBottom:18}}>Skills & languages</h3>
        <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'22px 28px'}}>
          <PillGroup title="Languages" category="language" items={ts.languages} lookup={tax?.languages}/>
          <PillGroup title="Main skills" category="main" items={ts.mainSkills} lookup={tax?.mainSkills}/>
          <PillGroup title="Cooking cuisines" category="cooking" items={ts.cookingSkills} lookup={tax?.cookingSkills}/>
          <PillGroup title="Other skills" category="other" items={ts.otherSkills} lookup={tax?.otherSkills}/>
          <PillGroup title="Personality" category="personality" items={ts.personality} lookup={tax?.personality}/>
        </div>
      </div>

      {/* My preference — captured from the resume form's Preference step.
          Reuses the candidate.expectations + jobTypes + contractStatus +
          availableDate fields populated by the prototype mock data. */}
      <div className="card-flat" style={{padding:24, marginBottom:16}}>
        <h3 style={{fontSize:15, fontWeight:700, marginBottom:18}}>My preference</h3>
        <div style={{display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:20}}>
          {[
            {label:'Position', value: me.jobTypes?.[0] || 'Domestic Helper'},
            {label:'Job type', value: me.expectations?.accommodation === 'Live-out' ? 'Live-out' : 'Live-in'},
            {label:'Expected salary', value: me.expectations?.salary || '—'},
            {label:'Day off', value: me.expectations?.dayOff || '—'},
            {label:'Accommodation', value: me.expectations?.accommodation || '—'},
            {label:'Contract status', value: me.contractStatus || '—'},
            {label:'Available from', value: me.availableDate || '—'},
            {label:'Preferred markets', value: me.locationCountry || me.city || '—'},
          ].map((x, i) => (
            <div key={i}>
              <div style={{fontSize:11, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.06em', fontWeight:600, marginBottom:4}}>{x.label}</div>
              <div style={{fontSize:14, fontWeight:500}}>{x.value}</div>
            </div>
          ))}
        </div>
      </div>

      {/* My experience — work history captured from the resume form's
          Working experience step. */}
      <div className="card-flat" style={{padding:24, marginBottom:16}}>
        <h3 style={{fontSize:15, fontWeight:700, marginBottom:14}}>My experience</h3>
        <div style={{display:'flex', flexDirection:'column', gap:8}}>
          {(me.workExperiences || []).filter(e => e && (e.position || e.country || e.startYear)).length === 0 && (
            <div style={{fontSize:13, color:'var(--t-ink-muted)', padding:'14px 0'}}>No work experience added yet.</div>
          )}
          {(me.workExperiences || []).filter(e => e && (e.position || e.country || e.startYear)).map((e, i) => {
            const years = `${e.startMonth || ''} ${e.startYear || ''}${e.current ? ' - Present' : e.endYear ? ` - ${e.endMonth || ''} ${e.endYear}` : ''}`.trim();
            return (
            <div key={i} style={{display:'flex', gap:12, padding:'12px 14px', background:'var(--t-paper)', border:'1px solid var(--t-line)', borderRadius:'var(--t-radius-sm)', alignItems:'center'}}>
              <div style={{width:40, height:40, borderRadius:10, background:'var(--trust-bg)', color:'var(--trust)', display:'grid', placeItems:'center', flexShrink:0}}>
                <Icon name="briefcase" size={20}/>
              </div>
              <div style={{flex:1, minWidth:0}}>
                <div style={{display:'flex', justifyContent:'space-between', alignItems:'baseline', gap:12, marginBottom:2, flexWrap:'wrap'}}>
                  <div style={{fontWeight:600, fontSize:14}}>{e.position || 'Work experience'}</div>
                  <div style={{fontSize:12, color:'var(--t-ink-muted)', display:'inline-flex', alignItems:'center', gap:4}}>
                    <Icon name="calendar" size={11}/> {years || 'Dates not provided'}
                  </div>
                </div>
                <div style={{fontSize:12.5, color:'var(--t-ink-muted)', display:'inline-flex', alignItems:'center', gap:4}}>
                  <Icon name="location" size={11}/> {e.country || 'Location not provided'}
                </div>
              </div>
            </div>
          );})}
        </div>
      </div>

      {/* Videos — official helpers see the 4 skill-category grid (admin-recorded);
          ALL helpers (official + self/agency) also get a self-upload slot
          beneath, so they can add their own intro clip on top of the official
          videos. */}
      {isOfficial && (
        <div className="card-flat" style={{padding:24, marginBottom:16}}>
          <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:6, gap:12, flexWrap:'wrap'}}>
            <div>
              {/* Phase 2: append <span className="chip chip-mint">HelperMatch Official</span> to the heading. */}
              <h3 style={{fontSize:15, fontWeight:700, marginBottom:4}}>Skill videos</h3>
              <p style={{fontSize:12, color:'var(--t-ink-muted)'}}>Recorded for you by our team. Reach out if anything needs to be re-recorded.</p>
            </div>
            <div style={{display:'flex', alignItems:'center', gap:8}}>
              <span className="chip chip-mint" style={{fontSize:11}}>{officialVideoCount} / 4 recorded</span>
            </div>
          </div>
          <div style={{display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:12, marginTop:14}}>
            {(window.VIDEO_CATEGORIES || []).map(cat => {
              const v = me.videos?.[cat.id];
              return (
                <div key={cat.id} style={{border:'1px solid var(--t-line)', borderRadius:12, overflow:'hidden', background:'var(--t-paper)'}}>
                  <div style={{aspectRatio:'16/10', background: v ? `linear-gradient(135deg, ${me.color}66, ${me.color}AA), radial-gradient(circle at 60% 40%, ${window.shadeColor(me.color,30)}, ${window.shadeColor(me.color,-30)})` : 'var(--t-bg)', display:'grid', placeItems:'center', position:'relative'}}>
                    {v ? (
                      <>
                        <div style={{width:44, height:44, borderRadius:99, background:'rgba(255,255,255,0.95)', color:'var(--trust-ink)', display:'grid', placeItems:'center', boxShadow:'0 2px 10px rgba(0,0,0,0.15)'}}>
                          <Icon name="play" size={18}/>
                        </div>
                        <span style={{position:'absolute', bottom:8, left:8, padding:'2px 7px', background:'rgba(0,0,0,0.6)', color:'white', fontSize:10, fontWeight:600, borderRadius:3, display:'inline-flex', alignItems:'center', gap:3}}>
                          <Icon name="verified" size={9}/> Assessed
                        </span>
                        <span style={{position:'absolute', bottom:8, right:8, padding:'2px 6px', background:'rgba(0,0,0,0.6)', color:'white', fontSize:10, fontWeight:600, borderRadius:3}}>{v.duration}</span>
                      </>
                    ) : (
                      <div style={{textAlign:'center', color:'var(--t-ink-muted)', fontSize:11, padding:16}}>
                        <div style={{width:36, height:36, borderRadius:99, background:'var(--t-paper)', border:'1.5px dashed var(--t-line)', display:'grid', placeItems:'center', margin:'0 auto 6px'}}>
                          <Icon name={cat.icon} size={14}/>
                        </div>
                        Not recorded
                      </div>
                    )}
                  </div>
                  <div style={{padding:'10px 12px 12px'}}>
                    <div style={{fontSize:13, fontWeight:700, marginBottom:2, display:'flex', alignItems:'center', gap:5}}>
                      <Icon name={cat.icon} size={12}/>
                      {cat.label}
                    </div>
                    <div style={{fontSize:11, color:'var(--t-ink-muted)'}}>
                      {cat.id==='cooking' && 'Show a dish end-to-end'}
                      {cat.id==='language' && 'Intro in your languages'}
                      {cat.id==='housekeeping' && 'Clean, laundry, organize'}
                      {cat.id==='other' && 'Care, driving, specialty'}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* Self-uploaded video — shown to ALL helpers regardless of verification.
          Officials get this in addition to their admin-recorded skill videos
          above; self/agency helpers see only this card. */}
      <div className="card-flat" style={{padding:24, marginBottom:16}}>
          <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:6, gap:12, flexWrap:'wrap'}}>
            <div>
              <h3 style={{fontSize:15, fontWeight:700, marginBottom:4}}>Self-uploaded video</h3>
              <p style={{fontSize:12, color:'var(--t-ink-muted)', marginBottom:6}}>One short clip introducing yourself. Profiles with an intro get 2.4× more employer views.</p>
              <p style={{fontSize:11, color:'var(--t-ink-muted)', display:'inline-flex', alignItems:'center', gap:6, padding:'4px 10px', background:'var(--t-bg)', border:'1px solid var(--t-line)', borderRadius:99}}>
                <Icon name="info" size={11}/>
                {(window.HM_VIDEO_HINT_FN && window.HM_VIDEO_HINT_FN()) || 'MP4 · MOV · max 150 MB · 30 sec – 3 min · 720p or higher'}
              </p>
            </div>
            <div style={{display:'flex', alignItems:'center', gap:8}}>
              <span className="chip chip-mint" style={{fontSize:11}}>{hasIntroVideo ? 'Uploaded' : 'Not yet'}</span>
            </div>
          </div>
          <div style={{display:'grid', gridTemplateColumns:'minmax(0, 360px)', gap:12, marginTop:14}}>
            <div style={{border:'1px solid var(--t-line)', borderRadius:12, overflow:'hidden', background:'var(--t-paper)'}}>
              <div style={{aspectRatio:'16/10', background: hasIntroVideo ? `linear-gradient(135deg, ${me.color}66, ${me.color}AA), radial-gradient(circle at 60% 40%, ${window.shadeColor(me.color,30)}, ${window.shadeColor(me.color,-30)})` : 'var(--t-bg)', display:'grid', placeItems:'center', position:'relative'}}>
                {hasIntroVideo ? (
                  <>
                    <div style={{width:48, height:48, borderRadius:99, background:'rgba(255,255,255,0.95)', color:'var(--trust-ink)', display:'grid', placeItems:'center', boxShadow:'0 2px 10px rgba(0,0,0,0.15)'}}>
                      <Icon name="play" size={20}/>
                    </div>
                    <span style={{position:'absolute', bottom:8, left:8, padding:'2px 7px', background:'rgba(0,0,0,0.6)', color:'white', fontSize:10, fontWeight:600, borderRadius:3, display:'inline-flex', alignItems:'center', gap:3}}>
                      <Icon name="play" size={9}/> Uploaded
                    </span>
                    <span style={{position:'absolute', bottom:8, right:8, padding:'2px 6px', background:'rgba(0,0,0,0.6)', color:'white', fontSize:10, fontWeight:600, borderRadius:3}}>{me.introVideo.duration}</span>
                  </>
                ) : (
                  <div style={{textAlign:'center', color:'var(--t-ink-muted)', fontSize:12, padding:20}}>
                    <div style={{width:44, height:44, borderRadius:99, background:'var(--t-paper)', border:'1.5px dashed var(--t-line)', display:'grid', placeItems:'center', margin:'0 auto 8px'}}>
                      <Icon name="play" size={18}/>
                    </div>
                    No intro video yet
                  </div>
                )}
              </div>
              <div style={{padding:'12px 14px 14px'}}>
                <div style={{fontSize:13, fontWeight:700, marginBottom:8}}>Self-intro</div>
                {hasIntroVideo ? (
                  <div style={{display:'flex', gap:6}}>
                    <button className="btn btn-outline btn-sm" style={{flex:1, fontSize:11, padding:'6px 8px'}}>Re-record</button>
                    <button className="btn btn-ghost btn-sm" style={{padding:'6px 8px'}} title="Delete"><Icon name="close" size={11}/></button>
                  </div>
                ) : (
                  <button className="btn btn-trust btn-sm btn-block" style={{fontSize:11, padding:'6px 8px'}}>
                    <Icon name="plus" size={11}/> Upload intro video
                  </button>
                )}
              </div>
            </div>
          </div>
          {/* Phase 2: re-enable the "Book a Surabaya assessment" promo callout once
              the verification feature ships. */}
        </div>

      {/* MVP: References management card removed — helpers no longer upload
          reference files. Resume form keeps a per-experience Yes/No flag, which
          renders on the public detail page as a single Reference: Yes/No row.
          Restore this card if helper-managed references come back into scope. */}

      {/* Verification & documents block hidden until the verification feature
          is built out. Restore the previous JSX from git history when ready. */}
    </div>
  );
};

// ===== Matches (Jobs for you) =====
const HelperMatches = ({ go, me, matchedJobs }) => {
  const withScores = matchedJobs.map((j, i) => ({
    j,
    score: 96 - i * 3,
    reasons: [
      j.reqLanguages?.includes(me.typedSkills?.languages?.[0]) && 'Language match',
      j.reqMainSkills?.find(s => me.typedSkills?.mainSkills?.includes(s)) && `${j.reqMainSkills.find(s => me.typedSkills?.mainSkills?.includes(s))} experience`,
      j.market === 'Taiwan' && 'Your target market',
      'Salary above your ask',
    ].filter(Boolean).slice(0, 3),
  }));

  return (
    <div>
      <div className="dash-header">
        <h1>Jobs for you</h1>
        <p>Families hiring now who match your profile. Ranked by how well your skills and experience fit.</p>
      </div>

      <div className="card-flat" style={{padding:18, marginBottom:20, display:'flex', alignItems:'center', gap:14, background:'var(--trust-bg)', border:'1px solid var(--trust-soft)'}}>
        <div style={{width:36, height:36, borderRadius:8, background:'var(--trust)', color:'white', display:'grid', placeItems:'center', flexShrink:0}}>
          <Icon name="sparkle" size={16}/>
        </div>
        <div style={{flex:1, minWidth:0}}>
          <div style={{fontSize:13, fontWeight:700, color:'var(--trust-ink)', marginBottom:2}}>Matched to your profile</div>
          <div style={{fontSize:12, color:'var(--t-ink-muted)'}}>Updated daily based on your skills, languages, target markets, and salary expectations.</div>
        </div>
        <button className="btn btn-outline btn-sm" onClick={()=>go('create-profile')}>
          <Icon name="edit" size={13}/> Edit preferences
        </button>
      </div>

      <div style={{display:'flex', flexDirection:'column', gap:14}}>
        {withScores.map(({j, score, reasons}) => (
          <div key={j.id} className="card" style={{padding:22, cursor:'pointer', display:'grid', gridTemplateColumns:'1fr auto', gap:20}} onClick={()=>go(`job:${j.id}`)}>
            <div style={{minWidth:0}}>
              <div style={{display:'flex', gap:8, marginBottom:8, flexWrap:'wrap'}}>
                <span className="chip chip-coral" style={{fontSize:11}}>{j.market}</span>
                <span className="chip chip-ghost" style={{fontSize:11}}>{j.jobType}</span>
                <span className="chip chip-ghost" style={{fontSize:11}}>{j.type}</span>
              </div>
              <div style={{fontSize:17, fontWeight:700, marginBottom:4, letterSpacing:'-0.01em'}}>{j.title}</div>
              <div style={{fontSize:13, color:'var(--t-ink-muted)', marginBottom:10}}>{j.city} · {j.familySize} · Posted {j.posted}</div>
              <div style={{display:'flex', flexWrap:'wrap', gap:14, paddingTop:10, borderTop:'1px solid var(--t-line)'}}>
                {reasons.map((r, i) => (
                  <div key={i} style={{fontSize:12, color:'var(--t-ink)', display:'flex', alignItems:'center', gap:6, fontWeight:500}}>
                    <Icon name="check" size={12} style={{color:'var(--trust)'}}/>
                    {r}
                  </div>
                ))}
              </div>
            </div>
            <div style={{textAlign:'right', display:'flex', flexDirection:'column', alignItems:'flex-end', gap:10, minWidth:140}}>
              <div>
                <div style={{fontSize:28, fontWeight:700, color:'var(--trust-ink)', letterSpacing:'-0.02em', lineHeight:1}}>{score}%</div>
                <div style={{fontSize:10, color:'var(--t-ink-muted)', textTransform:'uppercase', letterSpacing:'0.08em', fontWeight:700, marginTop:2}}>Match</div>
              </div>
              <div style={{fontSize:14, fontWeight:700, color:'var(--t-ink)'}}>{j.salary}</div>
              <button className="btn btn-trust btn-sm" onClick={(e)=>{e.stopPropagation(); go(`job:${j.id}`);}}>Apply</button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

// ===== Applications =====
// Each application links to (1) the public job post via View job, and
// (2) the relevant message thread via Message — but ONLY when the employer
// has reached out (a.threadId is set). Helpers cannot initiate threads —
// they can only reply within a thread the employer already started. This
// is the asymmetric messaging rule (see DOMAIN_MODEL.md §4.13 + §4.15).
//
// Status values are employer-driven only: 'Awaiting employer review' →
// 'Application viewed' → 'Shortlisted by employer' → 'Contacted by
// employer' (or terminal: rejected / withdrawn). No "schedule interview"
// feature in v1.
const HelperApplications = ({ go, applications }) => {
  const { jobs } = window.MOCK_DATA;
  const getJob = id => jobs.find(j => j.id === id);
  return (
    <div>
      <div className="dash-header">
        <h1>Applications</h1>
        <p>Track the status of every job you've applied to. The employer will reach out if interested.</p>
      </div>
      <div style={{display:'flex', flexDirection:'column', gap:14}}>
        {applications.map((a, i) => {
          const j = getJob(a.jobId);
          if (!j) return null;
          const badgeColor = {
            trust: { bg: 'var(--trust-bg)', fg: 'var(--trust-deep)' },
            mint:  { bg: 'var(--mint-bg, #DCF5E6)', fg: 'var(--mint-dark, #1F8A4C)' },
            sand:  { bg: 'var(--t-warm)', fg: 'var(--t-warm-ink)' },
            ghost: { bg: 'var(--t-bg)', fg: 'var(--t-ink-muted)' },
          }[a.badge] || { bg: 'var(--t-bg)', fg: 'var(--t-ink-muted)' };
          return (
            <div key={i} className="card-flat" style={{padding:20, display:'flex', gap:18, alignItems:'center', flexWrap:'wrap'}}>
              <div style={{width:44, height:44, borderRadius:10, background:'var(--trust-bg)', color:'var(--trust)', display:'grid', placeItems:'center', flexShrink:0}}>
                <Icon name="briefcase" size={18}/>
              </div>
              <div style={{flex:'1 1 220px', minWidth:0}}>
                <div style={{fontSize:15, fontWeight:600, marginBottom:4}}>{j.title}</div>
                <div style={{fontSize:12, color:'var(--t-ink-muted)', marginBottom:6}}>{j.market} · {j.city} · {j.salary}</div>
                <span style={{display:'inline-block', padding:'3px 10px', fontSize:11, fontWeight:600, borderRadius:99, background:badgeColor.bg, color:badgeColor.fg}}>
                  {a.status}
                </span>
              </div>
              <div style={{textAlign:'right', fontSize:11, color:'var(--t-ink-muted)', minWidth:80}}>{a.when}</div>
              <div style={{display:'flex', gap:8, flexShrink:0}}>
                {/* Message button only when employer has reached out (= thread exists). */}
                {a.threadId && (
                  <button className="btn btn-outline btn-sm" onClick={()=>go(`inbox:${a.threadId}`)}>
                    <Icon name="chat" size={13}/> Message
                  </button>
                )}
                <button className="btn btn-outline btn-sm" onClick={()=>go(`job:${j.id}`)}>View job</button>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ===== Saved =====
// Horizontal card layout — JobCard's grid layout overflowed inside the helper
// dashboard's narrower main column. Mirrors the Applications card layout for
// visual consistency across the helper sections.
const HelperSaved = ({ go, jobs }) => (
  <div>
    <div className="dash-header">
      <h1>Saved jobs</h1>
      <p>{jobs.length} jobs saved for later.</p>
    </div>
    <div style={{display:'flex', flexDirection:'column', gap:14}}>
      {jobs.map(j => (
        <div key={j.id} className="card-flat" style={{padding:20, display:'flex', gap:18, alignItems:'center'}}>
          <div style={{width:44, height:44, borderRadius:10, background:'var(--coral-bg)', color:'var(--coral-dark)', display:'grid', placeItems:'center', flexShrink:0}}>
            <Icon name="heart" size={18}/>
          </div>
          <div style={{flex:1, minWidth:0}}>
            <div style={{display:'flex', gap:6, marginBottom:6, flexWrap:'wrap'}}>
              <span className="chip chip-coral" style={{fontSize:11}}>{j.market}</span>
              <span className="chip chip-ghost" style={{fontSize:11}}>{j.type}</span>
            </div>
            <div style={{fontSize:15, fontWeight:600, marginBottom:2, lineHeight:1.3}}>{window.pickLocalised(j, 'title') || j.title}</div>
            <div style={{fontSize:12, color:'var(--t-ink-muted)', display:'flex', gap:10, flexWrap:'wrap'}}>
              <span style={{display:'inline-flex', alignItems:'center', gap:4}}><Icon name="location" size={11}/> {j.city}</span>
              <span style={{display:'inline-flex', alignItems:'center', gap:4}}><Icon name="clock" size={11}/> {j.posted}</span>
            </div>
          </div>
          <div style={{textAlign:'right', minWidth:100, flexShrink:0}}>
            <div style={{fontSize:14, fontWeight:700, color:'var(--t-ink)'}}>{j.salary}</div>
          </div>
          <button className="btn btn-outline btn-sm" onClick={()=>go(`job:${j.id}`)}>View job</button>
        </div>
      ))}
    </div>
  </div>
);

// ===== Earnings (delegated to pages-helper-referral.jsx) =====
const HelperEarnings = () => {
  if (typeof window.HelperReferralWallet === 'function') return <window.HelperReferralWallet/>;
  return <div style={{padding:40, color:'var(--t-ink-muted)'}}>Loading…</div>;
};

// ===== Account =====
const HelperAccount = ({ me }) => {
  const { lang, setLang, LANG_META, t } = window.useI18n();
  const [tab, setTab] = React.useState('contact');
  const tabs = [
    {id:'contact', label:'Contact info'},
    {id:'language', label:'Language'},
    {id:'notifications', label: t('dash.account.tab.notifications')},
    {id:'security', label:'Security'},
  ];
  // Contact form state — local state, save button writes back to backend
  // (PATCH /me/resume once available). Email is read-only (managed via the
  // auth verification flow).
  const [contactName, setContactName] = React.useState(me.name || '');
  const [contactPhoneCC, setContactPhoneCC] = React.useState('+62');
  const [contactPhone, setContactPhone] = React.useState('812 3456 7890');
  const [contactSaved, setContactSaved] = React.useState(false);
  const dialCodes = typeof DIAL_CODES !== 'undefined' ? DIAL_CODES : [];
  const saveContact = () => {
    // TODO: PATCH /me/resume with phone once backend lands.
    setContactSaved(true);
    setTimeout(() => setContactSaved(false), 2000);
  };
  const [notifyPrefs, setNotifyPrefs] = React.useState({ newsletter: true });
  return (
    <div>
      <div className="dash-header">
        <h1>Account</h1>
        <p>Manage your contact info, language, and security.</p>
      </div>
      <div style={{display:'grid', gridTemplateColumns:'220px 1fr', gap:24, alignItems:'start'}}>
        <div style={{display:'flex', flexDirection:'column', gap:2, background:'var(--t-paper)', border:'1px solid var(--t-line)', borderRadius:12, padding:8}}>
          {tabs.map(t => (
            <button key={t.id} onClick={()=>setTab(t.id)} style={{
              textAlign:'left', padding:'10px 12px', border:'none', background: tab===t.id ? 'var(--trust-bg)' : 'transparent',
              color: tab===t.id ? 'var(--trust-ink)' : 'var(--t-ink)', fontWeight: tab===t.id ? 600 : 500,
              fontSize:13, borderRadius:8, cursor:'pointer', fontFamily:'inherit'
            }}>{t.label}</button>
          ))}
        </div>
        <div style={{display:'flex', flexDirection:'column', gap:16}}>
          {tab === 'contact' && (
            <div className="card-flat" style={{padding:24}}>
              <h3 style={{fontSize:15, fontWeight:700, marginBottom:4}}>Contact info</h3>
              <p style={{fontSize:12, color:'var(--t-ink-muted)', marginBottom:16}}>Only shown to employers after they subscribe and start a conversation.</p>
              <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:14}}>
                <div>
                  <div className="label">Full name</div>
                  <input className="input" value={contactName} onChange={e => setContactName(e.target.value)}/>
                </div>
                <div>
                  <div className="label">Email</div>
                  <input
                    className="input" type="email" value="purwanti@example.id"
                    readOnly
                    style={{background:'var(--t-bg)', color:'var(--t-ink-muted)', cursor:'not-allowed'}}
                  />
                </div>
                <div style={{gridColumn:'1/-1'}}>
                  <div className="label">Phone (WhatsApp)</div>
                  <div style={{display:'grid', gridTemplateColumns:'200px 1fr', gap:8}}>
                    <select className="input" value={contactPhoneCC} onChange={e => setContactPhoneCC(e.target.value)}>
                      {dialCodes.map(d => (
                        <option key={d.cc + d.name} value={d.cc}>{d.flag} {d.cc} {d.name}</option>
                      ))}
                    </select>
                    <input className="input" value={contactPhone} onChange={e => setContactPhone(e.target.value)} placeholder="812 3456 7890"/>
                  </div>
                </div>
              </div>
              <div style={{display:'flex', alignItems:'center', gap:12, marginTop:18}}>
                <button className="btn btn-primary btn-sm" onClick={saveContact}>Save changes</button>
                {contactSaved && (
                  <span style={{fontSize:12, color:'var(--trust)', fontWeight:600, display:'inline-flex', alignItems:'center', gap:4}}>
                    <Icon name="check" size={12}/> Saved
                  </span>
                )}
              </div>
            </div>
          )}

          {tab === 'language' && (
            <div className="card-flat" style={{padding:24}}>
              <h3 style={{fontSize:15, fontWeight:700, marginBottom:16}}>Preferred language</h3>
              {/* Wires straight into the global i18n engine — picking a row
                  sets window.i18n.lang and persists it (also drives the
                  header LangSwitcher). Options stay in sync with
                  hm-i18n.js's SUPPORTED list. */}
              <div style={{display:'flex', flexDirection:'column', gap:10}}>
                {Object.values(LANG_META).map(meta => {
                  const active = lang === meta.code;
                  return (
                    <label
                      key={meta.code}
                      style={{display:'flex', alignItems:'center', gap:12, padding:'12px 14px', border:`1.5px solid ${active ? 'var(--trust)' : 'var(--t-line)'}`, borderRadius:10, cursor:'pointer', background: active ? 'var(--trust-bg)' : 'var(--t-paper)'}}
                    >
                      <input
                        type="radio"
                        name="lang"
                        checked={active}
                        onChange={() => setLang(meta.code)}
                      />
                      <span style={{fontSize:18}}>{meta.flag}</span>
                      <span style={{fontSize:14, fontWeight:500}}>{meta.label}</span>
                    </label>
                  );
                })}
              </div>
            </div>
          )}

          {tab === 'notifications' && (
            <div className="card-flat" style={{padding:24}}>
              <h3 style={{fontSize:15, fontWeight:700, marginBottom:4}}>{t('dash.account.notifications.heading')}</h3>
              <p style={{fontSize:12, color:'var(--t-ink-muted)', marginBottom:16}}>{t('dash.account.notifications.subtitle')}</p>
              <div style={{display:'grid', gridTemplateColumns:'1fr auto', alignItems:'center', padding:'14px 0', fontSize:13, gap:16}}>
                <div style={{fontWeight:500}}>{t('dash.account.notifications.row.newsletter')}</div>
                <Toggle
                  checked={notifyPrefs.newsletter}
                  onChange={(v) => setNotifyPrefs(p => ({ ...p, newsletter: v }))}
                  ariaLabel={t('dash.account.notifications.row.newsletter')}
                />
              </div>
            </div>
          )}

          {tab === 'security' && (
            <>
              <div className="card-flat" style={{padding:24}}>
                <h3 style={{fontSize:15, fontWeight:700, marginBottom:14}}>Password</h3>
                <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:14}}>
                  <div><div className="label">New password</div><input className="input" type="password" placeholder="••••••••"/></div>
                  <div><div className="label">Confirm new password</div><input className="input" type="password" placeholder="••••••••"/></div>
                </div>
                <button className="btn btn-outline btn-sm" style={{marginTop:14}}>Update password</button>
              </div>
              <div className="card-flat" style={{padding:24, borderColor:'var(--coral-soft, #F8D3C8)'}}>
                <h3 style={{fontSize:15, fontWeight:700, marginBottom:4, color:'var(--coral)'}}>Deactivate profile</h3>
                <p style={{fontSize:12, color:'var(--t-ink-muted)', marginBottom:14}}>Hides your profile from search while keeping your application history. You can reactivate anytime.</p>
                <button className="btn btn-outline btn-sm" style={{color:'var(--coral)', borderColor:'var(--coral)'}}>Deactivate</button>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { HelperDashPage });
