{% extends "base.htm" %}

{% block title %}NanoShare - Upload{% endblock %}

{% block meta %}
  <meta name="description" content="NanoShare is a lightweight self-hosted file sharing service built on Python Quart.">
  <meta name="keywords" content="NanoShare, file sharing, self-hosted, Python Quart, open source">
  <meta name="robots" content="index, follow" />
{% endblock %}

{% block content %}
<main class="file-upload">
  <section class="card" aria-labelledby="upload-title">
    <h1 id="upload-title" class="page-title">Upload</h1>
    <p class="subtle">Drop a file, paste from clipboard, or paste text. Configure expiry & add a note before uploading.</p>

    <!-- Dropzone -->
    <div id="dropzone" class="dropzone" tabindex="0" role="button" aria-label="Choose a file or drop it here">
      <input type="file" id="fileInput" />
      <div class="dz-icon">📤</div>
      <div class="dz-title">Choose a file or drag it here</div>
      <div class="dz-hint">Tip: Paste an image/file or text from clipboard (⌘/Ctrl + V)</div>
      <div id="fileMeta" class="dz-hint" style="margin-top:8px;display:none;"></div>
    </div>

    <!-- Or paste text -->
    <p class="subtle" style="text-align:center;margin:14px 0 0;">— or paste text below —</p>
    <div class="field">
      <label for="paste" class="label">Text</label>
      <textarea id="paste" class="textarea" placeholder="Paste text…"></textarea>
    </div>

    <!-- Expiration & Note -->
    <div class="row">
      <div class="field">
        <label for="expiresMode" class="label">Expiration</label>
        <select id="expiresMode" class="select">
          <option value="1h">1 hour</option>
          <option value="24h">24 hours</option>
          <option value="7d" selected>7 days</option>
          <option value="30d">30 days</option>
          <option value="never">Never</option>
          <option value="custom">Custom date…</option>
        </select>
      </div>
      <div class="field" id="customWrap" style="display:none;">
        <label for="customExpire" class="label">Custom expiration</label>
        <input type="datetime-local" id="customExpire" class="datetime" />
      </div>
    </div>

    <div class="field">
      <label for="note" class="label">Note (optional)</label>
      <input id="note" class="input" type="text" placeholder="For Joe at ExampleCo" />
    </div>

    <!-- Actions -->
    <div class="actions">
      <button id="clearBtn" class="btn btn-ghost" type="button">🧹 Clear</button>
      <div style="flex:1"></div>
      <button id="uploadBtn" class="btn" disabled>⬆️ Upload</button>
    </div>

    <!-- Progress + Preview -->
    <div class="progress" aria-hidden="true"><div class="bar" id="bar"></div></div>
    <div id="preview" class="preview"></div>
  </section>
</main>

<!-- Toast -->
<div id="toast" class="toast" role="status" aria-live="polite">✅ Uploaded successfully!</div>

<script>
/* ====== Elements ====== */
const dz = document.getElementById('dropzone');
const fileInput = document.getElementById('fileInput');
const pasteEl = document.getElementById('paste');
const uploadBtn = document.getElementById('uploadBtn');
const clearBtn = document.getElementById('clearBtn');
const preview = document.getElementById('preview');
const fileMeta = document.getElementById('fileMeta');
const expiresMode = document.getElementById('expiresMode');
const customWrap = document.getElementById('customWrap');
const customExpire = document.getElementById('customExpire');
const bar = document.getElementById('bar');
const toast = document.getElementById('toast');

let file=null, text='';

/* ====== Helpers ====== */
const mimeToExt = m => {
  // --- Image types ---
  if (m === 'image/png') return 'png';
  if (m === 'image/jpeg') return 'jpg';
  if (m === 'image/gif') return 'gif';
  if (m === 'image/webp') return 'webp';
  if (m === 'application/pdf') return 'pdf';

  // --- Video MIME types ---
  if (m === 'video/mp4') return 'mp4';
  if (m === 'video/webm') return 'webm';
  if (m === 'video/ogg') return 'ogv';
  if (m === 'video/quicktime') return 'mov';
  if (m === 'video/x-matroska' || m === 'video/mkv') return 'mkv';
  if (m === 'video/x-msvideo') return 'avi';
  if (m === 'video/x-ms-wmv') return 'wmv';
  if (m === 'video/mpeg') return 'mpeg';

  // --- Audio MIME types ---
  if (m === 'audio/mpeg') return 'mp3'
  if (m === 'audio/mp3') return 'mp3';
  if (m === 'audio/aac') return 'aac';
  if (m === 'audio/mp4' || m === 'audio/x-m4a') return 'm4a';
  if (m === 'audio/ogg') return 'ogg';
  if (m === 'audio/opus') return 'opus';
  if (m === 'audio/webm') return 'weba';
  if (m === 'audio/wav' || m === 'audio/x-wav') return 'wav';
  if (m === 'audio/flac') return 'flac';
  if (m === 'audio/x-ms-wma') return 'wma';

  // --- Text fallback ---
  if (m && m.startsWith('text/')) return 'txt';

  return 'bin'; // default / unknown
};

const isoStamp = () => new Date().toISOString().replace(/[:]/g,'').replace(/\.\d+Z$/,'Z');
const fmtKB = b => `${Math.max(1, Math.round((b||0)/1024)).toLocaleString()} KB`;

