/* Auth — simple email+password login, persisted in localStorage.
   Not real backend security; this is a prototype. */

const AUTH_KEY = 'ba_aptis_auth_v1';
const USERS_KEY = 'ba_aptis_users_v1';

function getStoredUsers() {
  try { return JSON.parse(localStorage.getItem(USERS_KEY) || '{}'); }
  catch { return {}; }
}
function setStoredUsers(u) {
  localStorage.setItem(USERS_KEY, JSON.stringify(u));
}
function getCurrentUser() {
  try { return JSON.parse(localStorage.getItem(AUTH_KEY) || 'null'); }
  catch { return null; }
}
function setCurrentUser(u) {
  if (u) localStorage.setItem(AUTH_KEY, JSON.stringify(u));
  else localStorage.removeItem(AUTH_KEY);
  // Tell other tabs/components
  window.dispatchEvent(new CustomEvent('ba-auth-change', { detail: u }));
}

function registerUser({ name, email, password }) {
  const users = getStoredUsers();
  if (users[email.toLowerCase()]) {
    throw new Error('Ya existe una cuenta con este email. Inicia sesión.');
  }
  users[email.toLowerCase()] = { name, email, password, createdAt: Date.now() };
  setStoredUsers(users);
  const u = { name, email, createdAt: users[email.toLowerCase()].createdAt };
  setCurrentUser(u);
  return u;
}

function loginUser({ email, password }) {
  const users = getStoredUsers();
  const rec = users[email.toLowerCase()];
  if (!rec) throw new Error('No encontramos una cuenta con ese email.');
  if (rec.password !== password) throw new Error('La contraseña no es correcta.');
  const u = { name: rec.name, email: rec.email, createdAt: rec.createdAt };
  setCurrentUser(u);
  return u;
}

function logoutUser() {
  setCurrentUser(null);
}

function useAuth() {
  const [user, setUser] = React.useState(() => getCurrentUser());
  React.useEffect(() => {
    const h = (e) => setUser(e.detail || getCurrentUser());
    window.addEventListener('ba-auth-change', h);
    window.addEventListener('storage', () => setUser(getCurrentUser()));
    return () => window.removeEventListener('ba-auth-change', h);
  }, []);
  return user;
}

