package com.writeoff.module.system.controller;

import com.writeoff.common.api.ApiResponse;
import com.writeoff.common.api.PageResult;
import com.writeoff.common.model.ImportResult;
import com.writeoff.module.system.dto.AssignUserRoleRequest;
import com.writeoff.module.system.dto.CreateUserRequest;
import com.writeoff.module.system.dto.CreateUserDelegationRequest;
import com.writeoff.module.system.dto.ImportUsersRequest;
import com.writeoff.module.system.dto.ResetPasswordRequest;
import com.writeoff.module.system.model.SystemUser;
import com.writeoff.module.system.model.UserDelegationInfo;
import com.writeoff.module.system.model.UserRoleHistory;
import com.writeoff.module.system.service.SystemUserService;
import com.writeoff.module.system.service.UserDelegationService;
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 org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
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.bind.annotation.PutMapping;

import javax.validation.Valid;

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final SystemUserService systemUserService;
    private final UserDelegationService userDelegationService;
    private final ExportTaskService exportTaskService;

    public UserController(SystemUserService systemUserService, UserDelegationService userDelegationService, ExportTaskService exportTaskService) {
        this.systemUserService = systemUserService;
        this.userDelegationService = userDelegationService;
        this.exportTaskService = exportTaskService;
    }

    @GetMapping
    @RequirePermission(value = "user.read", dataScope = DataScopeType.TENANT, auditAction = "USER_LIST")
    public ApiResponse<PageResult<SystemUser>> list(
            @RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
            @RequestParam(value = "pageSize", defaultValue = "20") int pageSize,
            @RequestParam(value = "includeDeleted", required = false) Boolean includeDeleted,
            @RequestParam(value = "keyword", required = false) String keyword) {
        return ApiResponse.success(systemUserService.listUsers(pageNo, pageSize, includeDeleted, keyword));
    }

    @PostMapping
    @RequirePermission(value = "user.create", dataScope = DataScopeType.TENANT, auditAction = "USER_CREATE")
    public ApiResponse<SystemUser> create(@RequestBody @Valid CreateUserRequest request) {
        return ApiResponse.success(systemUserService.createUser(request));
    }

    @PutMapping("/{id}")
    @RequirePermission(value = "user.update", dataScope = DataScopeType.TENANT, auditAction = "USER_UPDATE")
    public ApiResponse<SystemUser> update(@PathVariable("id") Long id, @RequestBody @Valid CreateUserRequest request) {
        return ApiResponse.success(systemUserService.updateUser(id, request));
    }

    @PostMapping("/assign-role")
    @RequirePermission(value = "user.role.assign", dataScope = DataScopeType.TENANT, auditAction = "USER_ASSIGN_ROLE")
    public ApiResponse<String> assignRole(@RequestBody @Valid AssignUserRoleRequest request) {
        systemUserService.assignRole(request.getUserId(), request.getRoleId());
        return ApiResponse.success("OK");
    }

    @PostMapping("/{id}/enable")
    @RequirePermission(value = "user.enable", dataScope = DataScopeType.TENANT, auditAction = "USER_ENABLE")
    public ApiResponse<String> enable(@PathVariable("id") Long id) {
        systemUserService.enableUser(id);
        return ApiResponse.success("OK");
    }

    @PostMapping("/{id}/disable")
    @RequirePermission(value = "user.disable", dataScope = DataScopeType.TENANT, auditAction = "USER_DISABLE")
    public ApiResponse<String> disable(@PathVariable("id") Long id) {
        systemUserService.disableUser(id);
        return ApiResponse.success("OK");
    }

    @PostMapping("/{id}/delete")
    @RequirePermission(value = "user.delete", dataScope = DataScopeType.TENANT, auditAction = "USER_DELETE")
    public ApiResponse<String> softDelete(@PathVariable("id") Long id) {
        systemUserService.softDeleteUser(id);
        return ApiResponse.success("OK");
    }

    @PostMapping("/{id}/reset-password")
    @RequirePermission(value = "user.password.reset", dataScope = DataScopeType.TENANT, auditAction = "USER_RESET_PASSWORD")
    public ApiResponse<String> resetPassword(@PathVariable("id") Long id, @RequestBody @Valid ResetPasswordRequest request) {
        systemUserService.resetPassword(id, request);
        return ApiResponse.success("OK");
    }

    @GetMapping("/{id}/role-history")
    @RequirePermission(value = "user.role.history.read", dataScope = DataScopeType.TENANT, auditAction = "USER_ROLE_HISTORY")
    public ApiResponse<PageResult<UserRoleHistory>> roleHistory(@PathVariable("id") Long id) {
        return ApiResponse.success(systemUserService.listUserRoleHistory(id));
    }

    @GetMapping("/{id}/delegations")
    @RequirePermission(value = "user.delegation.manage", dataScope = DataScopeType.TENANT, auditAction = "USER_DELEGATION_LIST")
    public ApiResponse<PageResult<UserDelegationInfo>> delegations(@PathVariable("id") Long id) {
        return ApiResponse.success(userDelegationService.listByUserId(id));
    }

    @PostMapping("/{id}/delegations")
    @RequirePermission(value = "user.delegation.manage", dataScope = DataScopeType.TENANT, auditAction = "USER_DELEGATION_CREATE")
    public ApiResponse<UserDelegationInfo> createDelegation(@PathVariable("id") Long id,
                                                            @RequestBody @Valid CreateUserDelegationRequest request) {
        return ApiResponse.success(userDelegationService.create(id, request));
    }

    @PostMapping("/import")
    @RequirePermission(value = "user.import", dataScope = DataScopeType.TENANT, auditAction = "USER_IMPORT")
    public ApiResponse<ImportResult> importUsers(@RequestBody @Valid ImportUsersRequest request) {
        return ApiResponse.success(systemUserService.importUsers(request.getUsers()));
    }

    @PostMapping("/export")
    @RequirePermission(value = "user.read", dataScope = DataScopeType.TENANT, auditAction = "USER_EXPORT")
    public ApiResponse<java.util.Map<String, Object>> exportUsers(@RequestBody @Valid CreateExportTaskRequest request) {
        request.setTaskCode("USER_EXPORT");
        request.setBizType("USER");
        return ApiResponse.success(exportTaskService.create(request));
    }
}
