<?php
namespace lib;

class Folder {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }

    // 创建文件夹
    public function create($uid, $name, $parentId = 0) {
        // 检查名称合法性
        if (preg_match('/[\\/:*?"<>|]/', $name)) {
            return ['code' => -1, 'msg' => '文件夹名称包含非法字符'];
        }
        
        // 检查父文件夹是否存在且属于该用户
        if ($parentId > 0) {
            $parent = $this->db->getRow("SELECT * FROM pre_folder WHERE folder_id=:id AND uid=:uid", [':id' => $parentId, ':uid' => $uid]);
            if (!$parent) {
                return ['code' => -1, 'msg' => '父文件夹不存在'];
            }
        }

        // 检查同名文件夹
        $exists = $this->db->getRow("SELECT folder_id FROM pre_folder WHERE uid=:uid AND parent_id=:pid AND name=:name", [':uid' => $uid, ':pid' => $parentId, ':name' => $name]);
        if ($exists) {
            return ['code' => -1, 'msg' => '同名文件夹已存在'];
        }

        $data = [
            'uid' => $uid,
            'parent_id' => $parentId,
            'name' => $name,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
            'perm_read' => 1,
            'perm_write' => 1,
            'perm_exec' => 1
        ];

        if ($this->db->insert('folder', $data)) {
            $this->log($uid, 'create_folder', "Created folder '$name' under parent $parentId");
            return ['code' => 0, 'msg' => '创建成功'];
        } else {
            return ['code' => -1, 'msg' => '创建失败'];
        }
    }

    // 重命名
    public function rename($uid, $folderId, $newName) {
        if (preg_match('/[\\/:*?"<>|]/', $newName)) {
            return ['code' => -1, 'msg' => '名称包含非法字符'];
        }

        $folder = $this->db->getRow("SELECT * FROM pre_folder WHERE folder_id=:id AND uid=:uid", [':id' => $folderId, ':uid' => $uid]);
        if (!$folder) {
            return ['code' => -1, 'msg' => '文件夹不存在'];
        }

        // Check duplicate
        $exists = $this->db->getRow("SELECT folder_id FROM pre_folder WHERE uid=:uid AND parent_id=:pid AND name=:name AND folder_id!=:id", [':uid' => $uid, ':pid' => $folder['parent_id'], ':name' => $newName, ':id' => $folderId]);
        if ($exists) {
            return ['code' => -1, 'msg' => '同名文件夹已存在'];
        }

        if ($this->db->update('folder', ['name' => $newName, 'updated_at' => date('Y-m-d H:i:s')], ['folder_id' => $folderId])) {
            $this->log($uid, 'rename_folder', "Renamed folder {$folderId} to '$newName'");
            return ['code' => 0, 'msg' => '重命名成功'];
        }
        return ['code' => -1, 'msg' => '重命名失败'];
    }

    // 排序
    public function sort($uid, $folderId, $sort) {
        if ($this->db->update('folder', ['sort' => $sort, 'updated_at' => date('Y-m-d H:i:s')], ['folder_id' => $folderId, 'uid' => $uid])) {
            return ['code' => 0, 'msg' => '排序设置成功'];
        }
        return ['code' => -1, 'msg' => '设置失败'];
    }

    // 删除文件夹 (递归删除)
    public function delete($uid, $folderId) {
        $folder = $this->db->getRow("SELECT * FROM pre_folder WHERE folder_id=:id AND uid=:uid", [':id' => $folderId, ':uid' => $uid]);
        if (!$folder) {
            return ['code' => -1, 'msg' => '文件夹不存在'];
        }

        // 查找所有子文件夹
        $subFolders = $this->db->getAll("SELECT folder_id FROM pre_folder WHERE parent_id=:pid", [':pid' => $folderId]);
        if ($subFolders) {
            foreach ($subFolders as $sub) {
                $this->delete($uid, $sub['folder_id']);
            }
        }

        // 删除该文件夹下的文件记录（实际文件删除逻辑需要对接 StorHelper，这里仅处理数据库记录）
        // 假设这里仅仅是解除关系或者删除记录，具体看业务需求。
        // 为了完整性，这里应该先获取所有文件，然后调用 StorHelper 删除，但为了简化，我们先只删除数据库记录。
        $files = $this->db->getAll("SELECT id, hash FROM pre_file WHERE folder_id=:fid AND uid=:uid", [':fid' => $folderId, ':uid' => $uid]);
        if ($files) {
            global $conf;
            $stor = \lib\StorHelper::getModel($conf['storage']);
            foreach ($files as $f) {
                if ($stor) {
                    $stor->delete($f['hash']);
                }
            }
        }
        $this->db->delete('file', ['folder_id' => $folderId, 'uid' => $uid]);
        
        // 删除文件夹
        if ($this->db->delete('folder', ['folder_id' => $folderId])) {
            $this->log($uid, 'delete_folder', "Deleted folder {$folderId}");
            return ['code' => 0, 'msg' => '删除成功'];
        }
        return ['code' => -1, 'msg' => '删除失败'];
    }
    
    // 移动文件夹/文件
    public function move($uid, $targetFolderId, $folderIds = [], $fileIds = []) {
        // Check target folder
        if ($targetFolderId > 0) {
            $target = $this->db->getRow("SELECT * FROM pre_folder WHERE folder_id=:id AND uid=:uid", [':id' => $targetFolderId, ':uid' => $uid]);
            if (!$target) return ['code' => -1, 'msg' => '目标文件夹不存在'];
        }

        $count = 0;
        if (!empty($folderIds)) {
            // 防止移动到自己或自己的子文件夹中
            if (in_array($targetFolderId, $folderIds)) {
                return ['code' => -1, 'msg' => '不能移动到自身'];
            }
            
            // 检查目标文件夹是否是待移动文件夹的子文件夹（防止循环）
            foreach ($folderIds as $fid) {
                if ($this->isSubFolder($targetFolderId, $fid)) {
                    return ['code' => -1, 'msg' => '不能移动到子文件夹中'];
                }
            }

            foreach ($folderIds as $fid) {
                // 检查是否已经在目标文件夹
                $current = $this->db->getRow("SELECT parent_id FROM pre_folder WHERE folder_id=:id AND uid=:uid", [':id' => $fid, ':uid' => $uid]);
                if ($current && $current['parent_id'] != $targetFolderId) {
                    $this->db->update('folder', ['parent_id' => $targetFolderId], ['folder_id' => $fid, 'uid' => $uid]);
                    $count++;
                }
            }
        }

        if (!empty($fileIds)) {
             foreach ($fileIds as $fid) {
                $this->db->update('file', ['folder_id' => $targetFolderId], ['id' => $fid, 'uid' => $uid]);
                $count++;
            }
        }

        $this->log($uid, 'move', "Moved items to folder $targetFolderId");
        return ['code' => 0, 'msg' => "成功移动 {$count} 项"];
    }

    // 检查 subId 是否是 parentId 的子孙
    private function isSubFolder($subId, $parentId) {
        if ($subId == 0) return false;
        if ($subId == $parentId) return true;
        
        $curr = $subId;
        while ($curr > 0) {
            $folder = $this->db->getRow("SELECT parent_id FROM pre_folder WHERE folder_id=:id", [':id' => $curr]);
            if (!$folder) break;
            if ($folder['parent_id'] == $parentId) return true;
            $curr = $folder['parent_id'];
        }
        return false;
    }

    // 获取文件夹列表（面包屑导航辅助）
    public function getPath($uid, $folderId) {
        $path = [];
        $curr = $folderId;
        while ($curr > 0) {
            $folder = $this->db->getRow("SELECT folder_id, name, parent_id FROM pre_folder WHERE folder_id=:id", [':id' => $curr]);
            if ($folder) {
                array_unshift($path, $folder);
                $curr = $folder['parent_id'];
            } else {
                break;
            }
        }
        return $path;
    }

    // 获取文件夹内容（子文件夹）
    public function getFolders($uid, $parentId = 0) {
        // Try to order by sort ASC, then name ASC. 
        $res = false;
        try {
            $res = $this->db->getAll("SELECT * FROM pre_folder WHERE uid=:uid AND parent_id=:pid ORDER BY sort ASC, name ASC", [':uid' => $uid, ':pid' => $parentId]);
        } catch (\Exception $e) {
            // Ignore exception and try fallback
        }

        // If getAll returned false (query failed) or threw exception
        if ($res === false) {
            return $this->db->getAll("SELECT * FROM pre_folder WHERE uid=:uid AND parent_id=:pid ORDER BY name ASC", [':uid' => $uid, ':pid' => $parentId]);
        }
        
        return $res;
    }
    
    private function log($uid, $action, $details) {
        $ip = function_exists('real_ip') ? real_ip() : $_SERVER['REMOTE_ADDR'];
        $this->db->insert('log', [
            'uid' => $uid,
            'action' => $action,
            'details' => $details,
            'ip' => $ip,
            'created_at' => date('Y-m-d H:i:s')
        ]);
    }
}
?>