// ---- Auth modal (login + register, switchable) ----
const AuthModal = ({ open, onClose, initialMode = 'login' }) => {
  const [mode, setMode] = React.useState(initialMode);
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [error, setError] = React.useState('');

  React.useEffect(() => {
    if (open) { setError(''); setMode(initialMode); }
  }, [open, initialMode]);

  if (!open) return null;

  const submit = (e) => {
    e.preventDefault();
    setError('');
    try {
      if (mode === 'register') {
        if (!name.trim()) { setError('Por favor, escribe tu nombre.'); return; }
        if (password.length < 6) { setError('La contraseña debe tener al menos 6 caracteres.'); return; }
        registerUser({ name: name.trim(), email: email.trim(), password });
      } else {
        loginUser({ email: email.trim(), password });
      }
      onClose && onClose();
    } catch (err) {
      setError(err.message || 'Ha ocurrido un error.');
    }
  };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(11, 31, 55, 0.55)',
      backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)',
      display: 'grid', placeItems: 'center', zIndex: 1000, padding: 20,
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: '#fff', borderRadius: 18,
        width: '100%', maxWidth: 440,
        boxShadow: 'var(--shadow-lg)',
        padding: 32, position: 'relative',
      }}>
        <button onClick={onClose} aria-label="Cerrar" style={{
          position: 'absolute', top: 14, right: 14,
          background: 'transparent', border: 'none', cursor: 'pointer',
          color: 'var(--ink-muted)', fontSize: 22, lineHeight: 1, padding: 6,
        }}>×</button>

        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
          <div style={{
            width: 36, height: 36, borderRadius: 8, background: '#fff',
            border: '1px solid var(--line)', padding: 3,
          }}>
            <img src="assets/bristol-mark.jpeg" alt="" style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
          </div>
          <div>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.1em',
              textTransform: 'uppercase', color: 'var(--ink-muted)' }}>Bristol Academy</div>
            <div style={{ fontSize: 14, fontWeight: 700 }}>Aptis Exam Trainer</div>
          </div>
        </div>

        <h2 style={{ fontSize: 22, margin: '14px 0 6px', letterSpacing: '-0.015em' }}>
          {mode === 'login' ? 'Iniciar sesión' : 'Crear cuenta'}
        </h2>
        <p style={{ color: 'var(--ink-soft)', fontSize: 14, margin: '0 0 22px' }}>
          {mode === 'login'
            ? 'Entra para continuar tus simulacros y ver tus resultados.'
            : 'Crea tu cuenta para guardar progreso y enviar Writings a tu profesor.'}
        </p>

        <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          {mode === 'register' && (
            <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-soft)' }}>Nombre completo</span>
              <input type="text" value={name} onChange={(e) => setName(e.target.value)}
                required autoFocus
                placeholder="Daniel García"
                style={authInputStyle} />
            </label>
          )}
          <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-soft)' }}>Email</span>
            <input type="email" value={email} onChange={(e) => setEmail(e.target.value)}
              required autoFocus={mode === 'login'}
              placeholder="tu@email.com"
              style={authInputStyle} />
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--ink-soft)' }}>Contraseña</span>
            <input type="password" value={password} onChange={(e) => setPassword(e.target.value)}
              required
              minLength={mode === 'register' ? 6 : undefined}
              placeholder={mode === 'register' ? 'Mínimo 6 caracteres' : '••••••••'}
              style={authInputStyle} />
          </label>

          {error && (
            <div style={{
              background: 'var(--danger-soft)', border: '1px solid var(--danger)',
              borderRadius: 8, padding: '10px 12px', fontSize: 13, color: 'var(--danger)',
            }}>
              {error}
            </div>
          )}

          <button type="submit" className="btn btn-primary btn-lg" style={{ marginTop: 8 }}>
            {mode === 'login' ? 'Entrar' : 'Crear cuenta'}
            <Icon name="arrow" size={14} />
          </button>
        </form>

        <div style={{ marginTop: 18, fontSize: 13.5, color: 'var(--ink-soft)', textAlign: 'center' }}>
          {mode === 'login' ? (
            <>¿Todavía no tienes cuenta?{' '}
              <button onClick={() => { setMode('register'); setError(''); }}
                style={{ background:'transparent', border:'none', color: 'var(--accent-strong)',
                  fontWeight: 700, cursor: 'pointer' }}>
                Crear cuenta
              </button>
            </>
          ) : (
            <>¿Ya tienes cuenta?{' '}
              <button onClick={() => { setMode('login'); setError(''); }}
                style={{ background:'transparent', border:'none', color: 'var(--accent-strong)',
                  fontWeight: 700, cursor: 'pointer' }}>
                Iniciar sesión
              </button>
            </>
          )}
        </div>

        <div style={{ marginTop: 18, fontSize: 11.5, color: 'var(--ink-muted)',
          textAlign: 'center', lineHeight: 1.5 }}>
          Al crear tu cuenta aceptas nuestros términos.
          Tus datos se usan únicamente para gestionar tu acceso a la plataforma.
        </div>
      </div>
    </div>
  );
};

const authInputStyle = {
  padding: '12px 14px',
  border: '1px solid var(--line)',
  borderRadius: 10,
  fontFamily: 'inherit',
  fontSize: 14.5,
  outline: 'none',
  width: '100%',
};

// ---- Send Writing via email ----
// Uses Web3Forms — delivers emails directly to the teacher's inbox without
// any activation step. We POST the form data through a hidden iframe to avoid
// CORS issues from any origin.
const TEACHER_EMAIL = 'examsbristolacademy@gmail.com';
const WEB3FORMS_ACCESS_KEY = '37943c7a-4d7f-418a-95fc-b264fd02859d';
const WEB3FORMS_ENDPOINT = 'https://api.web3forms.com/submit';

