package com.yushu.web.controller.system;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.yushu.common.annotation.Log;
import com.yushu.common.config.FileStorageConfig;
import com.yushu.common.core.controller.BaseController;
import com.yushu.common.core.domain.AjaxResult;
import com.yushu.common.enums.BusinessType;
import com.yushu.system.domain.SysFileInfo;
import com.yushu.system.service.ISysFileService;
import com.yushu.common.utils.poi.ExcelUtil;
import com.yushu.common.core.page.TableDataInfo;

/**
 * 文件Controller
 * 
 * @author yushu
 * @date 2024-11-15
 */
@RestController
@RequestMapping("/system/file")
public class SysFileController extends BaseController
{
    @Autowired
    private ISysFileService sysFileService;
    
    @Autowired
    private FileStorageConfig fileStorageConfig;

    /**
     * 查询文件列表
     */
    @PreAuthorize("@ss.hasPermi('system:file:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysFileInfo sysFile)
    {
        startPage();
        List<SysFileInfo> list = sysFileService.selectSysFileList(sysFile);
        return getDataTable(list);
    }

    /**
     * 导出文件列表
     */
    @PreAuthorize("@ss.hasPermi('system:file:export')")
    @Log(title = "文件", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysFileInfo sysFile)
    {
        List<SysFileInfo> list = sysFileService.selectSysFileList(sysFile);
        ExcelUtil<SysFileInfo> util = new ExcelUtil<SysFileInfo>(SysFileInfo.class);
        util.exportExcel(response, list, "文件数据");
    }

    /**
     * 获取文件详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:file:query')")
    @GetMapping(value = "/{fileId}")
    public AjaxResult getInfo(@PathVariable("fileId") Long fileId)
    {
        return success(sysFileService.selectSysFileByFileId(fileId));
    }

    /**
     * 上传文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:add')")
    @Log(title = "文件上传", businessType = BusinessType.INSERT)
    @PostMapping("/upload")
    public AjaxResult upload(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "folderId", required = false) Long folderId,
            @RequestParam(value = "fileName", required = false) String fileName)
    {
        try
        {
            SysFileInfo sysFile = sysFileService.uploadFile(file, folderId, fileName);
            return success(sysFile);
        }
        catch (Exception e)
        {
            return error("上传文件失败：" + e.getMessage());
        }
    }

    /**
     * 修改文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:edit')")
    @Log(title = "文件", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysFileInfo sysFile)
    {
        return toAjax(sysFileService.updateSysFile(sysFile));
    }

    /**
     * 删除文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:remove')")
    @Log(title = "文件", businessType = BusinessType.DELETE)
	@DeleteMapping("/{fileIds}")
    public AjaxResult remove(@PathVariable Long[] fileIds)
    {
        return toAjax(sysFileService.deleteSysFileByFileIds(fileIds));
    }
    
    /**
     * 下载文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:query')")
    @GetMapping("/download/{fileId}")
    public void download(@PathVariable Long fileId, HttpServletResponse response)
    {
        try
        {
            SysFileInfo sysFile = sysFileService.downloadFile(fileId);
            if (sysFile == null)
            {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 获取文件完整路径
            String basePath = fileStorageConfig.getLocal().getNormalizedBasePath();
            String fullPath = basePath + File.separator + sysFile.getFilePath();
            File file = new File(fullPath);
            
            if (!file.exists())
            {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8"));
            response.setContentLengthLong(file.length());
            
            // 输出文件
            try (InputStream inputStream = new FileInputStream(file);
                 OutputStream outputStream = response.getOutputStream())
            {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1)
                {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }
        }
        catch (Exception e)
        {
            logger.error("下载文件失败", e);
        }
    }
    
    /**
     * 预览文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:query')")
    @GetMapping("/preview/{fileId}")
    public void preview(@PathVariable Long fileId, HttpServletResponse response)
    {
        try
        {
            SysFileInfo sysFile = sysFileService.selectSysFileByFileId(fileId);
            if (sysFile == null)
            {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 获取文件完整路径
            String basePath = fileStorageConfig.getLocal().getNormalizedBasePath();
            String fullPath = basePath + File.separator + sysFile.getFilePath();
            File file = new File(fullPath);
            
            if (!file.exists())
            {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            
            // 设置响应头（在线预览）
            response.setContentType(sysFile.getMimeType());
            response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8"));
            response.setContentLengthLong(file.length());
            
            // 输出文件
            try (InputStream inputStream = new FileInputStream(file);
                 OutputStream outputStream = response.getOutputStream())
            {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1)
                {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }
        }
        catch (Exception e)
        {
            logger.error("预览文件失败", e);
        }
    }
    
    /**
     * 移动文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:edit')")
    @Log(title = "移动文件", businessType = BusinessType.UPDATE)
    @PostMapping("/move")
    public AjaxResult move(@RequestParam Long fileId, @RequestParam Long targetFolderId)
    {
        return toAjax(sysFileService.moveFile(fileId, targetFolderId));
    }
    
    /**
     * 复制文件
     */
    @PreAuthorize("@ss.hasPermi('system:file:add')")
    @Log(title = "复制文件", businessType = BusinessType.INSERT)
    @PostMapping("/copy")
    public AjaxResult copy(@RequestParam Long fileId, @RequestParam Long targetFolderId)
    {
        return toAjax(sysFileService.copyFile(fileId, targetFolderId));
    }
}
