<?php
/**
 * Step 4 — upload a video using the stored connection.
 *
 * Browser  ->  this page (?action=prepare)  ->  BentBox (create + sign)  ->  presigned URL
 * Browser  ->  presigned URL (PUT the file)            [direct mode, default]
 *   or
 * Browser  ->  this page (?action=upload) -> BentBox + storage  [proxy mode]
 *
 * Tokens stay server-side; only a short-lived presigned URL is handed to the
 * browser in direct mode (and nothing at all in proxy mode).
 */
require __DIR__ . '/config.php';

// ── AJAX actions (run and exit before any HTML) ──────────────────────────────
$action = $_GET['action'] ?? null;

if ($action === 'disconnect') { bb_clear_connection(); bb_json(['ok' => true]); }

if ($action !== null && !bb_is_connected()) {
    http_response_code(401);
    bb_json(['ok' => false, 'error' => 'not_connected']);
}

// Direct mode: create metadata + sign URL, return only the presigned URL.
if ($action === 'prepare') {
    $m = bb_read_meta(json_decode(file_get_contents('php://input'), true) ?: []);
    if ($e = bb_validate_meta($m)) bb_json(['ok' => false, 'error' => $e]);
    $r = bb_create_and_sign($m);
    if (!$r['ok']) bb_json(['ok' => false, 'error' => $r['error'], 'stage' => $r['stage'] ?? null]);
    bb_json(['ok' => true, 'video_id' => $r['video_id'],
             'upload_url' => $r['upload_url'], 'content_type' => $r['content_type']]);
}

// Proxy mode: receive the file, do everything server-side, return only the id.
if ($action === 'upload') {
    if (!isset($_FILES['file']['tmp_name']) || !is_uploaded_file($_FILES['file']['tmp_name']))
        bb_json(['ok' => false, 'error' => 'No file received.']);
    $m = bb_read_meta($_POST);
    if ($e = bb_validate_meta($m)) bb_json(['ok' => false, 'error' => $e]);
    $r = bb_create_and_sign($m);
    if (!$r['ok']) bb_json(['ok' => false, 'error' => $r['error'], 'stage' => $r['stage'] ?? null]);

    $fh = fopen($_FILES['file']['tmp_name'], 'rb');
    $ch = curl_init($r['upload_url']);
    curl_setopt_array($ch, [
        CURLOPT_PUT => true, CURLOPT_INFILE => $fh,
        CURLOPT_INFILESIZE => filesize($_FILES['file']['tmp_name']),
        CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 0,
        CURLOPT_HTTPHEADER => ['Content-Type: ' . $r['content_type']],
    ]);
    curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch); fclose($fh);
    bb_json(['ok' => ($code >= 200 && $code < 300), 'http' => $code, 'video_id' => $r['video_id']]);
}

// ── Page ─────────────────────────────────────────────────────────────────────
require __DIR__ . '/partials.php';

if (!bb_is_connected()) {
    bb_head('Upload');
    echo '<div class="card"><h2>Not connected</h2>'
       . '<p class="hint">Connect a BentBox account first.</p>'
       . '<a class="btn" href="connect.php">Connect a BentBox account</a></div>';
    bb_foot();
    exit;
}

bb_head('Upload', 'Create metadata, request a presigned URL, and upload — using the stored connection.');
?>
<div class="card">
    <h2>Upload a video</h2>
    <p class="hint">Filename, size and duration are read from the file automatically.</p>

    <div class="drop" id="drop">
        <strong>Choose a video</strong> or drag it here
        <div class="hint" id="fileinfo" style="margin-top:8px;">MP4 / MOV</div>
        <input type="file" id="file" accept="video/*" hidden>
    </div>

    <label>Title</label>
    <input type="text" id="title" maxlength="200" placeholder="Give the video a title">

    <label>Description</label>
    <textarea id="description" maxlength="5000" placeholder="Optional"></textarea>

    <div class="grid2">
        <div><label>Price (USD)</label><input type="number" id="price" min="0" max="9999.99" step="0.01" value="0"></div>
        <div><label>Tags</label><input type="text" id="tags" placeholder="comma, separated"></div>
    </div>
    <label class="chk"><input type="checkbox" id="is_premium"> Premium content</label>
    <label class="chk"><input type="checkbox" id="adult_content" checked> Adult content (18+)</label>

    <label class="chk"><input type="checkbox" id="sole_performer" checked> I am the only performer in this video</label>
    <div id="release_wrap" style="display:none;">
        <label>ProntoID release form ID</label>
        <input type="text" id="release_form_id" placeholder="Form ID covering the other performer(s)">
        <p class="hint" style="margin-top:6px;">Required when the video includes performers other than you.</p>
    </div>
    <label class="chk"><input type="checkbox" id="publish_on_ready" checked> Publish automatically once processing completes</label>

    <button class="btn block" id="go" style="margin-top:22px;">Upload</button>

    <div class="progress" id="progress"><div id="bar"></div></div>

    <ul class="steps" id="tracker" style="margin-top:18px;display:none;">
        <li id="t1">Create video metadata <code>POST /v1/content/video</code></li>
        <li id="t2">Request presigned URL <code>POST /v1/content/upload-url</code></li>
        <li id="t3">Upload the file <code>PUT &lt;presigned url&gt;</code></li>
    </ul>
    <div class="msg" id="msg"></div>
</div>

<p style="text-align:center;"><a class="muted-link" href="index.php">← back to overview</a></p>