function sendWritingByEmail({ user, examNum, topic, parts, responses }) {
  return new Promise((resolve) => {
    // ---- Build plain-text body ----
    const lines = [];
    lines.push(`Aptis General — Writing submission`);
    lines.push(`=================================`);
    lines.push(``);
    lines.push(`Alumno: ${user?.name || '(sin nombre)'}`);
    lines.push(`Email del alumno: ${user?.email || '(sin email)'}`);
    lines.push(`Examen: Exam ${examNum}`);
    if (topic) lines.push(`Tema: ${topic}`);
    lines.push(`Fecha: ${new Date().toLocaleString('es-ES')}`);
    lines.push(``);
    lines.push(`---------------------------------`);
    lines.push(``);
    parts.forEach((part, pi) => {
      lines.push(`>> ${part.label}`);
      lines.push(``);
      part.items.forEach((it, ii) => {
        const ans = responses[`${pi}-${ii}`] || '(sin respuesta)';
        if (it.prompt) {
          lines.push(`PROMPT: ${it.prompt.replace(/\n/g, ' ').slice(0, 400)}`);
        }
        lines.push(`RESPUESTA:`);
        lines.push(ans);
        lines.push(``);
      });
      lines.push(``);
    });
    const body = lines.join('\n');
    const subject = `[Aptis Trainer] Writing Exam ${examNum} — ${user?.name || user?.email || 'alumno'}`;

    // Try AJAX first (Web3Forms supports CORS)
    fetch(WEB3FORMS_ENDPOINT, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
      body: JSON.stringify({
        access_key: WEB3FORMS_ACCESS_KEY,
        subject: subject,
        from_name: user?.name || 'Aptis Trainer',
        replyto: user?.email || '',
        name: user?.name || '(sin nombre)',
        email: user?.email || '',
        examen: `Exam ${examNum}`,
        fecha: new Date().toLocaleString('es-ES'),
        message: body,
      }),
    })
      .then(res => res.json())
      .then(data => {
        if (data.success) {
          resolve({ ok: true, message: 'Email enviado correctamente.' });
        } else {
          resolve({ ok: false, message: data.message || 'No se pudo enviar.' });
        }
      })
      .catch((err) => {
        resolve({ ok: false, message: 'Error de red: ' + (err.message || err) });
      });
  });
}

