// Settings — profile, security & social accounts (split from settings.jsx).
// ProfileEditor, AccountSecurity, social platform editors, LoginIntegrations,
// HashtagSettings. Owns window.SettingsView export.

function ProfileEditor({ user, onUpdate }) {
  const [name, setName] = useState('');
  const [abo, setAbo] = useState('');
  const [phone, setPhone] = useState('');
  const [country, setCountry] = useState('th');
  const [avatar, setAvatar] = useState('');
  const [saving, setSaving] = useState(false);

  // My LINE link state
  const [linkingLine, setLinkingLine] = useState(false);
  const [lineStatus, setLineStatus] = useState(null);
  // Telegram link state — modal opens with a deep-link URL the user taps
  // to launch Telegram. Polls the token row until status='completed'.
  const [tgLinkOpen, setTgLinkOpen] = useState(null); // null | 'self' | 'partner'

  // Joint-ABO partner fields
  const [showPartner, setShowPartner] = useState(false);
  const [partnerName, setPartnerName] = useState('');
  const [partnerPhone, setPartnerPhone] = useState('');
  // Email field removed in the UI; partner identity now keyed by LINE link.
  const [partnerLineId, setPartnerLineId] = useState('');
  const [partnerLineName, setPartnerLineName] = useState('');
  const [partnerAvatar, setPartnerAvatar] = useState('');
  const [partnerStatus, setPartnerStatus] = useState(null); // {ok, msg}
  const partnerFileRef = useRef(null);
  // QR-scan flow: opens a modal that shows a QR pointing at /?partner_link=...
  // The partner scans on their phone, LIFF-logs-in, and the edge function
  // claims the token. This view polls the token until status='completed'.
  const [partnerLinkModalOpen, setPartnerLinkModalOpen] = useState(false);

  const fileRef = useRef(null);

  // Capture the active LIFF profile and store it on users.line_user_id.
  const handleLinkMyLine = async () => {
    setLineStatus(null);
    if (!window.SB_READY || !user?.id) {
      setLineStatus({ ok: false, msg: 'ระบบไม่ได้เชื่อมต่อฐานข้อมูล' });
      return;
    }
    setLinkingLine(true);
    try {
      if (!window.liff) throw new Error('LIFF SDK ไม่ได้โหลด');
      const liffId = window.EMPHASIS_ENV?.liffId;
      if (!liffId || liffId.startsWith('REPLACE')) throw new Error('LIFF ID ยังไม่ได้ตั้งค่า');
      await window.liff.init({ liffId });
      if (!window.liff.isLoggedIn()) {
        window.liff.login({ redirectUri: window.location.href });
        return;
      }
      const prof = await window.liff.getProfile();
      if (!prof?.userId) throw new Error('ไม่ได้รับ userId จาก LINE');
      const { error } = await window.supabase.from('users').update({
        line_user_id: prof.userId,
        line_display_name: prof.displayName || null,
      }).eq('id', user.id);
      if (error) throw error;
      setLineStatus({ ok: true, msg: `เชื่อม LINE ของ ${prof.displayName || prof.userId} เรียบร้อย` });
      if (onUpdate) await onUpdate();
    } catch (e) {
      setLineStatus({ ok: false, msg: e.message });
    } finally {
      setLinkingLine(false);
    }
  };

  useEffect(() => {
    if (user) {
      setName(user.lineDisplayName || user.name || '');
      setAbo(user.abo_code || '');
      setPhone(user.phone_number || '');
      setCountry(user.country || 'th');
      setAvatar(user.avatar_url || user.avatar || '');
      setPartnerName(user.partner_name || '');
      setPartnerPhone(user.partner_phone || '');
      setPartnerAvatar(user.partner_avatar || '');
      setPartnerLineId(user.partner_line_user_id || '');
      setPartnerLineName(user.partner_line_display_name || '');
      setShowPartner(!!(user.partner_name || user.partner_phone || user.partner_line_user_id || user.partner_avatar));
    }
  }, [user]);

  // Capture the currently-logged-in LIFF profile and persist it as the
  // partner's LINE identity straight to Supabase — same pattern as
  // handleLinkMyLine so the user doesn't have to click the main "บันทึก"
  // afterwards just to commit a LINE link.
  const handleCapturePartnerLine = async () => {
    setPartnerStatus(null);
    if (!window.SB_READY || !user?.id) {
      setPartnerStatus({ ok: false, msg: 'ระบบไม่ได้เชื่อมต่อฐานข้อมูล' });
      return;
    }
    try {
      if (!window.liff) throw new Error('LIFF SDK ไม่ได้โหลด');
      const liffId = window.EMPHASIS_ENV?.liffId;
      if (!liffId || liffId.startsWith('REPLACE')) throw new Error('LIFF ID ยังไม่ได้ตั้งค่า');
      await window.liff.init({ liffId });
      if (!window.liff.isLoggedIn()) {
        window.liff.login({ redirectUri: window.location.href });
        return;
      }
      const prof = await window.liff.getProfile();
      if (!prof?.userId) throw new Error('ไม่ได้รับ userId จาก LINE');
      // Block accidentally pasting the same LINE as the primary
      if (prof.userId === user?.line_user_id) {
        setPartnerStatus({ ok: false, msg: 'LINE นี้คือบัญชีหลักของคุณเองอยู่แล้ว · ให้คู่ร่วมธุรกิจมาทำเองในเครื่องของเขา' });
        return;
      }

      // Persist immediately
      const { error } = await window.supabase.from('users').update({
        partner_line_user_id: prof.userId,
        partner_line_display_name: prof.displayName || null,
      }).eq('id', user.id);
      if (error) {
        if (error.code === '23505') {
          setPartnerStatus({ ok: false, msg: 'LINE userId นี้ถูกผูกไว้กับบัญชีอื่นแล้ว' });
          return;
        }
        throw error;
      }

      setPartnerLineId(prof.userId);
      setPartnerLineName(prof.displayName || '');
      setPartnerStatus({ ok: true, msg: `เชื่อม LINE ของ ${prof.displayName || prof.userId} เรียบร้อย` });
      if (onUpdate) await onUpdate();
    } catch (e) {
      setPartnerStatus({ ok: false, msg: e.message });
    }
  };

  const handleClearPartner = () => {
    if (!confirm('ลบข้อมูลคู่ร่วมธุรกิจทั้งหมด?')) return;
    setPartnerName('');
    setPartnerPhone('');
    setPartnerAvatar('');
    setPartnerLineId('');
    setPartnerLineName('');
    setShowPartner(false);
  };

  // Generic file → resized data-URL setter. Used by both the primary
  // avatar and the partner avatar picker (just swap the target setter).
  const handleImageChangeFor = (setter) => (e) => {
    const file = e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (event) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const MAX_SIZE = 400; // Drop size to 400px
        let w = img.width;
        let h = img.height;
        if (w > h) {
          if (w > MAX_SIZE) { h *= MAX_SIZE / w; w = MAX_SIZE; }
        } else {
          if (h > MAX_SIZE) { w *= MAX_SIZE / h; h = MAX_SIZE; }
        }
        canvas.width = w;
        canvas.height = h;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, w, h);
        const dataUrl = canvas.toDataURL('image/jpeg', 0.7);
        setter(dataUrl);
      };
      img.src = event.target.result;
    };
    reader.readAsDataURL(file);
  };
  const handleImageChange = handleImageChangeFor(setAvatar);
  const handlePartnerImageChange = handleImageChangeFor(setPartnerAvatar);

  const handleSave = async () => {
    if (!window.SB_READY || !user?.id) {
        alert('ระบบไม่ได้เชื่อมต่อฐานข้อมูล (Mock Mode)');
        return;
    }

    // ABO code is locked in the UI; we also leave it out of the patch so
    // it can't be changed from a manipulated client. The login identity
    // (auth.users → users.abo_code) stays consistent.

    setSaving(true);
    const patch = {
        name,
        phone_number: phone,
        country,
        avatar_url: avatar,
        partner_name:              showPartner ? (partnerName  || null) : null,
        partner_phone:             showPartner ? (partnerPhone || null) : null,
        partner_email:             null,  // field dropped from UI
        partner_avatar:            showPartner ? (partnerAvatar || null) : null,
        partner_line_user_id:      showPartner ? (partnerLineId || null) : null,
        partner_line_display_name: showPartner ? (partnerLineName || null) : null,
    };
    const { error } = await window.supabase.from('users').update(patch).eq('id', user.id);

    if (error) {
        alert('บันทึกไม่สำเร็จ: ' + error.message);
    } else {
        if (onUpdate) await onUpdate();
        alert('บันทึกข้อมูลเรียบร้อยแล้ว');
    }
    setSaving(false);
  };

  const primaryCol = (
    <div className="space-y-3">
      {/* Avatar */}
      <div className="flex flex-col items-center gap-2 pt-1 pb-3">
        <div className="relative group">
          <div className="w-20 h-20 rounded-full overflow-hidden border-4 border-white shadow-card bg-ink-100 flex items-center justify-center">
            {avatar
              ? <img src={avatar} className="w-full h-full object-cover" />
              : <Icon name="user" className="w-8 h-8 text-ink-300" />}
          </div>
          <button onClick={() => fileRef.current?.click()}
            className="absolute inset-0 bg-ink-900/40 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 rounded-full transition-opacity">
            <Icon name="refresh" className="w-5 h-5" />
          </button>
        </div>
        <input type="file" ref={fileRef} onChange={handleImageChange} accept="image/*" className="hidden" />
        <div className="text-[10px] text-ink-400">คลิกรูปเพื่ออัปโหลด</div>
      </div>

      <SetField label="ชื่อ-นามสกุล (ดึงจาก LINE)">
        <input value={name} disabled
          className="w-full h-10 px-3 text-sm bg-ink-50 border border-ink-100 text-ink-700 rounded-lg cursor-not-allowed" />
      </SetField>

      <SetField label="เบอร์ติดต่อ">
        <input value={phone} onChange={e => setPhone(e.target.value)}
          inputMode="tel" placeholder="08X-XXX-XXXX"
          className="w-full h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 num" />
      </SetField>

      {/* LINE ของฉัน */}
      <div className="rounded-lg border border-ink-100 bg-white p-3">
        <div className="flex items-center justify-between gap-2">
          <div className="flex-1 min-w-0">
            <div className="text-[11px] font-semibold text-ink-700 flex items-center gap-1.5">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="#06C755">
                <path d="M19 4H5a2 2 0 0 0-2 2v9c0 2.5 2.2 4.5 5 5l-.8 2.2a.5.5 0 0 0 .8.5l4-3.7H19a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z" />
              </svg>
              LINE ของฉัน
            </div>
            {user?.line_user_id ? (
              <div className="text-[11px] mt-1">
                <div className="text-emerald-700 font-semibold">✓ {user.line_display_name || '—'}</div>
                <div className="text-[10px] text-ink-400 num truncate" title={user.line_user_id}>{user.line_user_id}</div>
              </div>
            ) : (
              <div className="text-[10px] text-ink-500 mt-1 leading-relaxed">ยังไม่ได้ผูก · กดปุ่มเพื่อใช้ LINE ปัจจุบัน</div>
            )}
          </div>
          <button type="button" onClick={handleLinkMyLine} disabled={linkingLine}
            className="flex-shrink-0 h-8 px-2.5 text-[11px] font-semibold rounded-md text-white disabled:opacity-60"
            style={{ background: '#06C755' }}>
            {linkingLine ? '...' : (user?.line_user_id ? 'เปลี่ยน' : 'เชื่อม LINE')}
          </button>
        </div>
        {lineStatus && (
          <div className={`mt-2 text-[11px] rounded px-2 py-1.5 ${lineStatus.ok ? 'bg-emerald-50 text-emerald-700 border border-emerald-100' : 'bg-rose-50 text-rose-700 border border-rose-100'}`}>
            {lineStatus.msg}
          </div>
        )}
      </div>

      {/* Telegram ของฉัน */}
      <div className="rounded-lg border border-ink-100 bg-white p-3">
        <div className="flex items-center justify-between gap-2">
          <div className="flex-1 min-w-0">
            <div className="text-[11px] font-semibold text-ink-700 flex items-center gap-1.5">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="#229ED9">
                <path d="M22 3 1 11l6 2 3 8 4-4 6 5z"/>
              </svg>
              Telegram ของฉัน
            </div>
            {user?.telegram_chat_id ? (
              <div className="text-[11px] mt-1">
                <div className="text-sky-700 font-semibold">✓ {user.telegram_username ? `@${user.telegram_username}` : 'เชื่อมแล้ว'}</div>
                <div className="text-[10px] text-ink-400 num truncate" title={user.telegram_chat_id}>chat {user.telegram_chat_id}</div>
              </div>
            ) : (
              <div className="text-[10px] text-ink-500 mt-1 leading-relaxed">รับแจ้งเตือนผ่าน Telegram เพิ่ม → กดเชื่อม Telegram</div>
            )}
          </div>
          <button type="button" onClick={() => setTgLinkOpen('self')}
            className="flex-shrink-0 h-8 px-2.5 text-[11px] font-semibold rounded-md text-white inline-flex items-center gap-1"
            style={{ background: '#229ED9' }}>
            <svg className="w-3 h-3" viewBox="0 0 24 24" fill="currentColor"><path d="M22 3 1 11l6 2 3 8 4-4 6 5z"/></svg>
            {user?.telegram_chat_id ? 'เปลี่ยน' : 'เชื่อม Telegram'}
          </button>
        </div>
      </div>
    </div>
  );

  const partnerCol = (
    <div className="space-y-3">
      {/* Partner avatar — clickable upload, mirrors primary side */}
      <div className="flex flex-col items-center gap-2 pt-1 pb-3">
        <div className="relative group">
          <div className="w-20 h-20 rounded-full overflow-hidden border-4 border-white shadow-card bg-brand-50 flex items-center justify-center">
            {partnerAvatar
              ? <img src={partnerAvatar} className="w-full h-full object-cover" alt="partner avatar" />
              : <Icon name="users" className="w-8 h-8 text-brand-300" />}
          </div>
          <button type="button" onClick={() => partnerFileRef.current?.click()}
            className="absolute inset-0 bg-ink-900/40 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 rounded-full transition-opacity">
            <Icon name="refresh" className="w-5 h-5" />
          </button>
        </div>
        <input type="file" ref={partnerFileRef} onChange={handlePartnerImageChange} accept="image/*" className="hidden" />
        <div className="text-[10px] text-ink-400">คลิกรูปเพื่ออัปโหลด</div>
      </div>

      <SetField label="ชื่อคู่ร่วมธุรกิจ">
        <input value={partnerName} onChange={e => setPartnerName(e.target.value)}
          placeholder="เช่น คุณวรชัย ใจดี"
          className="w-full h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 bg-white" />
      </SetField>

      <SetField label="เบอร์ติดต่อ">
        <input value={partnerPhone} onChange={e => setPartnerPhone(e.target.value)}
          inputMode="tel" placeholder="08X-XXX-XXXX"
          className="w-full h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 num bg-white" />
      </SetField>

      {/* Email field removed — partner identity is now driven by LINE link */}

      {/* LINE ของคู่ร่วมธุรกิจ */}
      <div className="rounded-lg border border-ink-100 bg-white p-3">
        <div className="flex items-center justify-between gap-2">
          <div className="flex-1 min-w-0">
            <div className="text-[11px] font-semibold text-ink-700 flex items-center gap-1.5">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="#06C755">
                <path d="M19 4H5a2 2 0 0 0-2 2v9c0 2.5 2.2 4.5 5 5l-.8 2.2a.5.5 0 0 0 .8.5l4-3.7H19a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z" />
              </svg>
              LINE ของคู่ร่วมธุรกิจ
            </div>
            {partnerLineId ? (
              <div className="text-[11px] mt-1">
                <div className="text-emerald-700 font-semibold">✓ {partnerLineName || '—'}</div>
                <div className="text-[10px] text-ink-400 num truncate" title={partnerLineId}>{partnerLineId}</div>
              </div>
            ) : (
              <div className="text-[10px] text-ink-500 mt-1 leading-relaxed">สแกน QR ด้วยมือถือคู่ร่วมธุรกิจ → login LINE → เชื่อมข้อมูลอัตโนมัติ</div>
            )}
          </div>
          <div className="flex flex-col gap-1 flex-shrink-0">
            <button type="button" onClick={() => setPartnerLinkModalOpen(true)}
              className="h-8 px-2.5 text-[11px] font-semibold rounded-md text-white inline-flex items-center gap-1"
              style={{ background: '#06C755' }}
              title="สแกน QR ด้วยมือถือคู่ร่วมธุรกิจ">
              <svg className="w-3 h-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
                <rect x="3" y="3"  width="7" height="7" rx="1"/>
                <rect x="14" y="3" width="7" height="7" rx="1"/>
                <rect x="3" y="14" width="7" height="7" rx="1"/>
                <path d="M14 14h3M20 14v3M14 17v4M17 17h4M17 20h4"/>
              </svg>
              {partnerLineId ? 'เปลี่ยน' : 'สแกน QR'}
            </button>
            <button type="button" onClick={handleCapturePartnerLine}
              className="h-7 px-2 text-[10px] font-medium rounded-md border border-ink-200 text-ink-600 hover:bg-ink-50">
              เครื่องนี้
            </button>
          </div>
        </div>

        <PartnerLinkModal
          open={partnerLinkModalOpen}
          ownerUserId={user?.id}
          onClose={() => setPartnerLinkModalOpen(false)}
          onComplete={async (claimed) => {
            const displayName = claimed.partner_line_display_name || '';
            setPartnerLineId(claimed.partner_line_user_id);
            setPartnerLineName(displayName);
            // Auto-fill the "ชื่อคู่ร่วมธุรกิจ" field with the LINE display
            // name when empty, and persist it right away so the user doesn't
            // need to hit "บันทึก" separately to keep it.
            if (!partnerName?.trim() && displayName) {
              setPartnerName(displayName);
              if (window.SB_READY && user?.id) {
                const { error } = await window.supabase
                  .from('users')
                  .update({ partner_name: displayName })
                  .eq('id', user.id);
                if (error) console.warn('[Settings] partner_name autofill failed:', error.message);
              }
            }
            setPartnerStatus({ ok: true, msg: `เชื่อม LINE ของ ${displayName || claimed.partner_line_user_id} เรียบร้อย` });
            if (onUpdate) await onUpdate();
          }}
        />

        <details className="mt-2 group">
          <summary className="text-[10px] text-ink-400 hover:text-ink-700 cursor-pointer select-none">
            หรือใส่ LINE userId เอง ▾
          </summary>
          <div className="mt-2 grid grid-cols-1 gap-2">
            <input value={partnerLineId} onChange={e => setPartnerLineId(e.target.value)}
              placeholder="U1234abc..."
              className="h-9 px-2 text-[11px] num border border-ink-200 rounded-md outline-none focus:border-brand-500" />
            <input value={partnerLineName} onChange={e => setPartnerLineName(e.target.value)}
              placeholder="ชื่อแสดงผล (optional)"
              className="h-9 px-2 text-[11px] border border-ink-200 rounded-md outline-none focus:border-brand-500" />
          </div>
        </details>

        {partnerStatus && (
          <div className={`mt-2 text-[11px] rounded px-2 py-1.5 ${partnerStatus.ok ? 'bg-emerald-50 text-emerald-700 border border-emerald-100' : 'bg-rose-50 text-rose-700 border border-rose-100'}`}>
            {partnerStatus.msg}
          </div>
        )}
      </div>

      {/* Telegram ของคู่ร่วมธุรกิจ */}
      <div className="rounded-lg border border-ink-100 bg-white p-3">
        <div className="flex items-center justify-between gap-2">
          <div className="flex-1 min-w-0">
            <div className="text-[11px] font-semibold text-ink-700 flex items-center gap-1.5">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="#229ED9">
                <path d="M22 3 1 11l6 2 3 8 4-4 6 5z"/>
              </svg>
              Telegram ของคู่ร่วมธุรกิจ
            </div>
            {user?.partner_telegram_chat_id ? (
              <div className="text-[11px] mt-1">
                <div className="text-sky-700 font-semibold">✓ {user.partner_telegram_username ? `@${user.partner_telegram_username}` : 'เชื่อมแล้ว'}</div>
                <div className="text-[10px] text-ink-400 num truncate">chat {user.partner_telegram_chat_id}</div>
              </div>
            ) : (
              <div className="text-[10px] text-ink-500 mt-1 leading-relaxed">รับแจ้งเตือนผ่าน Telegram เพิ่ม → กดเชื่อมให้คู่</div>
            )}
          </div>
          <button type="button" onClick={() => setTgLinkOpen('partner')}
            className="flex-shrink-0 h-8 px-2.5 text-[11px] font-semibold rounded-md text-white inline-flex items-center gap-1"
            style={{ background: '#229ED9' }}>
            <svg className="w-3 h-3" viewBox="0 0 24 24" fill="currentColor"><path d="M22 3 1 11l6 2 3 8 4-4 6 5z"/></svg>
            {user?.partner_telegram_chat_id ? 'เปลี่ยน' : 'เชื่อม Telegram'}
          </button>
        </div>
      </div>
    </div>
  );

  // Locked placeholder for the partner column — same shape as the unlocked
  // form so the page doesn't reflow when the user clicks the unlock button.
  const partnerLocked = (
    <div className="relative">
      {/* Faded, non-interactive skeleton matching partnerCol's height */}
      <div className="space-y-3 opacity-30 pointer-events-none select-none" aria-hidden="true">
        <div className="flex flex-col items-center gap-2 pt-1 pb-3">
          <div className="w-20 h-20 rounded-full bg-ink-100 border-4 border-white" />
          <div className="text-[10px] text-ink-400">คู่ร่วมธุรกิจ</div>
        </div>
        <div className="h-[58px] rounded-lg bg-ink-50/60" />
        <div className="h-[58px] rounded-lg bg-ink-50/60" />
        <div className="h-[58px] rounded-lg bg-ink-50/60" />
        <div className="h-[88px] rounded-lg bg-ink-50/60" />
      </div>

      {/* Centered unlock button */}
      <div className="absolute inset-0 flex items-center justify-center">
        <button
          type="button"
          onClick={() => setShowPartner(true)}
          className="group flex flex-col items-center gap-3 px-6 py-5 rounded-2xl bg-white border-2 border-dashed border-ink-200 hover:border-brand-500 hover:bg-brand-50/40 shadow-card transition-all">
          <div className="w-12 h-12 rounded-full bg-brand-50 group-hover:bg-brand-500 text-brand-500 group-hover:text-white flex items-center justify-center transition-colors">
            <Icon name="plus" className="w-6 h-6" strokeWidth={2.5} />
          </div>
          <div className="text-center">
            <div className="text-sm font-semibold text-ink-800 group-hover:text-brand-700">เพิ่มข้อมูลคู่ร่วมธุรกิจ</div>
            <div className="text-[11px] text-ink-400 mt-0.5 max-w-[180px] leading-relaxed">
              ปลดล็อกฝั่งนี้เพื่อกรอกชื่อ · เบอร์ · LINE
            </div>
          </div>
        </button>
      </div>
    </div>
  );

  return (
    <Card title="ข้อมูลพื้นฐาน">
      {/* Telegram deep-link modal — opens for primary or partner. */}
      <TelegramLinkModal
        target={tgLinkOpen}
        ownerUserId={user?.id}
        onClose={() => setTgLinkOpen(null)}
        onComplete={async () => {
          setTgLinkOpen(null);
          if (onUpdate) await onUpdate();
        }}
      />
      <div className="space-y-5">
        {/* ============ Two-column layout (always) ============ */}
        <div className="grid grid-cols-1 md:grid-cols-2 gap-5">
          {/* Primary column */}
          <div className="md:pr-5 md:border-r md:border-ink-100">
            <div className="flex items-center justify-between mb-3">
              <span className="text-[10px] uppercase tracking-wider font-bold text-ink-500">คนหลัก</span>
              <Pill color="#2F5DE5" tint="#EEF4FF" size="xs">คุณ</Pill>
            </div>
            {primaryCol}
          </div>

          {/* Partner column — locked until user clicks unlock */}
          <div>
            <div className="flex items-center justify-between mb-3">
              <span className={`text-[10px] uppercase tracking-wider font-bold ${showPartner ? 'text-brand-600' : 'text-ink-300'}`}>
                คู่ร่วมธุรกิจ
              </span>
              {showPartner ? (
                <button type="button" onClick={handleClearPartner}
                  className="text-[11px] text-rose-600 hover:text-rose-700 hover:bg-rose-50 px-2 py-0.5 rounded-md font-medium inline-flex items-center gap-1">
                  <Icon name="x" className="w-3 h-3" /> ลบ
                </button>
              ) : (
                <Pill color="#94A3B8" tint="#F1F5F9" size="xs">ปิดอยู่</Pill>
              )}
            </div>
            {showPartner ? partnerCol : partnerLocked}
          </div>
        </div>

        {/* Shared fields — apply to the whole ABO account */}
        <div className="pt-4 border-t border-ink-100 space-y-3">
          <div className="text-[10px] uppercase tracking-wider font-bold text-ink-500">ข้อมูลร่วม · บัญชี ABO</div>
          <SetField label="ABO Code (10 หลัก)">
            {/* Read-only. The ABO code is the account's login identity —
                changing it would orphan the user from their own data and
                the partner pairing. Show as locked + a small note. */}
            <div className="relative">
              <input
                value={abo}
                readOnly
                className="w-full h-10 pl-3 pr-24 text-sm border border-ink-200 rounded-lg outline-none num bg-ink-50 text-ink-500 cursor-not-allowed"
                title="แก้ไขเลข ABO ไม่ได้ — ใช้เป็นรหัสสำหรับ login"
              />
              <div className="absolute right-2 top-1/2 -translate-y-1/2 inline-flex items-center gap-1 text-[10px] font-semibold text-ink-400 bg-white border border-ink-200 rounded-md px-1.5 py-0.5">
                <Icon name="lock" className="w-3 h-3" /> Locked
              </div>
            </div>
            <div className="text-[10px] text-ink-400 mt-1.5 leading-relaxed">
              เลข ABO ผูกกับบัญชี login — แก้ไขที่นี่ไม่ได้
              {' '}หากผิด กรุณาติดต่อแอดมินเพื่อย้ายข้อมูลให้
            </div>
          </SetField>

          <SetField label="ประเทศหลัก">
            <div className="flex items-center gap-2 flex-wrap">
              {window.COUNTRIES.map(c => (
                <button key={c.id} onClick={() => setCountry(c.id)}
                  className={`flex items-center gap-2 px-3 h-10 rounded-lg border text-sm ${country === c.id ? 'border-brand-500 bg-brand-50 text-brand-700 font-semibold' : 'border-ink-200 text-ink-600 hover:bg-ink-50'}`}>
                  <span className="text-base">{c.flag}</span>{c.label}
                </button>
              ))}
            </div>
          </SetField>
        </div>

        <div className="pt-3 border-t border-ink-100">
          <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />} onClick={handleSave} disabled={saving}>
            {saving ? 'กำลังบันทึก...' : 'บันทึก'}
          </Btn>
        </div>
      </div>
    </Card>
  );
}

