<?php

date_default_timezone_set('Europe/Berlin');

if (!function_exists('str_starts_with')) {
  function str_starts_with($h,$n){ return $n!=='' && substr($h,0,strlen($n))===$n; }
}
function h($s){ return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }

$uploadDir = __DIR__ . '/uploads';
$jsonFile  = __DIR__ . '/data.json';
$maxSizeMB = 200; // ggf. anpassen (Videos!)
$allowedImageExt = ['jpg','jpeg','png','gif','webp','heic','heif'];
$allowedVideoExt = ['mp4','mov','webm'];

if (!is_dir($uploadDir)) @mkdir($uploadDir, 0755, true);
if (!file_exists($jsonFile)) @file_put_contents($jsonFile, json_encode([]));

$items = [];
if (file_exists($jsonFile)) {
  $raw = @file_get_contents($jsonFile);
  $items = json_decode($raw, true);
  if (!is_array($items)) $items = [];
}

$errors = [];
$notice = null;

function save_cropped_file($field, $uploadDir){
  if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) return [null, 'Cropped-Upload fehlgeschlagen.'];
  $safe = uniqid('m_', true) . '.jpg';
  $dest = $uploadDir . '/' . $safe;
  if (!move_uploaded_file($_FILES[$field]['tmp_name'], $dest)) return [null, 'Cropped-Datei konnte nicht gespeichert werden.'];
  return ['uploads/'.$safe, null];
}
function save_image_or_convert($fileArr, $uploadDir){
  $f = $fileArr;
  $ext = strtolower(pathinfo($f['name'] ?? 'upload', PATHINFO_EXTENSION));
  $mime = '';
  if (class_exists('finfo')) { $fi = new finfo(FILEINFO_MIME_TYPE); $mime = $fi->file($f['tmp_name']) ?: ''; }
  $isHeic = in_array($ext, ['heic','heif'], true) || stripos($mime,'heic')!==false || stripos($mime,'heif')!==false;

  if ($isHeic) {
    if (class_exists('Imagick')) {
      try {
        $img = new Imagick($f['tmp_name']);
        $img->setImageFormat('jpeg');
        $safe = uniqid('m_', true) . '.jpg';
        $dest = $uploadDir . '/' . $safe;
        if (!$img->writeImage($dest)) throw new Exception('Imagick writeImage fehlgeschlagen');
        return ['uploads/'.$safe, null];
      } catch (Throwable $e) {
        return [null, 'HEIC-Konvertierung fehlgeschlagen: '.$e->getMessage()];
      }
    } else {
      return [null, 'HEIC nicht unterstützt. Bitte JPG/PNG/WebP verwenden.'];
    }
  } else {
    $safe = uniqid('m_', true) . '.' . $ext;
    $dest = $uploadDir . '/' . $safe;
    if (!move_uploaded_file($f['tmp_name'], $dest)) return [null, 'Bild konnte nicht gespeichert werden.'];
    if (in_array($ext, ['jpg','jpeg'], true) && function_exists('exif_read_data') && function_exists('imagecreatefromjpeg')) {
      try{
        $exif = @exif_read_data($dest);
        if (!empty($exif['Orientation'])) {
          $src = imagecreatefromjpeg($dest);
          switch ((int)$exif['Orientation']) {
            case 3: $src = imagerotate($src, 180, 0); break;
            case 6: $src = imagerotate($src, -90, 0); break;
            case 8: $src = imagerotate($src, 90, 0); break;
          }
          imagejpeg($src, $dest, 90);
          imagedestroy($src);
        }
      }catch(Throwable $e){}
    }
    return ['uploads/'.$safe, null];
  }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $caption = trim($_POST['caption'] ?? '');

  if (isset($_FILES['cropped_file']) && $_FILES['cropped_file']['error'] === UPLOAD_ERR_OK) {
    if ($_FILES['cropped_file']['size'] > $maxSizeMB*1024*1024) {
      $errors[] = 'Bild (cropped) zu groß. Max '.$maxSizeMB.' MB.';
    } else {
      [$imgPath, $err] = save_cropped_file('cropped_file', $uploadDir);
      if ($err) $errors[] = $err;
      if (!$errors) {
        $items[] = ['file'=>$imgPath,'caption'=>$caption,'time'=>time(),'type'=>'image'];
        if (@file_put_contents($jsonFile, json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))===false) {
          $errors[]='Konnte data.json nicht schreiben.';
        } else {
 
  $last = $items[array_key_last($items)];
  send_push_new_post($last);

  header('Location: '.$_SERVER['PHP_SELF'].'?ok=1'); exit;
}
      }
    }

  } elseif (isset($_FILES['media']) && $_FILES['media']['error'] === UPLOAD_ERR_OK) {
    $f = $_FILES['media'];
    if ($f['size'] > $maxSizeMB*1024*1024) {
      $errors[] = 'Datei zu groß. Max '.$maxSizeMB.' MB.';
    } else {
      $ext = strtolower(pathinfo($f['name'] ?? 'upload', PATHINFO_EXTENSION));
      $mime = '';
      if (class_exists('finfo')) { $fi = new finfo(FILEINFO_MIME_TYPE); $mime = $fi->file($f['tmp_name']) ?: ''; }
      $isVideo = in_array($ext, $allowedVideoExt, true) || ($mime && str_starts_with($mime,'video/'));
      $isImage = in_array($ext, $allowedImageExt, true) || ($mime && str_starts_with($mime,'image/'));

      if ($isVideo) {
         
        $safe = uniqid('m_', true) . '.' . $ext;
        $dest = $uploadDir . '/' . $safe;
        if (!move_uploaded_file($f['tmp_name'], $dest)) {
          $errors[] = 'Video konnte nicht gespeichert werden.';
        } else {
          $videoPath = 'uploads/' . basename($dest);
          $posterPath = null;

          if (isset($_FILES['poster_cropped']) && $_FILES['poster_cropped']['error'] === UPLOAD_ERR_OK) {
            if ($_FILES['poster_cropped']['size'] > $maxSizeMB*1024*1024) {
              $errors[] = 'Poster (cropped) zu groß.';
            } else {
              [$p, $err] = save_cropped_file('poster_cropped', $uploadDir);
              if ($err) $errors[] = $err; else $posterPath = $p;
            }
          }
 
          if (!$posterPath && isset($_FILES['poster']) && $_FILES['poster']['error'] === UPLOAD_ERR_OK) {
            if ($_FILES['poster']['size'] > $maxSizeMB*1024*1024) {
              $errors[] = 'Poster zu groß.';
            } else {
              [$p, $err] = save_image_or_convert($_FILES['poster'], $uploadDir);
              if ($err) $errors[] = $err; else $posterPath = $p;
            }
          }

          if (!$errors) {
            $items[] = [
              'file'    => $videoPath,
              'poster'  => $posterPath ?: null, 
              'caption' => $caption,
              'time'    => time(),
              'type'    => 'video'
            ];
            if (@file_put_contents($jsonFile, json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))===false) {
              $errors[]='Konnte data.json nicht schreiben.';
            } else {
 
  $last = $items[array_key_last($items)];
  send_push_new_post($last);

  header('Location: '.$_SERVER['PHP_SELF'].'?ok=1'); exit;
}
          }
        }

      } elseif ($isImage) {
        // Bild ohne Crop (Fallback)
        [$imgPath, $err] = save_image_or_convert($f, $uploadDir);
        if ($err) $errors[] = $err;
        if (!$errors) {
          $items[] = ['file'=>$imgPath,'caption'=>$caption,'time'=>time(),'type'=>'image'];
          if (@file_put_contents($jsonFile, json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))===false) {
            $errors[]='Konnte data.json nicht schreiben.';
          } else {
  
  $last = $items[array_key_last($items)];
  send_push_new_post($last);

  header('Location: '.$_SERVER['PHP_SELF'].'?ok=1'); exit;
}
        }
      } else {
        $errors[] = 'Nicht unterstützter Dateityp.';
      }
    }
  } else {
    $errors[] = 'Bitte eine Datei auswählen.';
  }
}