window.useAuth = useAuth;
window.getCurrentUser = getCurrentUser;
window.AuthModal = AuthModal;
window.logoutUser = logoutUser;
// ---- Send Speaking via email ----
// Bundles audio recordings into a ZIP file (client-side using JSZip),
// uploads the ZIP to file.io (free anonymous transfer service, 14-day expiry),
// and emails the teacher a download link via Web3Forms.
// Also triggers a local download of the ZIP as a backup for the student.
function sendSpeakingByEmail({ user, examNum, tasks, recordings }) {
  return new Promise(async (resolve) => {
    if (typeof window.JSZip === 'undefined') {
      resolve({ ok: false, message: 'Falta la librería ZIP. Recarga la página.' });
      return;
    }

    // ---- Build ZIP with recordings ----
    const zip = new window.JSZip();
    let totalBytes = 0;
    const recordingDescriptions = [];

    tasks.forEach((task, i) => {
      const rec = recordings[i];
      if (rec && rec.blob) {
        const ext = (rec.mime || '').includes('mp4') ? 'm4a' :
                    (rec.mime || '').includes('ogg') ? 'ogg' :
                    (rec.mime || '').includes('mpeg') ? 'mp3' : 'webm';

        // Build a clean filename from the task title: "Part 1 · Personal information — Q1" → "Part1_Q1"
        const partMatch = task.title.match(/Part\s+(\d+)/i);
        const partNum = partMatch ? `Part${partMatch[1]}` : `Task${i+1}`;
        const qMatch = task.title.match(/Q(\d+)/);
        const subPart = qMatch ? `_Q${qMatch[1]}` :
          task.title.toLowerCase().includes('combined') || task.title.toLowerCase().includes('opinion')
            ? '_Combined' : '';
        const filename = `${partNum}${subPart}.${ext}`;
        zip.file(filename, rec.blob);
        totalBytes += rec.blob.size;
        recordingDescriptions.push(`${filename} · ${Math.round(rec.blob.size/1024)} KB · ${rec.duration}s`);
      }
    });

    if (totalBytes === 0) {
      resolve({ ok: false, message: 'No hay grabaciones para enviar.' });
      return;
    }

    // Add a metadata text file inside the ZIP
    const metadataLines = [];
    metadataLines.push(`Aptis General — Speaking submission`);
    metadataLines.push(`====================================`);
    metadataLines.push(``);
    metadataLines.push(`Student: ${user?.name || '(no name)'}`);
    metadataLines.push(`Email: ${user?.email || '(no email)'}`);
    metadataLines.push(`Exam: Exam ${examNum}`);
    metadataLines.push(`Date: ${new Date().toLocaleString('es-ES')}`);
    metadataLines.push(``);
    metadataLines.push(`Tasks:`);
    tasks.forEach((task, i) => {
      const rec = recordings[i];
      metadataLines.push(``);
      metadataLines.push(`• ${task.title}`);
      metadataLines.push(`  Prompt: ${task.prompt}`);
      metadataLines.push(`  Time limit: ${task.timeLimit}s`);
      if (rec) {
        metadataLines.push(`  Recorded: ${rec.duration}s · ${Math.round(rec.blob.size/1024)} KB`);
      } else {
        metadataLines.push(`  Recorded: (not recorded)`);
      }
    });
    zip.file('README.txt', metadataLines.join('\n'));

    // Generate ZIP blob
    let zipBlob;
    try {
      zipBlob = await zip.generateAsync({ type: 'blob', compression: 'DEFLATE',
        compressionOptions: { level: 6 } });
    } catch (err) {
      resolve({ ok: false, message: 'Error creando ZIP: ' + (err.message || err) });
      return;
    }

    const studentSlug = (user?.name || user?.email || 'alumno')
      .replace(/[^a-zA-Z0-9]/g, '_').slice(0, 30);
    const dateSlug = new Date().toISOString().slice(0, 10);
    const zipFilename = `Speaking_Exam${examNum}_${studentSlug}_${dateSlug}.zip`;

    // ---- Backup: trigger local download for the student ----
    try {
      const downloadUrl = URL.createObjectURL(zipBlob);
      const link = document.createElement('a');
      link.href = downloadUrl;
      link.download = zipFilename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      setTimeout(() => URL.revokeObjectURL(downloadUrl), 1000);
    } catch {}

    // ---- Upload ZIP to file.io ----
    let downloadLink = null;
    let uploadError = null;
    try {
      const fd = new FormData();
      fd.append('file', zipBlob, zipFilename);
      const res = await fetch('https://file.io/?expires=14d&maxDownloads=20', {
        method: 'POST', body: fd,
      });
      const data = await res.json();
      if (data && data.success && data.link) {
        downloadLink = data.link;
      } else {
        uploadError = data.message || 'No se pudo subir el ZIP a file.io.';
      }
    } catch (err) {
      uploadError = err.message || 'Error de red al subir el ZIP.';
    }

    // ---- Send email via Web3Forms with the download link (or fallback message) ----
    const emailLines = [];
    emailLines.push(`Aptis General — Speaking submission`);
    emailLines.push(``);
    emailLines.push(`Alumno: ${user?.name || '(sin nombre)'}`);
    emailLines.push(`Email del alumno: ${user?.email || '(sin email)'}`);
    emailLines.push(`Examen: Exam ${examNum}`);
    emailLines.push(`Fecha: ${new Date().toLocaleString('es-ES')}`);
    emailLines.push(`Archivo ZIP: ${zipFilename}`);
    emailLines.push(`Tamaño: ${Math.round(zipBlob.size/1024)} KB`);
    emailLines.push(``);
    if (downloadLink) {
      emailLines.push(`>>> DESCARGAR AUDIOS <<<`);
      emailLines.push(`Enlace: ${downloadLink}`);
      emailLines.push(`(válido 14 días, hasta 20 descargas)`);
    } else {
      emailLines.push(`⚠ La subida automática falló: ${uploadError || 'desconocido'}`);
      emailLines.push(`El alumno tiene una copia local del ZIP y debería reenviártelo manualmente.`);
    }
    emailLines.push(``);
    emailLines.push(`---------------------------------`);
    emailLines.push(``);
    emailLines.push(`Grabaciones incluidas:`);
    recordingDescriptions.forEach(d => emailLines.push(`  • ${d}`));
    emailLines.push(``);
    emailLines.push(`---------------------------------`);
    emailLines.push(``);
    tasks.forEach((task, i) => {
      const rec = recordings[i];
      emailLines.push(`>> ${task.title}`);
      emailLines.push(`Prompt: ${task.prompt}`);
      emailLines.push(`Time limit: ${task.timeLimit}s`);
      if (rec) emailLines.push(`Recorded: ${rec.duration}s · ${Math.round(rec.blob.size/1024)} KB`);
      else emailLines.push(`Recorded: (sin grabación)`);
      emailLines.push(``);
    });

    const body = emailLines.join('\n');
    const subject = `[Aptis Trainer] Speaking Exam ${examNum} — ${user?.name || user?.email || 'alumno'}`;

    fetch(WEB3FORMS_ENDPOINT, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
      body: JSON.stringify({
        access_key: WEB3FORMS_ACCESS_KEY,
        subject,
        from_name: user?.name || 'Aptis Trainer',
        replyto: user?.email || '',
        name: user?.name || '(sin nombre)',
        email: user?.email || '',
        examen: `Exam ${examNum}`,
        fecha: new Date().toLocaleString('es-ES'),
        zip_filename: zipFilename,
        download_link: downloadLink || '(no link — subida fallida)',
        message: body,
      }),
    })
      .then(res => res.json())
      .then(data => {
        if (data.success) {
          if (downloadLink) {
            resolve({ ok: true,
              message: 'Email enviado con enlace de descarga. El ZIP también se ha guardado en tu ordenador como copia.' });
          } else {
            resolve({ ok: true,
              message: 'Email enviado, pero la subida automática del ZIP falló. El ZIP está en tu carpeta de Descargas — envíalo manualmente al profesor.' });
          }
        } else {
          resolve({ ok: false, message: data.message || 'No se pudo enviar el email.' });
        }
      })
      .catch(err => {
        resolve({ ok: false, message: 'Error de red enviando email: ' + (err.message || err) });
      });
  });
}

