package net.siegeln.cameleer.saas.portal;

import net.siegeln.cameleer.saas.certificate.TenantCaCertEntity;
import net.siegeln.cameleer.saas.certificate.TenantCaCertService;
import net.siegeln.cameleer.saas.config.TenantContext;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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 java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/api/tenant")
public class TenantPortalController {

    private final TenantPortalService portalService;
    private final TenantCaCertService caCertService;

    public TenantPortalController(TenantPortalService portalService, TenantCaCertService caCertService) {
        this.portalService = portalService;
        this.caCertService = caCertService;
    }

    // --- Request bodies ---

    public record InviteRequest(String email, String roleId) {}

    public record RoleChangeRequest(String roleId) {}

    public record PasswordChangeRequest(String password) {}

    // --- Endpoints ---

    @GetMapping("/dashboard")
    public ResponseEntity<TenantPortalService.DashboardData> getDashboard() {
        return ResponseEntity.ok(portalService.getDashboard());
    }

    @GetMapping("/license")
    public ResponseEntity<TenantPortalService.LicenseData> getLicense() {
        var license = portalService.getLicense();
        if (license == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(license);
    }

    @GetMapping("/team")
    public ResponseEntity<List<Map<String, Object>>> listTeamMembers() {
        return ResponseEntity.ok(portalService.listTeamMembers());
    }

    @PostMapping("/team/invite")
    public ResponseEntity<Map<String, String>> inviteTeamMember(@RequestBody InviteRequest body) {
        String userId = portalService.inviteTeamMember(body.email(), body.roleId());
        return ResponseEntity.ok(Map.of("userId", userId != null ? userId : ""));
    }

    @DeleteMapping("/team/{userId}")
    public ResponseEntity<Void> removeTeamMember(@PathVariable String userId) {
        portalService.removeTeamMember(userId);
        return ResponseEntity.noContent().build();
    }

    @PatchMapping("/team/{userId}/role")
    public ResponseEntity<Void> changeTeamMemberRole(@PathVariable String userId,
                                                      @RequestBody RoleChangeRequest body) {
        portalService.changeTeamMemberRole(userId, body.roleId());
        return ResponseEntity.ok().build();
    }

    @PostMapping("/server/admin-password")
    public ResponseEntity<Void> resetServerAdminPassword(@RequestBody PasswordChangeRequest body) {
        try {
            portalService.resetServerAdminPassword(body.password());
            return ResponseEntity.noContent().build();
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        } catch (IllegalStateException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    @PostMapping("/password")
    public ResponseEntity<Void> changeOwnPassword(@AuthenticationPrincipal Jwt jwt,
                                                    @RequestBody PasswordChangeRequest body) {
        try {
            portalService.changePassword(jwt.getSubject(), body.password());
            return ResponseEntity.noContent().build();
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    @PostMapping("/team/{userId}/password")
    public ResponseEntity<Void> resetTeamMemberPassword(@PathVariable String userId,
                                                         @RequestBody PasswordChangeRequest body) {
        try {
            portalService.resetTeamMemberPassword(userId, body.password());
            return ResponseEntity.noContent().build();
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    @PostMapping("/server/restart")
    public ResponseEntity<Void> restartServer() {
        portalService.restartServer();
        return ResponseEntity.noContent().build();
    }

    @PostMapping("/server/upgrade")
    public ResponseEntity<Void> upgradeServer() {
        portalService.upgradeServer();
        return ResponseEntity.noContent().build();
    }

    @GetMapping("/settings")
    public ResponseEntity<TenantPortalService.TenantSettingsData> getSettings() {
        return ResponseEntity.ok(portalService.getSettings());
    }

    // --- CA Certificate management ---

    public record CaCertResponse(
        UUID id, String status, String label, String subject, String issuer,
        String fingerprint, Instant notBefore, Instant notAfter, Instant createdAt
    ) {
        public static CaCertResponse from(TenantCaCertEntity e) {
            return new CaCertResponse(
                e.getId(), e.getStatus().name(), e.getLabel(), e.getSubject(), e.getIssuer(),
                e.getFingerprint(), e.getNotBefore(), e.getNotAfter(), e.getCreatedAt()
            );
        }
    }

    @GetMapping("/ca")
    public ResponseEntity<List<CaCertResponse>> listCaCerts() {
        UUID tenantId = TenantContext.getTenantId();
        return ResponseEntity.ok(
            caCertService.listForTenant(tenantId).stream().map(CaCertResponse::from).toList()
        );
    }

    @PostMapping("/ca")
    public ResponseEntity<CaCertResponse> stageCaCert(
            @RequestParam("cert") MultipartFile certFile,
            @RequestParam(value = "label", required = false) String label) {
        try {
            UUID tenantId = TenantContext.getTenantId();
            var entity = caCertService.stage(tenantId, label, certFile.getBytes());
            return ResponseEntity.ok(CaCertResponse.from(entity));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    @PostMapping("/ca/{id}/activate")
    public ResponseEntity<CaCertResponse> activateCaCert(@PathVariable UUID id) {
        try {
            UUID tenantId = TenantContext.getTenantId();
            var entity = caCertService.activate(tenantId, id);
            return ResponseEntity.ok(CaCertResponse.from(entity));
        } catch (IllegalArgumentException | IllegalStateException e) {
            return ResponseEntity.badRequest().build();
        }
    }

    @DeleteMapping("/ca/{id}")
    public ResponseEntity<Void> deleteCaCert(@PathVariable UUID id) {
        try {
            UUID tenantId = TenantContext.getTenantId();
            caCertService.delete(tenantId, id);
            return ResponseEntity.noContent().build();
        } catch (IllegalArgumentException e) {
            return ResponseEntity.notFound().build();
        }
    }
}