// ===================== Account Security =====================
// Lets the logged-in user set or change their ABO password. The LINE
// linking UI lives over in ProfileEditor now so the whole "who am I" story
// is in one place.

function AccountSecurity({ user, onRefreshUser }) {
  const [pw1, setPw1] = useState('');
  const [pw2, setPw2] = useState('');
  const [show, setShow] = useState(false);
  const [savingPw, setSavingPw] = useState(false);
  const [pwStatus, setPwStatus] = useState(null); // {ok, msg}

  const aboCode = user?.abo_code || '';

  const handleSavePassword = async () => {
    setPwStatus(null);
    if (!window.SB_READY) {
      setPwStatus({ ok: false, msg: 'ระบบไม่ได้เชื่อมต่อฐานข้อมูล (Mock Mode)' });
      return;
    }
    if (!aboCode || !/^\d{10}$/.test(aboCode)) {
      setPwStatus({ ok: false, msg: 'ต้องตั้งเลข ABO 10 หลักให้ครบก่อน (แท็บ Profile)' });
      return;
    }
    if (pw1.length < 6) { setPwStatus({ ok: false, msg: 'Password ต้องยาวอย่างน้อย 6 ตัวอักษร' }); return; }
    if (pw1 !== pw2)   { setPwStatus({ ok: false, msg: 'Password 2 ช่องไม่ตรงกัน' }); return; }

    setSavingPw(true);
    // Route through the `set-password` edge function — it uses service role
    // to call admin.auth.admin.updateUserById, which bypasses both client-
    // side email-validation and the email-change confirmation flow.
    const { data, error } = await window.supabase.functions.invoke('set-password', {
      body: { aboCode, password: pw1 },
    });
    if (error) {
      setPwStatus({ ok: false, msg: error.message });
    } else if (data?.error) {
      setPwStatus({ ok: false, msg: data.error });
    } else {
      setPwStatus({ ok: true, msg: `ตั้ง password เรียบร้อย · ครั้งหน้า login ด้วย ${aboCode} + password นี้ได้เลย` });
      setPw1(''); setPw2('');
      if (onRefreshUser) await onRefreshUser();
    }
    setSavingPw(false);
  };

  return (
    <Card pad={false}>
      <div className="px-5 pt-4 pb-3 border-b border-ink-100 flex items-center gap-2.5">
        <div className="w-8 h-8 rounded-md bg-ink-900 text-white flex items-center justify-center">
          <Icon name="lock" className="w-4 h-4" />
        </div>
        <div>
          <h3 className="text-sm font-semibold text-ink-900">Account Security</h3>
          <p className="text-[11px] text-ink-400">ตั้ง password สำหรับ login ด้วย ABO · เชื่อม LINE อยู่ในแท็บ Profile</p>
        </div>
      </div>

      <div className="p-5">
        {/* Set / change password */}
        <div>
          <div className="flex items-center justify-between mb-2">
            <div>
              <div className="text-xs font-semibold text-ink-800">ตั้ง / เปลี่ยน password</div>
              <div className="text-[11px] text-ink-400">
                username สำหรับ login: <span className="num text-ink-700 font-semibold">{aboCode || '— ต้องตั้ง ABO ก่อน —'}</span>
              </div>
            </div>
            {user?.email && (
              <span className="text-[10px] text-ink-400 num truncate max-w-[180px]" title={user.email}>{user.email}</span>
            )}
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
            <input
              type={show ? 'text' : 'password'}
              value={pw1}
              onChange={e => setPw1(e.target.value)}
              placeholder="Password ใหม่ (≥ 6 ตัวอักษร)"
              autoComplete="new-password"
              className="h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-500/15"
            />
            <input
              type={show ? 'text' : 'password'}
              value={pw2}
              onChange={e => setPw2(e.target.value)}
              placeholder="ยืนยัน password อีกครั้ง"
              autoComplete="new-password"
              className="h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-500/15"
            />
          </div>
          <div className="mt-2 flex items-center justify-between gap-2">
            <label className="text-[11px] text-ink-500 inline-flex items-center gap-1.5 cursor-pointer">
              <input type="checkbox" checked={show} onChange={e => setShow(e.target.checked)} className="w-3.5 h-3.5" />
              แสดง password
            </label>
            <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />}
              onClick={handleSavePassword} disabled={savingPw || !pw1 || !pw2}>
              {savingPw ? 'กำลังบันทึก...' : 'บันทึก password'}
            </Btn>
          </div>
          {pwStatus && (
            <div className={`mt-2 text-[11px] rounded px-3 py-2 ${pwStatus.ok ? 'bg-emerald-50 text-emerald-700 border border-emerald-100' : 'bg-rose-50 text-rose-700 border border-rose-100'}`}>
              {pwStatus.msg}
            </div>
          )}
        </div>
      </div>
    </Card>
  );
}