<script>
const PROXY = <?= BB_PROXY_UPLOAD ? 'true' : 'false' ?>;
const $ = id => document.getElementById(id);
let meta = { filename:'', filesize:0, duration:0 };

const drop = $('drop'), fileInput = $('file');
drop.addEventListener('click', () => fileInput.click());
['dragover','dragenter'].forEach(e => drop.addEventListener(e, ev => { ev.preventDefault(); drop.classList.add('hl'); }));
['dragleave','drop'].forEach(e => drop.addEventListener(e, ev => { ev.preventDefault(); drop.classList.remove('hl'); }));
drop.addEventListener('drop', ev => { if (ev.dataTransfer.files[0]) setFile(ev.dataTransfer.files[0]); });
fileInput.addEventListener('change', () => { if (fileInput.files[0]) setFile(fileInput.files[0]); });

// Show the release-form field only when the uploader is NOT the sole performer.
$('sole_performer').addEventListener('change', function(){
    $('release_wrap').style.display = this.checked ? 'none' : 'block';
});

function setFile(f){
    fileInput._file = f;
    meta = { filename:f.name, filesize:f.size, duration:0 };
    if (!$('title').value) $('title').value = f.name.replace(/\.[^.]+$/, '');
    const v = document.createElement('video'); v.preload = 'metadata';
    v.onloadedmetadata = () => { URL.revokeObjectURL(v.src); meta.duration = Math.round((v.duration||0)*10)/10; info(); };
    v.onerror = info; v.src = URL.createObjectURL(f); info();
}
function info(){ $('fileinfo').innerHTML = '<strong>'+meta.filename+'</strong> · '
    +(meta.filesize/1048576).toFixed(1)+' MB · '+(meta.duration||'…')+'s'; }
function mark(id, s){ const el=$(id); el.style.color = s==='done' ? 'var(--ok)' : s==='fail' ? 'var(--err)' : ''; }
function showMsg(t, ok){ const m=$('msg'); m.className='msg '+(ok?'ok':'err'); m.textContent=t; }

$('go').addEventListener('click', async function(){
    const f = fileInput._file;
    if (!f) return showMsg('Choose a video file first.', false);
    if (!$('title').value.trim()) return showMsg('Add a title.', false);
    if (!$('sole_performer').checked && !$('release_form_id').value.trim())
        return showMsg('Add a ProntoID release form ID, or check "only performer".', false);

    this.disabled = true;
    $('tracker').style.display = 'block';
    $('progress').style.display = 'block'; $('bar').style.width='0%';
    $('msg').className = 'msg';
    ['t1','t2','t3'].forEach(id => mark(id,''));

    const md = {
        title:$('title').value.trim(), filename:meta.filename, filesize:meta.filesize, duration:meta.duration,
        description:$('description').value.trim(), price:parseFloat($('price').value)||0,
        is_premium:$('is_premium').checked, adult_content:$('adult_content').checked,
        sole_performer:$('sole_performer').checked,
        release_form_id:$('release_form_id').value.trim(),
        publish_on_ready:$('publish_on_ready').checked,
        tags:$('tags').value.split(',').map(t=>t.trim()).filter(Boolean).slice(0,20),
    };

    try {
        if (PROXY) {
            mark('t1','active');
            const r = await postForm('upload.php?action=upload', md, f);
            if (!r.ok) throw new Error(r.error||'upload failed');
            mark('t1','done'); mark('t2','done'); mark('t3','done');
            done(r.video_id);
        } else {
            mark('t1','active');
            const p = await postJson('upload.php?action=prepare', md);
            if (!p.ok) { mark(p.stage==='get_upload_url'?'t2':'t1','fail'); throw new Error(p.error||'prepare failed'); }
            mark('t1','done'); mark('t2','done'); mark('t3','active');
            await put(p.upload_url, f, f.type || p.content_type);
            mark('t3','done'); done(p.video_id);
        }
    } catch(e){ this.disabled=false; showMsg('Upload failed: '+e.message, false); }
});

function done(id){ $('bar').style.width='100%';
    const pub = $('publish_on_ready').checked;
    showMsg('✓ Uploaded (video_id: '+id+'). BentBox will process it'
        + (pub ? ' and publish it once it clears review.' : ' and keep it as a draft for you to publish.'), true); }
function postJson(url, body){ return fetch(url,{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify(body)}).then(r=>r.json()); }
function postForm(url, md, f){ return new Promise((res,rej)=>{
    const fd=new FormData(); Object.entries(md).forEach(([k,v])=>fd.append(k,Array.isArray(v)?v.join(','):v)); fd.append('file',f);
    const x=new XMLHttpRequest(); x.open('POST',url,true);
    x.upload.onprogress=e=>{ if(e.lengthComputable) $('bar').style.width=Math.round(e.loaded/e.total*100)+'%'; };
    x.onload=()=>{ let j={}; try{j=JSON.parse(x.responseText);}catch(_){} res(j); };
    x.onerror=()=>rej(new Error('network error')); x.send(fd); }); }
function put(url, f, ct){ return new Promise((res,rej)=>{
    const x=new XMLHttpRequest(); x.open('PUT',url,true); x.setRequestHeader('Content-Type', ct||'video/mp4');
    x.upload.onprogress=e=>{ if(e.lengthComputable) $('bar').style.width=Math.round(e.loaded/e.total*100)+'%'; };
    x.onload=()=>(x.status>=200&&x.status<300)?res():rej(new Error('storage returned '+x.status+' (if CORS, enable proxy mode)'));
    x.onerror=()=>rej(new Error('network / CORS error')); x.send(f); }); }
</script>
<?php bb_foot();
