<?php
namespace Thirty\controllers;

class ProfileController {
    private static function processAvatar($srcPath, $mime, $destPath, $size = 256) {
        // Load source
        switch ($mime) {
            case 'image/jpeg': $src = imagecreatefromjpeg($srcPath); break;
            case 'image/png':  $src = imagecreatefrompng($srcPath); break;
            case 'image/webp': $src = function_exists('imagecreatefromwebp') ? imagecreatefromwebp($srcPath) : null; break;
            case 'image/gif':  $src = imagecreatefromgif($srcPath); break;
            default: $src = null; break;
        }
        if (!$src) return false;
        $w = imagesx($src); $h = imagesy($src);
        // center-crop square
        $side = min($w, $h);
        $sx = (int)(($w - $side) / 2);
        $sy = (int)(($h - $side) / 2);
        $dst = imagecreatetruecolor($size, $size);
        // preserve transparency
        if (in_array($mime, ['image/png','image/webp','image/gif'])) {
            imagealphablending($dst, false);
            imagesavealpha($dst, true);
            $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
            imagefilledrectangle($dst, 0, 0, $size, $size, $transparent);
        }
        imagecopyresampled($dst, $src, 0, 0, $sx, $sy, $size, $size, $side, $side);
        $ok = false;
        switch ($mime) {
            case 'image/jpeg': $ok = imagejpeg($dst, $destPath, 90); break;
            case 'image/png':  $ok = imagepng($dst, $destPath, 6); break;
            case 'image/webp': $ok = function_exists('imagewebp') ? imagewebp($dst, $destPath, 90) : imagepng($dst, $destPath, 6); break;
            case 'image/gif':  $ok = imagegif($dst, $destPath); break;
        }
        imagedestroy($src); imagedestroy($dst);
        return $ok;
    }

