package com.writeoff.module.template.controller;

import com.writeoff.common.api.ApiResponse;
import com.writeoff.common.api.PageResult;
import com.writeoff.module.template.dto.CreateTemplateRequest;
import com.writeoff.module.template.dto.CreateTemplateVersionRequest;
import com.writeoff.module.template.dto.BindFlowTemplateRequest;
import com.writeoff.module.template.dto.RollbackTemplateRequest;
import com.writeoff.module.template.dto.TemplateUploadSignRequest;
import com.writeoff.module.template.model.TemplateDownloadLogInfo;
import com.writeoff.module.template.model.TemplateFlowLinkInfo;
import com.writeoff.module.template.model.TemplateInfo;
import com.writeoff.module.template.model.TemplateTypeOption;
import com.writeoff.module.template.model.TemplateVersionInfo;
import com.writeoff.module.template.service.TemplateService;
import com.writeoff.security.DataScopeType;
import com.writeoff.security.RequirePermission;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/templates")
public class TemplateController {
    private final TemplateService templateService;

    public TemplateController(TemplateService templateService) {
        this.templateService = templateService;
    }

    @GetMapping
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_LIST")
    public ApiResponse<PageResult<TemplateInfo>> list(
            @RequestParam(value = "templateName", required = false) String templateName,
            @RequestParam(value = "templateType", required = false) String templateType,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "scopeType", required = false) String scopeType,
            @RequestParam(value = "bizScene", required = false) String bizScene,
            @RequestParam(value = "watermarkEnabled", required = false) Boolean watermarkEnabled,
            @RequestParam(value = "effectiveStatus", required = false) String effectiveStatus,
            @RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
            @RequestParam(value = "pageSize", defaultValue = "20") int pageSize) {
        return ApiResponse.success(templateService.list(templateName, templateType, status, scopeType, bizScene, watermarkEnabled, effectiveStatus, pageNo, pageSize));
    }

    @GetMapping("/published-options")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_PUBLISHED_OPTIONS")
    public ApiResponse<List<TemplateInfo>> publishedOptions(
            @RequestParam(value = "bizScene", required = false) String bizScene) {
        return ApiResponse.success(templateService.listPublishedOptions(bizScene));
    }

    @GetMapping("/type-options")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_TYPE_OPTIONS")
    public ApiResponse<List<TemplateTypeOption>> typeOptions() {
        return ApiResponse.success(templateService.listTypeOptions());
    }

    @GetMapping("/flow-scene-options")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_FLOW_SCENE_OPTIONS")
    public ApiResponse<List<Map<String, String>>> flowSceneOptions() {
        return ApiResponse.success(templateService.flowSceneOptions());
    }

    @GetMapping("/flow-links")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_FLOW_LINKS")
    public ApiResponse<List<TemplateFlowLinkInfo>> flowLinks() {
        return ApiResponse.success(templateService.listFlowLinks());
    }

    @PostMapping("/flow-links/{sceneCode}/bind")
    @RequirePermission(value = "template.flow.link", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_FLOW_LINK_BIND")
    public ApiResponse<TemplateFlowLinkInfo> bindFlowLink(@PathVariable("sceneCode") String sceneCode,
                                                           @RequestBody @Valid BindFlowTemplateRequest request) {
        return ApiResponse.success(templateService.bindFlowLink(sceneCode, request.getTemplateId()));
    }

    @PostMapping("/type-options/{typeCode}/enable")
    @RequirePermission(value = "template.publish", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_TYPE_ENABLE")
    public ApiResponse<String> enableTypeOption(@PathVariable("typeCode") String typeCode) {
        templateService.enableTypeOption(typeCode);
        return ApiResponse.success("ok");
    }

    @PostMapping("/type-options/{typeCode}/disable")
    @RequirePermission(value = "template.publish", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_TYPE_DISABLE")
    public ApiResponse<String> disableTypeOption(@PathVariable("typeCode") String typeCode) {
        templateService.disableTypeOption(typeCode);
        return ApiResponse.success("ok");
    }

    @PostMapping
    @RequirePermission(value = "template.create", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_CREATE")
    public ApiResponse<TemplateInfo> create(@RequestBody @Valid CreateTemplateRequest request) {
        return ApiResponse.success(templateService.create(request));
    }

    @PostMapping("/upload-sign")
    @RequirePermission(value = "template.create", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_UPLOAD_SIGN")
    public ApiResponse<Map<String, Object>> uploadSign(@RequestBody @Valid TemplateUploadSignRequest request) {
        return ApiResponse.success(templateService.presignUpload(request));
    }

    @GetMapping("/{id}/versions")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_VERSIONS")
    public ApiResponse<List<TemplateVersionInfo>> versions(@PathVariable("id") Long id) {
        return ApiResponse.success(templateService.versions(id));
    }

    @PostMapping("/{id}/versions")
    @RequirePermission(value = "template.create", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_VERSION_CREATE")
    public ApiResponse<TemplateInfo> addVersion(@PathVariable("id") Long id,
                                                @RequestBody @Valid CreateTemplateVersionRequest request) {
        return ApiResponse.success(templateService.addVersion(id, request));
    }

    @PostMapping("/{id}/publish")
    @RequirePermission(value = "template.publish", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_PUBLISH")
    public ApiResponse<TemplateInfo> publish(@PathVariable("id") Long id) {
        return ApiResponse.success(templateService.publish(id));
    }

    @PostMapping("/{id}/disable")
    @RequirePermission(value = "template.disable", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_DISABLE")
    public ApiResponse<TemplateInfo> disable(@PathVariable("id") Long id) {
        return ApiResponse.success(templateService.disable(id));
    }

    @PostMapping("/{id}/archive")
    @RequirePermission(value = "template.archive", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_ARCHIVE")
    public ApiResponse<TemplateInfo> archive(@PathVariable("id") Long id) {
        return ApiResponse.success(templateService.archive(id));
    }

    @PostMapping("/{id}/rollback")
    @RequirePermission(value = "template.rollback", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_ROLLBACK")
    public ApiResponse<TemplateInfo> rollback(@PathVariable("id") Long id,
                                              @RequestBody @Valid RollbackTemplateRequest request) {
        return ApiResponse.success(templateService.rollback(id, request));
    }

    @GetMapping("/{id}/download")
    @RequirePermission(value = "template.download", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_DOWNLOAD")
    public ApiResponse<Map<String, Object>> download(@PathVariable("id") Long id, HttpServletRequest request) {
        return ApiResponse.success(templateService.download(id, request.getRemoteAddr(), request.getHeader("User-Agent")));
    }

    @GetMapping("/{id}/download-watermark")
    @RequirePermission(value = "template.download", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_DOWNLOAD_WATERMARK")
    public ApiResponse<Map<String, Object>> downloadWatermark(@PathVariable("id") Long id,
                                                               @RequestParam(value = "watermarkText", required = false) String watermarkText,
                                                               HttpServletRequest request) {
        return ApiResponse.success(templateService.downloadWatermark(id, watermarkText, request.getRemoteAddr(), request.getHeader("User-Agent")));
    }

    @GetMapping("/{id}/versions/diff")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_VERSION_DIFF")
    public ApiResponse<Map<String, Object>> versionDiff(@PathVariable("id") Long id,
                                                         @RequestParam(value = "leftVersionNo", required = false) Integer leftVersionNo,
                                                         @RequestParam(value = "rightVersionNo", required = false) Integer rightVersionNo) {
        return ApiResponse.success(templateService.versionDiff(id, leftVersionNo, rightVersionNo));
    }

    @GetMapping("/download-logs")
    @RequirePermission(value = "template.read", dataScope = DataScopeType.TENANT, auditAction = "TEMPLATE_DOWNLOAD_LOGS")
    public ApiResponse<PageResult<TemplateDownloadLogInfo>> downloadLogs(
            @RequestParam(value = "templateId", required = false) Long templateId,
            @RequestParam(value = "templateName", required = false) String templateName,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "userKeyword", required = false) String userKeyword,
            @RequestParam(value = "versionNo", required = false) Integer versionNo,
            @RequestParam(value = "downloadType", required = false) String downloadType,
            @RequestParam(value = "ip", required = false) String ip,
            @RequestParam(value = "downloadedFrom", required = false) String downloadedFrom,
            @RequestParam(value = "downloadedTo", required = false) String downloadedTo,
            @RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
            @RequestParam(value = "pageSize", defaultValue = "20") int pageSize) {
        return ApiResponse.success(templateService.listDownloadLogs(
                templateId,
                templateName,
                userId,
                userKeyword,
                versionNo,
                downloadType,
                ip,
                downloadedFrom,
                downloadedTo,
                pageNo,
                pageSize
        ));
    }
}