// ===================== Social Accounts editor =====================
// Self-contained: platform meta + handle helpers live here (they used to be
// globals in views/social.jsx, removed in the Social Focus rewrite).
// Writes to users.social_accounts (jsonb).
const SOCIAL_PLATFORMS_META = [
  { id: 'instagram', label: 'Instagram',  color: '#E1306C', logo: 'instagram', profile: 'https://instagram.com/',       placeholder: '@username หรือ instagram.com/username' },
  { id: 'tiktok',    label: 'TikTok',     color: '#000000', logo: 'tiktok',    profile: 'https://www.tiktok.com/@',    placeholder: '@username' },
  { id: 'youtube',   label: 'YouTube',    color: '#FF0000', logo: 'youtube',   profile: 'https://www.youtube.com/@',   placeholder: '@channel' },
  { id: 'facebook',  label: 'Facebook',   color: '#1877F2', logo: 'facebook',  profile: 'https://www.facebook.com/',   placeholder: 'ชื่อเพจ / facebook.com/page' },
  { id: 'threads',   label: 'Threads',    color: '#000000', logo: 'threads',   profile: 'https://www.threads.net/@',   placeholder: '@username' },
  { id: 'line',      label: 'LINE OA',    color: '#06C755', logo: 'line',      profile: 'https://line.me/R/ti/p/~',    placeholder: '@lineid' },
];

