<?php
/**
 * HuSNS - 存储插件
 * 
 * @author  HYR
 * @QQ      281900864
 * @website https://huyourui.com
 * @license MIT
 * @声明    严禁用于违法违规用途
 */
namespace Plugin\storage;

use Hook;
use Helper;

class Plugin
{
    public function __construct()
    {
        Hook::register('post_before_publish', [$this, 'onPostBeforePublish']);
        Hook::register('post_before_delete', [$this, 'onPostBeforeDelete']);
        Hook::register('upload_after', [$this, 'onUploadAfter']);
        Hook::register('before_render', [$this, 'onBeforeRender']);
        Hook::register('admin_menu', [$this, 'addAdminMenu']);
        Hook::register('app_start', [$this, 'onAppStart']);
        Hook::register('app_end', [$this, 'onAppEnd']);
    }

    /**
     * 应用启动 - 开启输出缓冲
     * 仅在远程存储可用时开启，否则不需要缓冲替换
     */
    public function onAppStart($params = null)
    {
        $manager = new StorageManager();
        $currentType = $manager->getCurrentStorageType();

        if ($currentType !== 'local') {
            $driver = $manager->getDriver($currentType);
            // 远程存储配置有效时才开启输出缓冲
            if ($driver->validateConfig()) {
                ob_start();
            }
        }
        return $params;
    }

    /**
     * 应用结束 - 替换输出中的本地URL为远程URL
     * 如果远程存储不可用，则不替换，保持本地URL
     */
    public function onAppEnd($params = null)
    {
        $manager = new StorageManager();
        $currentType = $manager->getCurrentStorageType();

        if ($currentType === 'local') {
            return $params;
        }

        // 检查远程存储是否可用，不可用则保持本地URL
        $driver = $manager->getDriver($currentType);
        if (!$driver->validateConfig()) {
            // 远程存储不可用，直接输出缓冲内容（保持本地URL）
            $output = ob_get_clean();
            if ($output) {
                echo $output;
            }
            return $params;
        }

        $output = ob_get_clean();

        if ($output) {
            $baseUrl = \Helper::getBaseUrl();
            // 本地URL前缀，如 /uploads/ 或 http://domain/uploads/
            $localPrefix = $baseUrl ? $baseUrl . '/uploads/' : '/uploads/';
            $remoteBaseUrl = rtrim($driver->getUrl(''), '/');

            // 替换HTML中所有 /uploads/xxx 的本地URL为远程URL
            if (!empty($remoteBaseUrl)) {
                $output = preg_replace(
                    '#(src|href)=["\']' . preg_quote($localPrefix, '#') . '([^"\']+)["\']#i',
                    '$1="' . $remoteBaseUrl . '/$2"',
                    $output
                );
            }

            echo $output;
        }

        return $params;
    }