if (isset($_GET['ok'])) $notice = 'Upload erfolgreich!';

$preview = array_slice(array_reverse($items), 0, 12);
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="upload.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="upload.ico" /><!--Hier mit eigenem Icon ersetzen-->
<title>OYS Upload</title><!--Hier mit eigenem Text ersetzen-->

<link rel="stylesheet" href="assets/cropper.min.css">
<script src="assets/cropper.min.js"></script>

<style>
:root{--gap:16px;--radius:14px;--shadow:0 6px 20px rgba(0,0,0,.08)}
*{box-sizing:border-box}
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;margin:0;background:#f7f7f8;color:#111}

.header{position:sticky;top:0;background:#fff;border-bottom:1px solid #eee;padding:12px 16px;display:flex;align-items:center;justify-content:space-between;z-index:10}
.header h1{margin:0;font-size:24px}
.header a{display:inline-flex;align-items:center;gap:8px;text-decoration:none;background:#111;color:#fff;padding:10px 14px;border-radius:12px;border:1px solid #2a2a34}

.container{max-width:900px;margin:24px auto;padding:0 16px}
.panel{background:#fff;border:1px solid #eee;border-radius:14px;box-shadow:var(--shadow);padding:16px;margin-bottom:16px}

.btn{display:inline-flex;align-items:center;gap:8px;padding:12px 16px;border-radius:12px;background:#111;color:#fff;border:1px solid #2a2a34;font-weight:700;cursor:pointer;text-decoration:none}
.btn:hover{background:#18181f}
.btn:active{transform:translateY(1px)}
.btn.ghost{background:transparent;color:#111;border:1px solid #ccc}

.filepicker{position:relative;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.filepicker .file-input{position:absolute;inset:0;opacity:0;cursor:pointer}
.filepicker .file-name{font-size:.95rem;color:#444}

input[type=file],textarea,select{width:100%;padding:10px 12px;border:1px solid #ddd;border-radius:10px;font:inherit;background:#fafafa}
select{width:auto}
textarea{min-height:84px}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--gap);margin-top:24px}
.card{background:#fff;border:1px solid #eee;border-radius:14px;box-shadow:var(--shadow);overflow:hidden}
.card img,.card video{width:100%;display:block;aspect-ratio:4/5;object-fit:cover;background:#000}
.card figcaption{padding:10px 12px;border-top:1px solid #f0f0f0;white-space:pre-wrap}
.meta{padding:10px 12px;color:#666;font-size:.85rem;border-top:1px dashed #eee}

#img-crop-area,#poster-crop-area{display:none;align-items:flex-start;gap:16px;flex-wrap:wrap}
#img-cropper-wrapper,#poster-cropper-wrapper{max-width:100%;width:100%}
#img-crop-image,#poster-crop-image{max-width:100%;width:100%;background:#000;border-radius:12px}

.notice{background:#e6fbef;border:1px solid #b8f1cf;color:#0a7a3e}
.errors{background:#ffecec;border:1px solid #ffc9c9;color:#b10000}
.hidden{display:none}
.hint{color:#666;font-size:.9rem}
</style>
</head>
<body>
  <div class="header">
    <h1>OwnYourSocial Upload</h1><!--Hier mit eigenem Text ersetzen-->
    <a class="btn" href="index.php">Zum Feed</a>
  </div>

  <div class="container">

    <?php if ($notice): ?>
      <div class="panel notice">✅ Upload erfolgreich!</div>
    <?php endif; ?>
    <?php if ($errors): ?>
      <div class="panel errors">
        <strong>Fehler:</strong>
        <ul style="margin:8px 0 0 18px;padding:0">
          <?php foreach($errors as $e): ?><li><?=h($e)?></li><?php endforeach; ?>
        </ul>
      </div>
    <?php endif; ?>

    <form id="upload-form" method="post" enctype="multipart/form-data" class="panel">
      <!-- Hauptdatei -->
      <div style="font-weight:700;margin-bottom:6px">Hauptdatei (Bild oder Video)</div>
      <div class="filepicker" aria-label="Hauptdatei wählen">
        <button type="button" class="btn file-trigger">📁 Datei auswählen</button>
        <input id="file-input" class="file-input" type="file" accept="image/*,video/*">
        <span id="file-name" class="file-name">Keine Datei gewählt</span>
      </div>

      <div id="img-crop-area" class="panel" style="margin-top:12px">
        <div class="hint" style="margin-bottom:8px">Bild zuschneiden (optional): Seitenverhältnis wählen, dann zoomen/rotieren/flippen.</div>
        <div class="controls">
          <select id="img-aspect" title="Seitenverhältnis">
            <option value="0.8">4:5 (Instagram)</option>
            <option value="free">Frei</option>
            <option value="1">1:1</option>
            <option value="0.5625">9:16</option>
            <option value="1.7777777778">16:9</option>
          </select>
          <button type="button" class="btn ghost" id="img-zoom-in">Zoom +</button>
          <button type="button" class="btn ghost" id="img-zoom-out">Zoom −</button>
          <button type="button" class="btn ghost" id="img-rotate-left">↺ 90°</button>
          <button type="button" class="btn ghost" id="img-rotate-right">↻ 90°</button>
          <button type="button" class="btn ghost" id="img-flip-h">Flip ↔</button>
          <button type="button" class="btn ghost" id="img-flip-v">Flip ↕</button>
          <button type="button" class="btn" id="img-reset">Reset</button>
        </div>
        <div id="img-cropper-wrapper">
          <img id="img-crop-image" alt="Bild-Crop">
        </div>
      </div>

      <!-- Poster für Video -->
      <div id="poster-section" class="panel hidden">
        <div style="font-weight:700;margin-bottom:6px">Optionales Vorschaubild (Poster) für Video</div>
        <div class="filepicker" aria-label="Posterdatei wählen">
          <button type="button" class="btn file-trigger">🖼️ Poster auswählen</button>
          <input id="poster-input" class="file-input" type="file" accept="image/*">
          <span id="poster-file-name" class="file-name">Optional – kein Poster gewählt</span>
        </div>

        <div id="poster-crop-area" class="panel" style="margin-top:12px">
          <div class="controls">
            <select id="poster-aspect" title="Seitenverhältnis">
              <option value="0.8">4:5 (Instagram)</option>
            <option value="free">Frei</option>
            <option value="1">1:1</option>
            <option value="0.5625">9:16</option>
            <option value="1.7777777778">16:9</option>
            </select>
            <button type="button" class="btn ghost" id="poster-zoom-in">Zoom +</button>
            <button type="button" class="btn ghost" id="poster-zoom-out">Zoom −</button>
            <button type="button" class="btn ghost" id="poster-rotate-left">↺ 90°</button>
            <button type="button" class="btn ghost" id="poster-rotate-right">↻ 90°</button>
            <button type="button" class="btn ghost" id="poster-flip-h">Flip ↔</button>
            <button type="button" class="btn ghost" id="poster-flip-v">Flip ↕</button>
            <button type="button" class="btn" id="poster-reset">Reset</button>
          </div>
          <div id="poster-cropper-wrapper">
            <img id="poster-crop-image" alt="Poster-Crop">
          </div>
        </div>
        <div class="hint">Tipp: 4:5 wirkt in der Galerie besonders gut.</div>
      </div>

      <!-- Caption -->
      <div style="font-weight:700;margin:12px 0 6px">Caption (optional)</div>
      <textarea name="caption" rows="3" placeholder="Schreib eine Bildunterschrift …"></textarea>

      <!-- Hidden real inputs -->
      <input type="file" name="media" id="media-fallback" style="display:none">
      <input type="file" name="cropped_file" id="cropped-file" style="display:none">
      <input type="file" name="poster" id="poster-fallback" style="display:none">
      <input type="file" name="poster_cropped" id="poster-cropped-file" style="display:none">

      <div class="controls" style="margin-top:8px">
        <button type="button" class="btn" id="submit-btn">⬆️ Speichern & Hochladen</button>
      </div>

      <div class="hint">Videos groß? Prüfe Server-Limits (upload_max_filesize, post_max_size). Aktuell max. <?=$maxSizeMB?> MB.</div>
    </form>

    <h2 style="margin:28px 0 8px">Letzte Uploads</h2>
    <div class="grid">
      <?php foreach ($preview as $it): ?>
        <article class="card">
          <figure>
            <?php if (($it['type'] ?? '') === 'video'): ?>
              <video controls playsinline preload="none"
                <?php if (!empty($it['poster'])): ?>poster="<?=h($it['poster'])?>"<?php endif; ?>
                src="<?=h($it['file'])?>"></video>
            <?php else: ?>
              <img loading="lazy" src="<?=h($it['file'])?>" alt="">
            <?php endif; ?>
            <?php if (!empty($it['caption'])): ?>
              <figcaption><?=nl2br(h($it['caption']))?></figcaption>
            <?php endif; ?>
          </figure>
          <div class="meta"><?=date('d.m.Y H:i', (int)($it['time'] ?? time()))?></div>
        </article>
      <?php endforeach; ?>
    </div>

  </div>

<script>

let imgCropper=null, posterCropper=null;
let imgScaleX=1,imgScaleY=1, posterScaleX=1,posterScaleY=1;

const fileInput = document.getElementById('file-input');
const fileNameEl = document.getElementById('file-name');
const mediaFallback = document.getElementById('media-fallback');
const croppedFile = document.getElementById('cropped-file');

const posterSection = document.getElementById('poster-section');
const posterInput = document.getElementById('poster-input');
const posterFileNameEl = document.getElementById('poster-file-name');
const posterFallback = document.getElementById('poster-fallback');
const posterCroppedFile = document.getElementById('poster-cropped-file');

const imgCropArea = document.getElementById('img-crop-area');
const imgCropImg = document.getElementById('img-crop-image');
const imgAspect = document.getElementById('img-aspect');

const posterCropArea = document.getElementById('poster-crop-area');
const posterCropImg = document.getElementById('poster-crop-image');
const posterAspect = document.getElementById('poster-aspect');

document.querySelectorAll('.filepicker').forEach(fp=>{
  const trigger = fp.querySelector('.file-trigger');
  const input = fp.querySelector('.file-input');
  const nameEl = fp.querySelector('.file-name');
  trigger?.addEventListener('click', ()=> input?.click());
  input?.addEventListener('change', ()=>{
    const f = input.files?.[0];
    const def = input.id==='poster-input' ? 'Optional – kein Poster gewählt' : 'Keine Datei gewählt';
    nameEl && (nameEl.textContent = f ? f.name : def);
  });
});

function isVideo(file){ return file && file.type.startsWith('video/'); }
function isHeic(file){
  const n=(file?.name||'').toLowerCase();
  return n.endsWith('.heic')||n.endsWith('.heif')||(file?.type||'').includes('heic')||(file?.type||'').includes('heif');
}
function destroyCropper(which){
  if (which==='img' && imgCropper){ imgCropper.destroy(); imgCropper=null; imgScaleX=imgScaleY=1; }
  if (which==='poster' && posterCropper){ posterCropper.destroy(); posterCropper=null; posterScaleX=posterScaleY=1; }
}

fileInput.addEventListener('change', ()=>{
  destroyCropper('img'); destroyCropper('poster');
  imgCropArea.style.display='none';
  posterSection.classList.add('hidden');
  posterCropArea.style.display='none';
  mediaFallback.files = fileInput.files; // Spiegeln

  const f=fileInput.files[0];
  fileNameEl.textContent = f ? f.name : 'Keine Datei gewählt';
  if(!f) return;

  if (isVideo(f)) {
     
    posterSection.classList.remove('hidden');
  } else if (!isHeic(f)) {
     
    const r=new FileReader();
    r.onload=e=>{
      imgCropImg.src=e.target.result;
      imgCropArea.style.display='block';
      imgCropper = new Cropper(imgCropImg,{viewMode:1,movable:true,zoomable:true,rotatable:true,scalable:true,autoCropArea:1,background:false});
    };
    r.readAsDataURL(f);
  }  
});

document.getElementById('img-zoom-in').onclick = ()=> imgCropper && imgCropper.zoom(0.1);
document.getElementById('img-zoom-out').onclick= ()=> imgCropper && imgCropper.zoom(-0.1);
document.getElementById('img-rotate-left').onclick = ()=> imgCropper && imgCropper.rotate(-90);
document.getElementById('img-rotate-right').onclick= ()=> imgCropper && imgCropper.rotate(90);
document.getElementById('img-flip-h').onclick = ()=> { if(!imgCropper) return; imgScaleX*=-1; imgCropper.scaleX(imgScaleX); };
document.getElementById('img-flip-v').onclick = ()=> { if(!imgCropper) return; imgScaleY*=-1; imgCropper.scaleY(imgScaleY); };
document.getElementById('img-reset').onclick= ()=> { if(!imgCropper) return; imgScaleX=imgScaleY=1; imgCropper.reset(); };
imgAspect.addEventListener('change', ()=> { if(!imgCropper) return; const v=imgAspect.value; imgCropper.setAspectRatio(v==='free'?NaN:parseFloat(v)); });

posterInput.addEventListener('change', ()=>{
  destroyCropper('poster');
  posterCropArea.style.display='none';
  const f=posterInput.files[0];
  posterFileNameEl.textContent = f ? f.name : 'Optional – kein Poster gewählt';
  posterFallback.files = posterInput.files; 
  if(!f) return;

  if (isHeic(f)) { return; }  
  const r=new FileReader();
  r.onload=e=>{
    posterCropImg.src=e.target.result;
    posterCropArea.style.display='block';
    posterCropper = new Cropper(posterCropImg,{viewMode:1,movable:true,zoomable:true,rotatable:true,scalable:true,autoCropArea:1,background:false});
  };
  r.readAsDataURL(f);
});

document.getElementById('submit-btn').addEventListener('click', async ()=>{
  const f=fileInput.files[0];
  if(!f){ alert('Bitte eine Datei wählen.'); return; }

  if (!isVideo(f) && imgCropper){
    const durl=imgCropper.getCroppedCanvas({maxWidth:3000,maxHeight:3000}).toDataURL('image/jpeg',0.9);
    const blob=await (await fetch(durl)).blob();
    const file=new File([blob],'cropped.jpg',{type:'image/jpeg'});
    const dt=new DataTransfer(); dt.items.add(file); croppedFile.files=dt.files;
  } else {
     
    if (!mediaFallback.files.length) mediaFallback.files = fileInput.files;
  }

  if (posterInput.files.length && posterCropper){
    const durl=posterCropper.getCroppedCanvas({maxWidth:3000,maxHeight:3000}).toDataURL('image/jpeg',0.9);
    const blob=await (await fetch(durl)).blob();
    const file=new File([blob],'poster.jpg',{type:'image/jpeg'});
    const dt=new DataTransfer(); dt.items.add(file); posterCroppedFile.files=dt.files;
  } else {
     
    if (posterInput.files.length && !posterFallback.files.length) posterFallback.files = posterInput.files;
  }

  document.getElementById('upload-form').submit();
});
</script>

</body>
</html>