<?php
/**
 * upload_photo.php — saves a user's profile photo.
 *
 * Place this in the SAME folder as your settings page (e.g. /customer/),
 * or anywhere under /seven-credit-system/ and point the settings form at it.
 *
 * Expects: POST multipart/form-data with a file field named "photo".
 * Requires: an active session with $_SESSION['user_id'] (user already logged in).
 * Returns:  JSON { ok:true, photo, url } on success, or { ok:false, error } on failure.
 */

session_start();
header('Content-Type: application/json; charset=utf-8');

/* ---- resolve project paths from the web root (works wherever this file lives) ---- */
$ROOT       = rtrim($_SERVER['DOCUMENT_ROOT'], '/').'/seven-credit-system';
$PHOTO_DIR  = $ROOT.'/assets/profile_photos';
$PHOTO_WEB  = '/seven-credit-system/assets/profile_photos';

require_once $ROOT.'/config/database.php';   // provides $pdo

function fail($msg, $code = 400) {
    http_response_code($code);
    echo json_encode(['ok' => false, 'error' => $msg]);
    exit;
}

/* ---- auth ---- */
if (empty($_SESSION['user_id'])) {
    fail('You are not logged in.', 401);
}
$userId = (int) $_SESSION['user_id'];

/* ---- request checks ---- */
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    fail('Invalid request method.');
}
if (!isset($_FILES['photo'])) {
    fail('No file was received. Make sure the file field is named "photo".');
}

$f = $_FILES['photo'];

/* ---- upload error handling ---- */
if ($f['error'] !== UPLOAD_ERR_OK) {
    $map = [
        UPLOAD_ERR_INI_SIZE   => 'The file is larger than the server allows (upload_max_filesize).',
        UPLOAD_ERR_FORM_SIZE  => 'The file is too large.',
        UPLOAD_ERR_PARTIAL    => 'The upload was interrupted, please try again.',
        UPLOAD_ERR_NO_FILE    => 'No file was selected.',
        UPLOAD_ERR_NO_TMP_DIR => 'Server is missing a temp folder.',
        UPLOAD_ERR_CANT_WRITE => 'Server could not write the file to disk.',
    ];
    fail($map[$f['error']] ?? 'Upload failed (error '.$f['error'].').');
}

/* ---- size limit (5 MB) ---- */
if ($f['size'] > 5 * 1024 * 1024) {
    fail('Please choose an image under 5 MB.');
}

/* ---- verify it is really an image, and get the type ---- */
$info = @getimagesize($f['tmp_name']);
if ($info === false) {
    fail('That file is not a valid image.');
}
$allowed = [
    'image/jpeg' => 'jpg',
    'image/png'  => 'png',
    'image/webp' => 'webp',
];
$mime = $info['mime'] ?? '';
if (!isset($allowed[$mime])) {
    fail('Please use a JPG, PNG or WEBP image.');
}
$ext = $allowed[$mime];

/* ---- make sure the destination folder exists and is writable ---- */
if (!is_dir($PHOTO_DIR)) {
    @mkdir($PHOTO_DIR, 0775, true);
}
if (!is_dir($PHOTO_DIR) || !is_writable($PHOTO_DIR)) {
    fail('The photo folder is missing or not writable on the server: '.$PHOTO_WEB, 500);
}

/* ---- build a safe, unique filename ---- */
$filename = 'user_'.$userId.'_'.time().'.'.$ext;
$dest     = $PHOTO_DIR.'/'.$filename;

/* ---- save the file: square-crop with GD if available, else just move it ---- */
$saved = false;
if (function_exists('imagecreatetruecolor')) {
    $saved = save_square($f['tmp_name'], $dest, $mime, 512);
}
if (!$saved) {
    if (!move_uploaded_file($f['tmp_name'], $dest)) {
        fail('Could not save the uploaded file.', 500);
    }
}

/* ---- update the database, remember old photo to clean up ---- */
try {
    $stmt = $pdo->prepare('SELECT profile_photo FROM users WHERE id = ?');
    $stmt->execute([$userId]);
    $old = $stmt->fetchColumn();

    $upd = $pdo->prepare('UPDATE users SET profile_photo = ? WHERE id = ?');
    $upd->execute([$filename, $userId]);
} catch (Throwable $e) {
    @unlink($dest);
    fail('Database error while saving your photo.', 500);
}

/* ---- keep the session in sync (login page reads this) ---- */
$_SESSION['profile_photo'] = $filename;

/* ---- delete the previous photo file ---- */
if ($old && $old !== $filename && is_file($PHOTO_DIR.'/'.$old)) {
    @unlink($PHOTO_DIR.'/'.$old);
}

echo json_encode([
    'ok'    => true,
    'photo' => $filename,
    'url'   => $PHOTO_WEB.'/'.$filename,
]);
exit;


/**
 * Crop the image to a centered square and resize to $size, then save.
 * Returns true on success, false if GD couldn't handle it (caller falls back to move).
 */
function save_square($src, $dest, $mime, $size) {
    switch ($mime) {
        case 'image/jpeg': $img = @imagecreatefromjpeg($src); break;
        case 'image/png':  $img = @imagecreatefrompng($src);  break;
        case 'image/webp': $img = function_exists('imagecreatefromwebp') ? @imagecreatefromwebp($src) : false; break;
        default:           $img = false;
    }
    if (!$img) return false;

    $w = imagesx($img);
    $h = imagesy($img);
    $side = min($w, $h);
    $sx = (int) (($w - $side) / 2);
    $sy = (int) (($h - $side) / 2);

    $out = imagecreatetruecolor($size, $size);
    // preserve transparency for png/webp
    imagealphablending($out, false);
    imagesavealpha($out, true);
    $transparent = imagecolorallocatealpha($out, 0, 0, 0, 127);
    imagefilledrectangle($out, 0, 0, $size, $size, $transparent);

    imagecopyresampled($out, $img, 0, 0, $sx, $sy, $size, $size, $side, $side);

    $ok = false;
    $ext = pathinfo($dest, PATHINFO_EXTENSION);
    if ($ext === 'jpg')  $ok = imagejpeg($out, $dest, 88);
    elseif ($ext === 'png')  $ok = imagepng($out, $dest, 6);
    elseif ($ext === 'webp' && function_exists('imagewebp')) $ok = imagewebp($out, $dest, 88);

    imagedestroy($img);
    imagedestroy($out);
    return $ok;
}