    /**
     * 帖子发布前 - 将本地文件同步到远程存储
     * 如果远程存储不可用，则回退到本地存储
     */
    public function onPostBeforePublish($data)
    {
        $manager = new StorageManager();
        $currentType = $manager->getCurrentStorageType();

        // 本地存储不需要处理
        if ($currentType === 'local') {
            return $data;
        }

        // 检查远程存储是否可用
        $driver = $manager->getDriver($currentType);
        $remoteAvailable = $driver->validateConfig();

        // 处理图片
        if (isset($data['images']) && is_array($data['images'])) {
            $newImages = [];
            foreach ($data['images'] as $image) {
                $localPath = $this->getLocalFullPath($image);
                if (file_exists($localPath)) {
                    $uploaded = false;
                    if ($remoteAvailable) {
                        $result = $driver->upload($localPath, $image, basename($image));
                        if ($result['success']) {
                            $newImages[] = $image;
                            $this->recordFile([
                                'filename' => $result['filename'] ?? basename($image),
                                'original_name' => basename($image),
                                'path' => $image,
                                'url' => $result['url'] ?? '',
                                'storage_type' => $currentType,
                                'file_type' => 'image',
                                'file_size' => $result['file_size'] ?? filesize($localPath),
                                'user_id' => $data['user_id'] ?? null
                            ]);
                            @unlink($localPath);
                            $uploaded = true;
                        }
                    }
                    if (!$uploaded) {
                        // 远程上传失败或不可用，回退到本地存储
                        $newImages[] = $image;
                        $this->recordFile([
                            'filename' => basename($image),
                            'original_name' => basename($image),
                            'path' => $image,
                            'url' => '',
                            'storage_type' => 'local',
                            'file_type' => 'image',
                            'file_size' => filesize($localPath),
                            'user_id' => $data['user_id'] ?? null
                        ]);
                    }
                } else {
                    $newImages[] = $image;
                }
            }
            $data['images'] = $newImages;
        }

        // 处理视频
        if (isset($data['videos']) && is_array($data['videos'])) {
            $newVideos = [];
            foreach ($data['videos'] as $video) {
                $localPath = $this->getLocalFullPath($video);
                if (file_exists($localPath)) {
                    $uploaded = false;
                    if ($remoteAvailable) {
                        $result = $driver->upload($localPath, $video, basename($video));
                        if ($result['success']) {
                            $newVideos[] = $video;
                            $this->recordFile([
                                'filename' => $result['filename'] ?? basename($video),
                                'original_name' => basename($video),
                                'path' => $video,
                                'url' => $result['url'] ?? '',
                                'storage_type' => $currentType,
                                'file_type' => 'video',
                                'file_size' => $result['file_size'] ?? filesize($localPath),
                                'user_id' => $data['user_id'] ?? null
                            ]);
                            @unlink($localPath);
                            $uploaded = true;
                        }
                    }
                    if (!$uploaded) {
                        // 远程上传失败或不可用，回退到本地存储
                        $newVideos[] = $video;
                        $this->recordFile([
                            'filename' => basename($video),
                            'original_name' => basename($video),
                            'path' => $video,
                            'url' => '',
                            'storage_type' => 'local',
                            'file_type' => 'video',
                            'file_size' => filesize($localPath),
                            'user_id' => $data['user_id'] ?? null
                        ]);
                    }
                } else {
                    $newVideos[] = $video;
                }
            }
            $data['videos'] = $newVideos;
        }

        // 处理附件
        if (isset($data['attachments']) && is_array($data['attachments'])) {
            $newAttachments = [];
            foreach ($data['attachments'] as $attachment) {
                $path = is_array($attachment) ? ($attachment['path'] ?? '') : $attachment;
                $localPath = $this->getLocalFullPath($path);
                if (file_exists($localPath)) {
                    $uploaded = false;
                    if ($remoteAvailable) {
                        $result = $driver->upload($localPath, $path, basename($path));
                        if ($result['success']) {
                            if (is_array($attachment)) {
                                $attachment['path'] = $path;
                                $attachment['url'] = $result['url'] ?? '';
                                $newAttachments[] = $attachment;
                            } else {
                                $newAttachments[] = $path;
                            }
                            $this->recordFile([
                                'filename' => $result['filename'] ?? basename($path),
                                'original_name' => basename($path),
                                'path' => $path,
                                'url' => $result['url'] ?? '',
                                'storage_type' => $currentType,
                                'file_type' => 'attachment',
                                'file_size' => $result['file_size'] ?? filesize($localPath),
                                'user_id' => $data['user_id'] ?? null
                            ]);
                            @unlink($localPath);
                            $uploaded = true;
                        }
                    }
                    if (!$uploaded) {
                        // 远程上传失败或不可用，回退到本地存储
                        $newAttachments[] = $attachment;
                        $this->recordFile([
                            'filename' => basename($path),
                            'original_name' => basename($path),
                            'path' => $path,
                            'url' => '',
                            'storage_type' => 'local',
                            'file_type' => 'attachment',
                            'file_size' => filesize($localPath),
                            'user_id' => $data['user_id'] ?? null
                        ]);
                    }
                } else {
                    $newAttachments[] = $attachment;
                }
            }
            $data['attachments'] = $newAttachments;
        }

        return $data;
    }

