package com.writeoff.module.project.controller;

import com.writeoff.common.api.ApiResponse;
import com.writeoff.common.api.PageResult;
import com.writeoff.module.project.dto.CreateProjectRequest;
import com.writeoff.module.project.dto.SaveProjectBindingsRequest;
import com.writeoff.module.project.model.Project;
import com.writeoff.module.project.service.ProjectService;
import com.writeoff.module.export.dto.CreateExportTaskRequest;
import com.writeoff.module.export.service.ExportTaskService;
import com.writeoff.security.DataScopeType;
import com.writeoff.security.RequirePermission;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/projects")
public class ProjectController {
    private final ProjectService projectService;
    private final ExportTaskService exportTaskService;

    public ProjectController(ProjectService projectService, ExportTaskService exportTaskService) {
        this.projectService = projectService;
        this.exportTaskService = exportTaskService;
    }

    @GetMapping
    public ApiResponse<PageResult<Project>> list(@RequestParam(value = "parentOnly", required = false) Boolean parentOnly,
                                                 @RequestParam(value = "includeDeleted", required = false) Boolean includeDeleted) {
        return ApiResponse.success(projectService.list(parentOnly, includeDeleted));
    }

    @GetMapping("/{id}/children")
    public ApiResponse<List<Project>> children(@PathVariable("id") Long id,
                                               @RequestParam(value = "includeDeleted", required = false) Boolean includeDeleted) {
        return ApiResponse.success(projectService.listChildren(id, includeDeleted));
    }

    @PostMapping
    @RequirePermission(value = "project.create", dataScope = DataScopeType.TENANT, auditAction = "PROJECT_CREATE")
    public ApiResponse<Project> create(@RequestBody @Valid CreateProjectRequest request) {
        return ApiResponse.success(projectService.create(request));
    }

    @PutMapping("/{id}")
    @RequirePermission(value = "project.create", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_UPDATE")
    public ApiResponse<Project> update(@PathVariable("id") Long id,
                                       @RequestBody @Valid CreateProjectRequest request) {
        return ApiResponse.success(projectService.update(id, request));
    }

    @GetMapping("/binding-candidates")
    @RequirePermission(value = "project.bind.user", dataScope = DataScopeType.TENANT, auditAction = "PROJECT_BIND_CANDIDATES")
    public ApiResponse<Map<String, Object>> bindingCandidates() {
        return ApiResponse.success(projectService.listBindingCandidates());
    }

    @GetMapping("/{id}/bindings")
    @RequirePermission(value = "project.bind.user", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_BIND_READ")
    public ApiResponse<Map<String, Object>> bindings(@PathVariable("id") Long id) {
        return ApiResponse.success(projectService.getBindings(id));
    }

    @GetMapping("/{id}/key-change-logs")
    @RequirePermission(value = "project.key-change-log.read", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_KEY_CHANGE_LOG_LIST")
    public ApiResponse<List<Map<String, Object>>> keyChangeLogs(@PathVariable("id") Long id) {
        return ApiResponse.success(projectService.listKeyChangeLogs(id));
    }

    @PostMapping("/{id}/bindings")
    @RequirePermission(value = "project.bind.user", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_BIND_SAVE")
    public ApiResponse<String> saveBindings(@PathVariable("id") Long id,
                                            @RequestBody @Valid SaveProjectBindingsRequest request) {
        projectService.saveBindings(id, request);
        return ApiResponse.success("OK");
    }

    @PostMapping("/{id}/freeze")
    @RequirePermission(value = "project.freeze", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_FREEZE")
    public ApiResponse<Map<String, Object>> freeze(@PathVariable("id") Long id,
                                                   @RequestParam String reason) {
        Project project = projectService.freeze(id, reason);
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("projectId", project.getId());
        result.put("status", project.getStatus().name());
        result.put("reason", reason);
        return ApiResponse.success(result);
    }

    @PostMapping("/{id}/unfreeze")
    @RequirePermission(value = "project.unfreeze", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_UNFREEZE")
    public ApiResponse<Map<String, Object>> unfreeze(@PathVariable("id") Long id,
                                                     @RequestBody Map<String, String> body) {
        String reason = body == null ? null : body.get("reason");
        Project project = projectService.unfreeze(id, reason);
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("projectId", project.getId());
        result.put("status", project.getStatus().name());
        result.put("reason", reason);
        return ApiResponse.success(result);
    }

    @PostMapping("/{id}/archive")
    @RequirePermission(value = "project.archive", dataScope = DataScopeType.PROJECT, auditAction = "PROJECT_ARCHIVE")
    public ApiResponse<Map<String, Object>> archive(@PathVariable("id") Long id) {
        Project project = projectService.archive(id);
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("projectId", project.getId());
        result.put("status", project.getStatus().name());
        return ApiResponse.success(result);
    }

    @PostMapping("/export")
    @RequirePermission(value = "project.create", dataScope = DataScopeType.TENANT, auditAction = "PROJECT_EXPORT")
    public ApiResponse<Map<String, Object>> exportProjects(@RequestBody @Valid CreateExportTaskRequest request) {
        request.setTaskCode("PROJECT_EXPORT");
        request.setBizType("PROJECT");
        return ApiResponse.success(exportTaskService.create(request));
    }
}