const _cleanHandle = (raw) => {
  if (!raw) return '';
  let h = String(raw).trim();
  if (/^https?:\/\//i.test(h)) {
    try { const u = new URL(h); const seg = u.pathname.split('/').filter(Boolean).pop() || ''; h = seg || u.hostname; } catch (e) { /* keep h */ }
  }
  return h.replace(/^@+/, '').trim();
};

const _profileUrl = (meta, handle) => {
  if (!handle) return '';
  if (meta.id === 'facebook' && /facebook\.com/i.test(handle)) {
    return /^https?:/i.test(handle) ? handle : 'https://' + handle;
  }
  return (meta.profile || '') + handle;
};

// Small brand badge — circle tinted with the platform colour + first letter.
// (No external logo dependency, so it can't be left undefined.)
function PlatformLogo({ id, size = 28 }) {
  const meta = SOCIAL_PLATFORMS_META.find(m => m.id === id) || { color: '#64748B', label: id || '?' };
  const ch = (meta.label || '?').trim().charAt(0).toUpperCase();
  return (
    <span style={{ width: size, height: size, background: meta.color, fontSize: size * 0.46 }}
      className="rounded-lg inline-flex items-center justify-center text-white font-bold flex-shrink-0">
      {ch}
    </span>
  );
}

function SocialAccountsEditor({ user, onUpdate }) {
  const [accounts, setAccounts] = useState({});
  const [saving, setSaving]     = useState(false);
  const [status, setStatus]     = useState(null); // {ok,msg}

  useEffect(() => {
    setAccounts(user?.social_accounts || {});
  }, [user?.social_accounts]);

  const set = (platformId, patch) => setAccounts(prev => ({
    ...prev,
    [platformId]: { ...(prev[platformId] || {}), ...patch },
  }));

  const clearPlatform = (platformId) => setAccounts(prev => {
    const next = { ...prev };
    delete next[platformId];
    return next;
  });

  // enabled defaults to true when a handle exists (back-compat for old rows).
  const isEnabled = (acc) => acc && _cleanHandle(acc.handle) && acc.enabled !== false;

  const handleSave = async () => {
    setStatus(null);
    if (!window.SB_READY || !user?.id) {
      setStatus({ ok: false, msg: 'ระบบไม่ได้เชื่อมต่อฐานข้อมูล' });
      return;
    }
    setSaving(true);
    // Store only handle + enabled flag. Metrics come from the API (social_stats);
    // the nightly refresh + Dashboard skip any platform with enabled === false.
    const cleaned = {};
    for (const meta of SOCIAL_PLATFORMS_META) {
      const acc = accounts[meta.id];
      if (!acc) continue;
      const handle = _cleanHandle(acc.handle);
      if (!handle) continue;
      cleaned[meta.id] = { handle, enabled: acc.enabled !== false };
    }
    const { error } = await window.supabase.from('users').update({ social_accounts: cleaned }).eq('id', user.id);
    setSaving(false);
    if (error) {
      setStatus({ ok: false, msg: 'บันทึกไม่สำเร็จ: ' + error.message });
      return;
    }
    setAccounts(cleaned);
    setStatus({ ok: true, msg: 'บันทึกเรียบร้อย · ดึงข้อมูลรอบถัดไปจะอัปเดต Social Dashboard ให้' });
    if (onUpdate) await onUpdate();
  };

  const filledCount = Object.values(accounts).filter(isEnabled).length;

  return (
    <Card pad={false}>
      <div className="px-5 pt-4 pb-3 border-b border-ink-100 flex items-center gap-2.5">
        <div className="w-8 h-8 rounded-md bg-gradient-to-br from-fuchsia-500 to-orange-400 text-white flex items-center justify-center">
          <Icon name="share-2" className="w-4 h-4" />
        </div>
        <div className="flex-1 min-w-0">
          <h3 className="text-sm font-semibold text-ink-900">Social Accounts</h3>
          <p className="text-[11px] text-ink-400">
            ใส่ username/URL ของแต่ละแพลตฟอร์ม · ตัวเลข (ผู้ติดตาม, ER ฯลฯ) ดึงอัตโนมัติทุกเที่ยงคืน · เปิดเฉพาะที่อยากแสดง {filledCount > 0 && <span className="text-emerald-700 font-semibold">({filledCount} เปิดอยู่)</span>}
          </p>
        </div>
      </div>

      <div className="p-5 space-y-3">
        {SOCIAL_PLATFORMS_META.map(meta => {
          const acc = accounts[meta.id] || {};
          const handle = _cleanHandle(acc.handle);
          const url    = _profileUrl(meta, handle);
          const filled = !!handle;
          const on      = isEnabled(acc);

          return (
            <div key={meta.id}
              className={`rounded-xl border p-3 transition-colors ${on ? 'border-ink-200 bg-white' : filled ? 'border-ink-200 bg-ink-50/40' : 'border-dashed border-ink-200 bg-ink-50/30'}`}>
              {/* Header */}
              <div className="flex items-center gap-2.5 mb-3">
                <PlatformLogo id={meta.id} size={28} />
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2">
                    <span className="text-sm font-semibold text-ink-900">{meta.label}</span>
                    {on
                      ? <Pill color="#10B981" tint="#E7F8F1" size="xs">แสดง</Pill>
                      : filled
                        ? <Pill color="#D97706" tint="#FEF3C7" size="xs">ปิดอยู่</Pill>
                        : <Pill color="#94A3B8" tint="#F1F5F9" size="xs">ยังไม่ตั้ง</Pill>}
                  </div>
                  {url && (
                    <a href={url} target="_blank" rel="noopener noreferrer"
                      className="text-[10px] text-ink-400 hover:text-brand-600 inline-flex items-center gap-1">
                      {url} <Icon name="arrowR" className="w-2.5 h-2.5" />
                    </a>
                  )}
                </div>
                {/* Enable / disable toggle (only meaningful once a handle is set) */}
                <button type="button" disabled={!filled}
                  onClick={() => set(meta.id, { enabled: !on })}
                  title={on ? 'ปิดไม่ให้แสดงใน Social Dashboard' : 'เปิดให้แสดง'}
                  className={`relative w-10 h-6 rounded-full transition-colors flex-shrink-0 ${!filled ? 'bg-ink-100 cursor-not-allowed' : on ? 'bg-emerald-500' : 'bg-ink-300'}`}>
                  <span className={`absolute top-0.5 left-0.5 w-5 h-5 rounded-full bg-white shadow transition-transform ${on ? 'translate-x-4' : ''}`} />
                </button>
                {filled && (
                  <button type="button" onClick={() => clearPlatform(meta.id)}
                    className="text-[11px] text-rose-600 hover:bg-rose-50 px-2 py-1 rounded-md font-medium">
                    ลบ
                  </button>
                )}
              </div>

              {/* Handle input */}
              <SetField label="Username / URL">
                <input
                  value={acc.handle || ''}
                  onChange={e => set(meta.id, { handle: e.target.value })}
                  placeholder={meta.placeholder}
                  className="w-full h-9 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500 bg-white" />
              </SetField>
            </div>
          );
        })}

        {status && (
          <div className={`text-[11px] rounded px-3 py-2 ${status.ok ? 'bg-emerald-50 text-emerald-700 border border-emerald-100' : 'bg-rose-50 text-rose-700 border border-rose-100'}`}>
            {status.msg}
          </div>
        )}

        <div className="pt-2 flex items-center justify-between gap-2">
          <p className="text-[10px] text-ink-400 leading-relaxed flex-1">
            ℹ︎ ระบบดึงผู้ติดตาม/Engagement จาก API ให้อัตโนมัติทุกเที่ยงคืน · ปิดสวิตช์แพลตฟอร์มไหน จะไม่ดึงและไม่แสดงใน Social Dashboard
          </p>
          <Btn variant="brand" size="sm" icon={<Icon name="check" className="w-3.5 h-3.5" />}
            onClick={handleSave} disabled={saving}>
            {saving ? 'กำลังบันทึก...' : 'บันทึก'}
          </Btn>
        </div>
      </div>
    </Card>
  );
}