    /**
     * 帖子删除前 - 删除远程存储中的文件
     * 如果远程存储不可用，则只删除本地文件
     */
    public function onPostBeforeDelete($post)
    {
        $manager = new StorageManager();
        $currentType = $manager->getCurrentStorageType();

        // 本地存储由核心代码处理删除
        if ($currentType === 'local') {
            return $post;
        }

        // 检查远程存储是否可用
        $driver = $manager->getDriver($currentType);
        if (!$driver->validateConfig()) {
            // 远程存储不可用，尝试删除本地文件
            $this->deleteLocalFiles($post);
            return $post;
        }

        // 删除图片
        if (!empty($post['images'])) {
            $images = is_array($post['images']) ? $post['images'] : json_decode($post['images'], true);
            if (is_array($images)) {
                foreach ($images as $image) {
                    $driver->delete($image);
                }
            }
        }

        // 删除视频
        if (!empty($post['videos'])) {
            $videos = is_array($post['videos']) ? $post['videos'] : json_decode($post['videos'], true);
            if (is_array($videos)) {
                foreach ($videos as $video) {
                    $driver->delete($video);
                }
            }
        }

        // 删除附件
        if (!empty($post['attachments'])) {
            $attachments = is_array($post['attachments']) ? $post['attachments'] : json_decode($post['attachments'], true);
            if (is_array($attachments)) {
                foreach ($attachments as $attachment) {
                    $path = is_array($attachment) ? ($attachment['path'] ?? '') : $attachment;
                    if ($path) {
                        $driver->delete($path);
                    }
                }
            }
        }

        return $post;
    }

    /**
     * 删除本地文件（远程不可用时的回退处理）
     */
    private function deleteLocalFiles($post)
    {
        // 删除本地图片
        if (!empty($post['images'])) {
            $images = is_array($post['images']) ? $post['images'] : json_decode($post['images'], true);
            if (is_array($images)) {
                foreach ($images as $image) {
                    $localPath = $this->getLocalFullPath($image);
                    if (file_exists($localPath)) {
                        @unlink($localPath);
                    }
                }
            }
        }

        // 删除本地视频
        if (!empty($post['videos'])) {
            $videos = is_array($post['videos']) ? $post['videos'] : json_decode($post['videos'], true);
            if (is_array($videos)) {
                foreach ($videos as $video) {
                    $path = is_array($video) ? ($video['path'] ?? '') : $video;
                    if ($path) {
                        $localPath = $this->getLocalFullPath($path);
                        if (file_exists($localPath)) {
                            @unlink($localPath);
                        }
                    }
                }
            }
        }

        // 删除本地附件
        if (!empty($post['attachments'])) {
            $attachments = is_array($post['attachments']) ? $post['attachments'] : json_decode($post['attachments'], true);
            if (is_array($attachments)) {
                foreach ($attachments as $attachment) {
                    $path = is_array($attachment) ? ($attachment['path'] ?? '') : $attachment;
                    if ($path) {
                        $localPath = $this->getLocalFullPath($path);
                        if (file_exists($localPath)) {
                            @unlink($localPath);
                        }
                    }
                }
            }
        }
    }

    /**
     * 渲染前 - 将远程存储文件URL替换为远程地址
     * 如果远程存储不可用，则不替换，保持本地URL
     */
    public function onBeforeRender($data)
    {
        $manager = new StorageManager();
        $currentType = $manager->getCurrentStorageType();

        // 本地存储不需要替换URL
        if ($currentType === 'local') {
            return $data;
        }

        // 检查远程存储是否可用，不可用则保持本地URL
        $driver = $manager->getDriver($currentType);
        if (!$driver->validateConfig()) {
            return $data;
        }

        $uploadPath = defined('UPLOAD_PATH') ? UPLOAD_PATH : (\ROOT_PATH . 'uploads/');

        // 遍历数据，将本地文件路径对应的URL替换为远程URL
        // 处理帖子列表中的 images 字段
        if (isset($data['posts']) && is_array($data['posts'])) {
            foreach ($data['posts'] as &$post) {
                $post = $this->replacePostUrls($post, $driver);
            }
            unset($post);
        }

        // 处理单条帖子
        if (isset($data['post']) && is_array($data['post'])) {
            $data['post'] = $this->replacePostUrls($data['post'], $driver);
        }

        return $data;
    }