window.sendSpeakingByEmail = sendSpeakingByEmail;

// ---- mailto fallback — opens user's email client with everything pre-filled ----
function buildMailtoFallback({ user, examNum, topic, parts, responses }) {
  const lines = [];
  lines.push(`Aptis General — Writing submission`);
  lines.push(``);
  lines.push(`Alumno: ${user?.name || '(sin nombre)'}`);
  lines.push(`Email del alumno: ${user?.email || '(sin email)'}`);
  lines.push(`Examen: Exam ${examNum}`);
  if (topic) lines.push(`Tema: ${topic}`);
  lines.push(`Fecha: ${new Date().toLocaleString('es-ES')}`);
  lines.push(``);
  lines.push(`---------------------------------`);
  lines.push(``);
  parts.forEach((part, pi) => {
    lines.push(`>> ${part.label}`);
    lines.push(``);
    part.items.forEach((it, ii) => {
      const ans = responses[`${pi}-${ii}`] || '(sin respuesta)';
      const wc = (ans || '').trim().split(/\s+/).filter(Boolean).length;
      if (it.prompt) {
        lines.push(`PROMPT: ${it.prompt.replace(/\n/g, ' ').slice(0, 400)}`);
      }
      if (it.minWords && it.maxWords) {
        lines.push(`RECOMENDADO: ${it.minWords}–${it.maxWords} palabras · ESCRITO: ${wc}`);
        if (wc < it.minWords && window.computeWordPenalty) {
          const penalty = window.computeWordPenalty(wc, it.minWords);
          if (penalty > 0) lines.push(`⚠ Por debajo del mínimo recomendado · penalización estimada: −${penalty}%`);
        }
        if (wc > it.maxWords) {
          lines.push(`⚠ Por encima del máximo recomendado.`);
        }
      }
      lines.push(`RESPUESTA:`);
      lines.push(ans);
      lines.push(``);
    });
    lines.push(``);
  });
  const body = lines.join('\n');
  const subject = `[Aptis Trainer] Writing Exam ${examNum} — ${user?.name || user?.email || 'alumno'}`;
  return `mailto:${TEACHER_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
}

window.buildMailtoFallback = buildMailtoFallback;
window.TEACHER_EMAIL = TEACHER_EMAIL;