function LoginIntegrations({ data, onSave, loading, user, onRefreshUser }) {
  const lineUserId = user?.line_user_id || user?.lineUserId;
  const items = [
    { id: 'line',   label: 'LINE',            desc: 'เข้าระบบและรับการแจ้งเตือนผ่าน LINE',          icon: 'line',     color: '#06C755', account: lineUserId || 'Connected' },
    { id: 'zoom',   label: 'Zoom',            desc: 'สร้างห้องประชุมจากปฏิทินอัตโนมัติ',              icon: 'zoom',     color: '#2D8CFF', account: 'zoom.us' },
    { id: 'gcal',   label: 'Google Calendar', desc: 'Sync นัดหมายไปยัง Google Calendar',          icon: 'calendar', color: '#4285F4', account: 'google.com' },
    { id: 'ig',     label: 'Instagram',       desc: 'ดึงโปรไฟล์ผู้มุ่งหวังจาก IG handle',              icon: 'sparkles', color: '#E1306C', account: 'instagram.com' },
  ];

  const toggle = (id) => onSave({ [id]: !data[id] });

  return (
    <div className="space-y-4">
      <AccountSecurity user={user} onRefreshUser={onRefreshUser} />
    </div>
  );
}

// ===================== Content Hashtags =====================
function HashtagSettings() {
  const [tags, setTags] = useState([
    { id: 1, label: '#พัฒนาตัวเอง',  enabled: true,  category: 'self' },
    { id: 2, label: '#mindset',       enabled: true,  category: 'self' },
    { id: 3, label: '#ธุรกิจ',          enabled: true,  category: 'biz' },
    { id: 4, label: '#รายได้เสริม',     enabled: true,  category: 'biz' },
    { id: 5, label: '#ลดน้ำหนัก',      enabled: true,  category: 'health' },
    { id: 6, label: '#bodykey',       enabled: true,  category: 'health' },
    { id: 7, label: '#lifestyle',     enabled: false, category: 'life' },
    { id: 8, label: '#wellness',      enabled: false, category: 'life' },
  ]);
  const [newTag, setNewTag] = useState('');

  const toggle = (id) => setTags(tags.map(t => t.id === id ? { ...t, enabled: !t.enabled } : t));
  const remove = (id) => setTags(tags.filter(t => t.id !== id));
  const add = () => {
    if (!newTag.trim()) return;
    const label = newTag.startsWith('#') ? newTag : '#' + newTag;
    setTags([...tags, { id: Date.now(), label, enabled: true, category: 'custom' }]);
    setNewTag('');
  };

  const catColors = { self: '#7C3AED', biz: '#2F5DE5', health: '#10B981', life: '#F59E0B', custom: '#64748B' };
  const catLabel = { self: 'พัฒนาตัวเอง', biz: 'ธุรกิจ', health: 'สุขภาพ', life: 'Lifestyle', custom: 'อื่นๆ' };

  return (
    <Card title="Hashtag สำหรับการ Track Content"
          action={<span className="text-[11px] text-ink-400">ใช้แสดงเนื้อหา trending ในหน้า Social Dashboard</span>}>
      <div className="mb-4 flex items-center gap-2">
        <input value={newTag} onChange={e => setNewTag(e.target.value)} onKeyDown={e => e.key === 'Enter' && add()}
               className="flex-1 h-10 px-3 text-sm border border-ink-200 rounded-lg outline-none focus:border-brand-500"
               placeholder="พิมพ์ hashtag ใหม่ เช่น #moneymindset" />
        <Btn variant="brand" size="sm" icon={<Icon name="plus" />} onClick={add}>เพิ่ม</Btn>
      </div>

      <div className="space-y-3">
        {['self', 'biz', 'health', 'life', 'custom'].map(cat => {
          const list = tags.filter(t => t.category === cat);
          if (list.length === 0) return null;
          return (
            <div key={cat}>
              <div className="flex items-center gap-2 mb-2">
                <Pill color={catColors[cat]} tint={catColors[cat] + '20'} size="xs">{catLabel[cat]}</Pill>
                <span className="text-[10px] text-ink-400 num">{list.length} tags</span>
              </div>
              <div className="flex flex-wrap gap-1.5">
                {list.map(t => (
                  <div key={t.id} className={`group inline-flex items-center gap-1.5 pl-3 pr-1.5 py-1.5 rounded-full text-xs border ${t.enabled ? 'bg-brand-50 border-brand-200 text-brand-800' : 'bg-ink-50 border-ink-200 text-ink-400'}`}>
                    <button onClick={() => toggle(t.id)} className="font-medium">{t.label}</button>
                    <button onClick={() => remove(t.id)} className="w-5 h-5 rounded-full hover:bg-rose-100 hover:text-rose-600 text-ink-400 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
                      <Icon name="x" className="w-3 h-3" strokeWidth={2.5} />
                    </button>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </Card>
  );
}

function SetField({ label, children }) {
  return (
    <div>
      <label className="text-[11px] uppercase tracking-wider font-semibold text-ink-500 mb-1.5 block">{label}</label>
      {children}
    </div>
  );
}

window.SettingsView = SettingsView;