    /**
     * 替换帖子中的文件URL为远程URL
     */
    private function replacePostUrls($post, $driver)
    {
        // 处理图片
        if (!empty($post['images'])) {
            $images = is_array($post['images']) ? $post['images'] : json_decode($post['images'], true);
            if (is_array($images)) {
                $newImages = [];
                foreach ($images as $image) {
                    // 如果是完整URL则跳过
                    if (strpos($image, '://') !== false) {
                        $newImages[] = $image;
                    } else {
                        $newImages[] = $driver->getUrl($image);
                    }
                }
                $post['images'] = is_string($post['images']) ? json_encode($newImages) : $newImages;
            }
        }

        // 处理视频
        if (!empty($post['videos'])) {
            $videos = is_array($post['videos']) ? $post['videos'] : json_decode($post['videos'], true);
            if (is_array($videos)) {
                $newVideos = [];
                foreach ($videos as $video) {
                    if (is_array($video)) {
                        if (isset($video['path']) && strpos($video['path'], '://') === false) {
                            $video['path'] = $driver->getUrl($video['path']);
                        }
                        $newVideos[] = $video;
                    } else {
                        if (strpos($video, '://') !== false) {
                            $newVideos[] = $video;
                        } else {
                            $newVideos[] = $driver->getUrl($video);
                        }
                    }
                }
                $post['videos'] = is_string($post['videos']) ? json_encode($newVideos) : $newVideos;
            }
        }

        // 处理附件
        if (!empty($post['attachments'])) {
            $attachments = is_array($post['attachments']) ? $post['attachments'] : json_decode($post['attachments'], true);
            if (is_array($attachments)) {
                $newAttachments = [];
                foreach ($attachments as $attachment) {
                    if (is_array($attachment)) {
                        if (isset($attachment['path']) && strpos($attachment['path'], '://') === false) {
                            $attachment['url'] = $driver->getUrl($attachment['path']);
                        }
                        $newAttachments[] = $attachment;
                    } else {
                        if (strpos($attachment, '://') !== false) {
                            $newAttachments[] = $attachment;
                        } else {
                            $newAttachments[] = $driver->getUrl($attachment);
                        }
                    }
                }
                $post['attachments'] = is_string($post['attachments']) ? json_encode($newAttachments) : $newAttachments;
            }
        }

        return $post;
    }

    /**
     * 上传后处理 - 记录文件信息（用于本地存储）
     */
    public function onUploadAfter($params)
    {
        if (isset($params['filename']) && isset($params['original_name'])) {
            $this->recordFile($params);
        }
        return $params;
    }

    /**
     * 添加后台菜单
     */
    public function addAdminMenu($menus)
    {
        $menus[] = [
            'name' => 'storage',
            'title' => '存储管理',
            'icon' => 'fa-hdd',
            'children' => [
                [
                    'name' => 'storage/config',
                    'title' => '存储设置',
                    'url' => Helper::url('storage/config')
                ],
                [
                    'name' => 'storage/files',
                    'title' => '文件管理',
                    'url' => Helper::url('storage/files')
                ]
            ]
        ];
        return $menus;
    }

    /**
     * 获取本地完整文件路径
     */
    private function getLocalFullPath($relativePath)
    {
        $uploadPath = defined('UPLOAD_PATH') ? UPLOAD_PATH : (\ROOT_PATH . 'uploads/');
        return $uploadPath . ltrim($relativePath, '/');
    }

    /**
     * 记录文件上传信息
     */
    private function recordFile($params)
    {
        try {
            $db = \Database::getInstance();
            $db->insert('storage_files', [
                'original_name' => $params['original_name'] ?? '',
                'filename' => $params['filename'] ?? '',
                'path' => $params['path'] ?? '',
                'url' => $params['url'] ?? '',
                'storage_type' => $params['storage_type'] ?? 'local',
                'file_type' => $params['file_type'] ?? 'image',
                'file_size' => $params['file_size'] ?? 0,
                'mime_type' => $params['mime_type'] ?? '',
                'user_id' => $params['user_id'] ?? (isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null),
                'created_at' => time()
            ]);
        } catch (\Exception $e) {
            // 记录失败不影响上传
        }
    }
}