function updateUI(){
  uploadBtn.disabled = !(file || (text && text.trim()));
  pasteEl.disabled = !!file;
  fileInput.disabled = !!(text && text.trim());
  // Preview + meta
  if(file){
    fileMeta.style.display='block';
    fileMeta.innerHTML = `Selected: <span class="badge">${file.name}</span> · <span class="badge">${fmtKB(file.size)}</span>`;
  }else{
    fileMeta.style.display='none';
    fileMeta.textContent='';
  }
  preview.textContent = '';
}

function setFileFromBlob(blob){
  const ext=mimeToExt(blob.type||'');
  const name=`pasted-${isoStamp()}.${ext}`;
  file=new File([blob],name,{type:blob.type||'application/octet-stream'});
  text=''; pasteEl.value='';
  updateUI();
}

function clearAll(){
  file=null; text=''; pasteEl.value='';
  fileInput.value='';
  bar.style.width='0%';
  preview.textContent='';
  updateUI();
}

/* ====== Dropzone interactions ====== */
dz.addEventListener('click',()=>!fileInput.disabled && fileInput.click());
dz.addEventListener('keydown',e=>{
  if((e.key==='Enter'||e.key===' ') && !fileInput.disabled){ e.preventDefault(); fileInput.click(); }
});
dz.addEventListener('dragover',e=>{e.preventDefault(); dz.classList.add('drag');});
['dragleave','dragend'].forEach(ev=>dz.addEventListener(ev,()=>dz.classList.remove('drag')));
dz.addEventListener('drop',e=>{
  e.preventDefault(); dz.classList.remove('drag');
  if(fileInput.disabled)return;
  const f=e.dataTransfer.files&&e.dataTransfer.files[0];
  if(f){file=f;text='';pasteEl.value='';updateUI();}
});
fileInput.addEventListener('change',e=>{
  const f=e.target.files[0]; if(f){file=f;text='';pasteEl.value='';updateUI();}
});

/* ====== Clipboard handling ====== */
window.addEventListener('paste', e => {
  if (e.target === pasteEl) return; // 👈 let browser handle it

  if (file || (text && text.trim())) return;

  const items = e.clipboardData?.items || [];
  const fItem = [...items].find(it => it.kind === 'file');

  if (fItem) {
    e.preventDefault();
    const blob = fItem.getAsFile();
    if (blob) setFileFromBlob(blob);
    return;
  }

  const pasted = e.clipboardData?.getData('text') || '';
  if (pasted) {
    pasteEl.value = pasted;
    text = pasted;
    updateUI();
  }
});

pasteEl.addEventListener('input',e => { text = e.target.value; updateUI(); });

/* ====== Expiration handling ====== */
expiresMode.addEventListener('change',()=>{
  if(expiresMode.value==='custom'){
    customWrap.style.display='block';
    customExpire.value = new Date(Date.now()+3600*1000).toISOString().slice(0,16);
  } else {
    customWrap.style.display='none';
  }
});

/* ====== Clear ====== */
clearBtn.addEventListener('click',clearAll);

/* ====== Upload ====== */
uploadBtn.addEventListener('click',async()=>{
  const note=document.getElementById('note').value;
  let expiresValue=expiresMode.value;
  if(expiresValue==='custom' && customExpire.value){
    const dt=new Date(customExpire.value);
    if(isNaN(+dt)){ preview.textContent='❌ Invalid custom date'; return; }
    expiresValue=dt.toISOString();
  }

  const form=new FormData();
  if(file) form.append('file',file,file.name);
  if(text && text.trim()) form.append('text',text);
  form.append('expires',expiresValue);
  form.append('note',note);

  uploadBtn.disabled=true;
  preview.textContent='Uploading…';
  bar.style.width='0%';

  try{
    // Use fetch with progress via XHR fallback for better granularity
    const endpoint = '/api/upload';
    if('upload' in new XMLHttpRequest()){
      await new Promise((resolve, reject)=>{
        const xhr=new XMLHttpRequest();
        xhr.open('POST', endpoint);
        xhr.upload.onprogress = (e)=>{
          if(e.lengthComputable){
            const pct = Math.round((e.loaded/e.total)*100);
            bar.style.width = pct + '%';
          }
        };
        xhr.onload = ()=> xhr.status>=200 && xhr.status<300 ? resolve() : reject(new Error('Upload failed'));
        xhr.onerror = ()=> reject(new Error('Network error'));
        xhr.send(form);
      });
    } else {
      const res=await fetch(endpoint,{method:'POST',body:form});
      if(!res.ok) throw new Error('Upload failed');
      bar.style.width='100%';
    }

    preview.textContent = '✅ Uploaded successfully!';
    showToast('✅ Uploaded successfully!');
    setTimeout(()=>{ window.location.href = '{{ url_for("side_main.files_list") }}'; }, 800);
  }catch(err){
    preview.textContent = '❌ ' + (err?.message || 'Upload error');
    showToast('❌ Upload failed', true);
    bar.style.width='0%';
  }finally{
    uploadBtn.disabled=false;
  }
});

function showToast(msg, danger=false){
  toast.textContent = msg;
  toast.style.borderColor = danger ? 'color-mix(in srgb, var(--danger) 50%, var(--border))' : 'var(--border)';
  toast.classList.add('show');
  setTimeout(()=> toast.classList.remove('show'), 1800);
}

/* ====== Init ====== */
updateUI();
</script>
{% endblock %}