    public static function show() {
        require_auth();
        global $DB;
        
        $me = user();
        $nick = trim($_GET['nick'] ?? '');
        $user_id = (int)($_GET['user_id'] ?? 0);
        
        // Verificar si es un admin viendo el perfil
        $is_admin_view = isset($_SESSION['admin_viewing_profile']) && $_SESSION['admin_viewing_profile'] === true;
        if ($is_admin_view) {
            // Limpiar la bandera después de usarla
            unset($_SESSION['admin_viewing_profile']);
        }
        
        // Si se proporciona user_id, buscar por ID en lugar de nick
        if ($user_id > 0) {
            $st = $DB->prepare('
                SELECT 
                    u.id, 
                    u.nick, 
                    u.first_name,
                    u.last_name,
                    u.dob,
                    u.created_at,
                    p.avatar_url, 
                    p.bio,
                    p.province_code,
                    p.municipality_code,
                    prov.name as province_name,
                    mun.name as municipality_name
                FROM users u 
                LEFT JOIN profiles p ON p.user_id = u.id 
                LEFT JOIN provinces prov ON prov.code = p.province_code
                LEFT JOIN municipalities mun ON mun.code = p.municipality_code
                WHERE u.id = ? 
                LIMIT 1
            ');
            $st->execute([$user_id]);
            $profile = $st->fetch();
        } else if ($nick !== '') {
            // Buscar por nick (comportamiento normal)
            $st = $DB->prepare('
                SELECT 
                    u.id, 
                    u.nick, 
                    u.first_name,
                    u.last_name,
                    u.dob,
                    u.created_at,
                    p.avatar_url, 
                    p.bio,
                    p.province_code,
                    p.municipality_code,
                    prov.name as province_name,
                    mun.name as municipality_name
                FROM users u 
                LEFT JOIN profiles p ON p.user_id = u.id 
                LEFT JOIN provinces prov ON prov.code = p.province_code
                LEFT JOIN municipalities mun ON mun.code = p.municipality_code
                WHERE u.nick = ? 
                LIMIT 1
            ');
            $st->execute([$nick]);
            $profile = $st->fetch();
        } else {
            // Si no se proporciona nick ni user_id, mostrar el perfil propio
            $nick = $me['nick'];
            $st = $DB->prepare('
                SELECT 
                    u.id, 
                    u.nick, 
                    u.first_name,
                    u.last_name,
                    u.dob,
                    u.created_at,
                    p.avatar_url, 
                    p.bio,
                    p.province_code,
                    p.municipality_code,
                    prov.name as province_name,
                    mun.name as municipality_name
                FROM users u 
                LEFT JOIN profiles p ON p.user_id = u.id 
                LEFT JOIN provinces prov ON prov.code = p.province_code
                LEFT JOIN municipalities mun ON mun.code = p.municipality_code
                WHERE u.nick = ? 
                LIMIT 1
            ');
            $st->execute([$nick]);
            $profile = $st->fetch();
        }
        
        if (!$profile) {
            http_response_code(404);
            echo 'Perfil no encontrado';
            return;
        }

        $uid = $me['id'];
        $profile_id = (int)$profile['id'];
        $state = 'none';
        $friend_request_id = null;

        // Determinar el estado de la relación
        if ($profile_id === $uid) {
            $state = 'self';
        } else {
            // Verificar si son amigos
            $f = $DB->prepare('SELECT 1 FROM friendships WHERE user_id = ? AND friend_id = ?');
            $f->execute([$uid, $profile_id]);
            if ($f->fetchColumn()) {
                $state = 'friend';
            } else {
                // Verificar solicitudes de amistad
                $rq = $DB->prepare('
                    SELECT id, sender_id, receiver_id, status 
                    FROM friend_requests 
                    WHERE ((sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)) 
                    AND status = "pending" 
                    LIMIT 1
                ');
                $rq->execute([$uid, $profile_id, $profile_id, $uid]);
                $request = $rq->fetch();
                
                if ($request) {
                    $friend_request_id = (int)$request['id'];
                    $state = ($request['sender_id'] === $uid) ? 'outgoing' : 'incoming';
                }
            }
        }

        // Si es admin viendo el perfil, permitir acceso completo sin restricciones de amistad
        $can_view_full_profile = $is_admin_view || $state === 'self' || $state === 'friend';
        
        if (!$can_view_full_profile) {
            // Mostrar perfil limitado para no amigos
            view('profile/public', [
                'profile' => $profile,
                'state' => $state,
                'friend_request_id' => $friend_request_id
            ]);
            return;
        }

        // Obtener estadísticas (solo para vista completa)
        $stats = [];
        
        // Contar fotos
        $photos_count_stmt = $DB->prepare('
            SELECT COUNT(*) FROM photos 
            WHERE owner_id = ? 
        ');
        $photos_count_stmt->execute([$profile_id]);
        $stats['photos_count'] = (int)$photos_count_stmt->fetchColumn();
        
        // Contar amigos
        $friends_count_stmt = $DB->prepare('
            SELECT COUNT(*) FROM friendships 
            WHERE user_id = ?
        ');
        $friends_count_stmt->execute([$profile_id]);
        $stats['friends_count'] = (int)$friends_count_stmt->fetchColumn();

        // Obtener fotos del usuario (solo para vista completa)
        $photos_stmt = $DB->prepare('
            SELECT 
                p.id,
                p.storage_rel_path,
                po.text,
                po.visibility,
                po.created_at,
                (SELECT COUNT(*) FROM post_likes WHERE post_id = po.id) as like_count,
                (SELECT COUNT(*) FROM post_comments WHERE post_id = po.id) as comment_count
            FROM photos p 
            JOIN posts po ON po.id = p.post_id
            WHERE p.owner_id = ?
            ORDER BY po.created_at DESC
        ');
        $photos_stmt->execute([$profile_id]);
        $photos = $photos_stmt->fetchAll();

        // Pasar datos a la vista
        view('profile/show', [
            'profile' => $profile,
            'state' => $state,
            'stats' => $stats,
            'photos' => $photos,
            'friend_request_id' => $friend_request_id,
            'is_admin_view' => $is_admin_view
        ]);
    }

    
    public static function updateAvatar() {
        require_auth();
        verify_csrf();
        global $DB;
        
        $me = user();
        $uid = $me['id'];

        // === 1) Si llega recorte desde canvas (avatar_data), usarlo y guardar ===
        if (!empty($_POST['avatar_data']) && preg_match('~^data:(image/\\w+);base64,(.+)$~', $_POST['avatar_data'], $m)) {
            $mime = $m[1];
            $raw = base64_decode($m[2]);
            $allowed = [
                'image/jpeg' => 'jpg',
                'image/png'  => 'png',
                'image/webp' => 'webp',
                'image/gif'  => 'gif'
            ];
            if (!isset($allowed[$mime])) {
                set_flash('Formato no permitido en recorte.');
                redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
            }
            $ext = $allowed[$mime];
            $avatarsDir = UPLOADS_PATH . '/avatars';
            if (!is_dir($avatarsDir)) { @mkdir($avatarsDir, 0775, true); }
            $basename = bin2hex(random_bytes(12)) . '.' . $ext;
            $destPath = $avatarsDir . '/' . $basename;
            if (file_put_contents($destPath, $raw) === false) {
                set_flash('No se pudo guardar el recorte.');
                redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
            }
            // Asegurar tamaño exacto 256x256 y preservar transparencia
            self::processAvatar($destPath, $mime, $destPath, 256);
            $publicUrl = asset_url('uploads/avatars/' . $basename);
            // Obtener y borrar anterior si es local
            $st = $DB->prepare('SELECT avatar_url FROM profiles WHERE user_id = ?');
            $st->execute([$uid]);
            $old = $st->fetchColumn();
            $upd = $DB->prepare('UPDATE profiles SET avatar_url = ? WHERE user_id = ?');
            $upd->execute([$publicUrl, $uid]);
            if ($old && str_contains($old, '/uploads/avatars/')) {
                $rel = preg_replace('~^.*?/uploads/avatars/~', '', $old);
                $oldPath = UPLOADS_PATH . '/avatars/' . $rel;
                if (is_file($oldPath)) { @unlink($oldPath); }
            }
            set_flash('Avatar actualizado correctamente.');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }

        // === 2) Fallback: subida directa de archivo (sin recorte) ===
        $file = $_FILES['avatar'] ?? null;
        if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
            set_flash('Selecciona una imagen para el avatar.');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }
        
        $maxSize = 2 * 1024 * 1024; // 2MB
        if ($file['size'] > $maxSize) {
            set_flash('El archivo es demasiado grande (máx 2MB).');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }
        
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $mime = $finfo->file($file['tmp_name']);
        $allowed = [
            'image/jpeg' => 'jpg',
            'image/png'  => 'png',
            'image/webp' => 'webp',
            'image/gif'  => 'gif'
        ];
        if (!isset($allowed[$mime])) {
            set_flash('Formato no permitido. Usa JPG, PNG, WEBP o GIF.');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }
        
        $avatarsDir = UPLOADS_PATH . '/avatars';
        if (!is_dir($avatarsDir)) { @mkdir($avatarsDir, 0775, true); }
        $ext = $allowed[$mime];
        $basename = bin2hex(random_bytes(12)) . '.' . $ext;
        $destPath = $avatarsDir . '/' . $basename;
        
        if (!move_uploaded_file($file['tmp_name'], $destPath)) {
            set_flash('No se pudo guardar el archivo.');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }
        
        // Procesar a cuadrado 256x256 (center-crop) para uniformidad
        $processed = self::processAvatar($destPath, $mime, $destPath, 256);
        if (!$processed) {
            @unlink($destPath);
            set_flash('No se pudo procesar la imagen.');
            redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
        }
        
        $publicUrl = asset_url('uploads/avatars/' . $basename);
        
        // Obtener avatar anterior y actualizar
        $st = $DB->prepare('SELECT avatar_url FROM profiles WHERE user_id = ?');
        $st->execute([$uid]);
        $old = $st->fetchColumn();
        $upd = $DB->prepare('UPDATE profiles SET avatar_url = ? WHERE user_id = ?');
        $upd->execute([$publicUrl, $uid]);
        if ($old && str_contains($old, '/uploads/avatars/')) {
            $rel = preg_replace('~^.*?/uploads/avatars/~', '', $old);
            $oldPath = UPLOADS_PATH . '/avatars/' . $rel;
            if (is_file($oldPath)) { @unlink($oldPath); }
        }
        
        set_flash('Avatar actualizado correctamente.');
        redirect(base_url('/profile?nick=' . urlencode($me['nick'])));
    }
    
    
    public static function edit() {
        require_auth();
        global $DB;
        $me = user();
        $stmt = $DB->prepare('
            SELECT u.email, u.nick, u.first_name, u.last_name,
                   pr.province_code, pr.municipality_code, pr.avatar_url, pr.bio
            FROM users u
            LEFT JOIN profiles pr ON pr.user_id = u.id
            WHERE u.id = ?
        ');
        $stmt->execute([$me['id']]);
        $row = $stmt->fetch();
        $provinces = $DB->query('SELECT code, name FROM provinces ORDER BY name')->fetchAll();
        $municipalities = [];
        if (!empty($row['province_code'])) {
            $st = $DB->prepare('SELECT code, name FROM municipalities WHERE province_code = ? ORDER BY name');
            $st->execute([$row['province_code']]);
            $municipalities = $st->fetchAll();
        }
        view('profile/edit', ['data'=>$row,'provinces'=>$provinces,'municipalities'=>$municipalities]);
    }
    
    public static function update() {
        require_auth();
        verify_csrf();
        global $DB;
        $me = user();
        
        $email = trim($_POST['email'] ?? '');
        $nick = trim($_POST['nick'] ?? '');
        $first = trim($_POST['first_name'] ?? '');
        $last = trim($_POST['last_name'] ?? '');
        $bio = trim($_POST['bio'] ?? '');
        $province = trim($_POST['province_code'] ?? '');
        $municipality = trim($_POST['municipality_code'] ?? '');
        $current_password = $_POST['current_password'] ?? '';
        $new_password = $_POST['new_password'] ?? '';
        $new_password2 = $_POST['new_password2'] ?? '';
        
        // Validaciones básicas
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { 
            set_flash('Email inválido.'); 
            redirect(base_url('/profile/edit')); 
        }
        
        // Validación del nick
        if (empty($nick) || strlen($nick) < 3) {
            set_flash('El nombre de usuario debe tener al menos 3 caracteres.');
            redirect(base_url('/profile/edit'));
        }
        
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $nick)) {
            set_flash('El nombre de usuario solo puede contener letras, números y guiones bajos.');
            redirect(base_url('/profile/edit'));
        }
        
        // Validación de contraseña
        if ($new_password || $new_password2) {
            if (strlen($new_password) < 8) { 
                set_flash('La nueva contraseña debe tener al menos 8 caracteres.'); 
                redirect(base_url('/profile/edit')); 
            }
            if ($new_password !== $new_password2) { 
                set_flash('Las contraseñas no coinciden.'); 
                redirect(base_url('/profile/edit')); 
            }
            if (!$current_password) { 
                set_flash('Introduce tu contraseña actual para cambiarla.'); 
                redirect(base_url('/profile/edit')); 
            }
            $st = $DB->prepare('SELECT password_hash FROM users WHERE id = ?'); 
            $st->execute([$me['id']]);
            $hash = $st->fetchColumn();
            if (!$hash || !password_verify($current_password, $hash)) { 
                set_flash('La contraseña actual no es correcta.'); 
                redirect(base_url('/profile/edit')); 
            }
        }
        
        // Verificar unicidad del email
        $st = $DB->prepare('SELECT id FROM users WHERE email = ? AND id != ?'); 
        $st->execute([$email, $me['id']]);
        if ($st->fetch()) { 
            set_flash('Ese email ya está en uso.'); 
            redirect(base_url('/profile/edit')); 
        }
        
        // Verificar unicidad del nick
        $st = $DB->prepare('SELECT id FROM users WHERE nick = ? AND id != ?'); 
        $st->execute([$nick, $me['id']]);
        if ($st->fetch()) { 
            set_flash('Ese nombre de usuario ya está en uso.'); 
            redirect(base_url('/profile/edit')); 
        }
        
        $DB->beginTransaction();
        try {
            // Actualizar datos del usuario
            $uq = 'UPDATE users SET email = ?, nick = ?, first_name = ?, last_name = ?';
            $params = [$email, $nick, $first, $last];
            
            if ($new_password) { 
                $new_hash = password_hash($new_password, PASSWORD_DEFAULT); 
                $uq .= ', password_hash = ?'; 
                $params[] = $new_hash; 
            }
            
            $uq .= ' WHERE id = ?'; 
            $params[] = $me['id'];
            $st = $DB->prepare($uq); 
            $st->execute($params);
            
            // Actualizar o insertar perfil
            $DB->prepare('INSERT IGNORE INTO profiles (user_id, bio, province_code, municipality_code, avatar_url, consents) VALUES (?, ?, ?, ?, NULL, NULL)')
               ->execute([$me['id'], $bio, $province, $municipality]);
            
            $DB->prepare('UPDATE profiles SET bio = ?, province_code = ?, municipality_code = ? WHERE user_id = ?')
               ->execute([$bio, $province, $municipality, $me['id']]);
            
            $DB->commit(); 
            set_flash('Perfil actualizado correctamente.');
            
            // Actualizar sesión si el nick cambió
            if ($nick !== $me['nick']) {
                $_SESSION['user']['nick'] = $nick;
            }
            
        } catch (\Exception $e) {
            $DB->rollBack(); 
            error_log('Profile update error: ' . $e->getMessage()); 
            set_flash('No se pudo actualizar el perfil.');
        }
        
        redirect(base_url('/profile?nick=' . urlencode($nick)));
    }

    public static function checkEmail() {
        require_auth();
        verify_csrf();
        global $DB;
        
        $email = trim($_POST['email'] ?? '');
        $me = user();
        
        if (empty($email)) {
            echo json_encode(['available' => false]);
            return;
        }
        
        // Verificar si el email ya está en uso por otro usuario
        $st = $DB->prepare('SELECT id FROM users WHERE email = ? AND id != ?');
        $st->execute([$email, $me['id']]);
        $exists = $st->fetch();
        
        echo json_encode(['available' => !$exists]);
    }

    public static function checkNick() {
        require_auth();
        verify_csrf();
        global $DB;
        
        $nick = trim($_POST['nick'] ?? '');
        $me = user();
        
        if (empty($nick)) {
            echo json_encode(['available' => false]);
            return;
        }
        
        // Verificar si el nick ya está en uso por otro usuario
        $st = $DB->prepare('SELECT id FROM users WHERE nick = ? AND id != ?');
        $st->execute([$nick, $me['id']]);
        $exists = $st->fetch();
        
        echo json_encode(['available' => !$exists]);
    }
}
?>