package com.saas.admin.controller;

import com.saas.admin.dto.CallerIdMappingResponse;
import com.saas.admin.dto.CreateCallerIdMappingRequest;
import com.saas.admin.entity.CallerIdMapping;
import com.saas.admin.repository.TenantRepository;
import com.saas.admin.repository.UserRepository;
import com.saas.admin.service.CallerIdMappingService;
import com.saas.shared.dto.common.ApiResponse;
import com.saas.shared.dto.common.PageResponse;
import com.saas.shared.security.UserPrincipal;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * CallerIdMappingController
 * 
 * Admin API for managing caller ID to tenant mappings for call forwarding
 * scenarios.
 * 
 * Access: SYSTEM_ADMIN only
 * Base Path: /api/admin/caller-id-mappings
 */
@RestController
@RequestMapping("/api/admin/caller-id-mappings")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Caller ID Mappings", description = "Admin APIs for managing custom caller ID to tenant mappings (call forwarding support)")
@PreAuthorize("hasRole('SYSTEM_ADMIN')")
public class CallerIdMappingController {

        private final CallerIdMappingService callerIdMappingService;
        private final TenantRepository tenantRepository;
        private final UserRepository userRepository;

        @PostMapping
        @Operation(summary = "Create caller ID mapping", description = "Map a caller phone number to a tenant for call forwarding scenarios")
        public ResponseEntity<ApiResponse<CallerIdMappingResponse>> createMapping(
                        @Valid @RequestBody CreateCallerIdMappingRequest request) {

                log.info("📞 [API] Creating caller ID mapping: From={}, Tenant={}",
                                request.getFromPhoneNumber(), request.getTenantId());

                Long currentUserId = getCurrentUserId();

                CallerIdMapping mapping = callerIdMappingService.createMapping(
                                request.getFromPhoneNumber(),
                                request.getTenantId(),
                                request.getDescription(),
                                currentUserId);

                CallerIdMappingResponse response = mapToResponse(mapping);

                return ResponseEntity.ok(ApiResponse.success(response, "Caller ID mapping created successfully"));
        }

        @GetMapping
        @Operation(summary = "List caller ID mappings", description = "Get all caller ID mappings with optional tenant filter (paginated)")
        public ResponseEntity<ApiResponse<PageResponse<CallerIdMappingResponse>>> listMappings(
                        @RequestParam(required = false) String tenantId,
                        @RequestParam(defaultValue = "0") int page,
                        @RequestParam(defaultValue = "20") int size,
                        @RequestParam(defaultValue = "createdAt") String sortBy,
                        @RequestParam(defaultValue = "DESC") String sortDir) {

                Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
                Pageable pageable = PageRequest.of(page, size, sort);

                Page<CallerIdMapping> mappingsPage = tenantId != null
                                ? callerIdMappingService.listMappingsByTenant(tenantId, pageable)
                                : callerIdMappingService.listMappingsByTenant(null, pageable); // List all if no tenant
                                                                                               // filter

                List<CallerIdMappingResponse> responses = mappingsPage.getContent().stream()
                                .map(this::mapToResponse)
                                .collect(Collectors.toList());

                PageResponse<CallerIdMappingResponse> pageResponse = PageResponse.<CallerIdMappingResponse>builder()
                                .content(responses)
                                .page(mappingsPage.getNumber())
                                .size(mappingsPage.getSize())
                                .totalElements(mappingsPage.getTotalElements())
                                .totalPages(mappingsPage.getTotalPages())
                                .hasNext(mappingsPage.hasNext())
                                .hasPrevious(mappingsPage.hasPrevious())
                                .build();

                return ResponseEntity
                                .ok(ApiResponse.success(pageResponse, "Caller ID mappings retrieved successfully"));
        }

        @GetMapping("/{id}")
        @Operation(summary = "Get caller ID mapping by ID")
        public ResponseEntity<ApiResponse<CallerIdMappingResponse>> getMappingById(@PathVariable Long id) {
                CallerIdMapping mapping = callerIdMappingService.getMappingById(id);
                CallerIdMappingResponse response = mapToResponse(mapping);
                return ResponseEntity.ok(ApiResponse.success(response));
        }

        @DeleteMapping("/{id}")
        @Operation(summary = "Delete caller ID mapping", description = "Remove a custom caller ID mapping")
        public ResponseEntity<ApiResponse<Void>> deleteMapping(@PathVariable Long id) {
                log.info("🗑️ [API] Deleting caller ID mapping: ID={}", id);
                callerIdMappingService.deleteMapping(id);
                return ResponseEntity.ok(ApiResponse.success(null, "Caller ID mapping deleted successfully"));
        }

        @PatchMapping("/{id}/toggle-status")
        @Operation(summary = "Toggle mapping active status", description = "Enable/disable a caller ID mapping without deleting it")
        public ResponseEntity<ApiResponse<CallerIdMappingResponse>> toggleStatus(@PathVariable Long id) {
                log.info("🔄 [API] Toggling caller ID mapping status: ID={}", id);
                CallerIdMapping updated = callerIdMappingService.toggleMappingStatus(id);
                CallerIdMappingResponse response = mapToResponse(updated);
                return ResponseEntity.ok(ApiResponse.success(response, "Mapping status updated successfully"));
        }

        @GetMapping("/count")
        @Operation(summary = "Count mappings by tenant", description = "Get total caller ID mappings count for a tenant (quota check)")
        public ResponseEntity<ApiResponse<Long>> countMappingsByTenant(@RequestParam String tenantId) {
                long count = callerIdMappingService.countMappingsByTenant(tenantId);
                return ResponseEntity.ok(ApiResponse.success(count));
        }

        /**
         * Map entity to response DTO with tenant and user names
         */
        private CallerIdMappingResponse mapToResponse(CallerIdMapping mapping) {
                String tenantName = tenantRepository.findByTenantId(mapping.getTenantId())
                                .map(t -> t.getTenantName())
                                .orElse("Unknown");

                String createdByName = userRepository.findById(mapping.getCreatedBy())
                                .map(u -> u.getFirstName() + " " + u.getLastName())
                                .orElse("Unknown");

                return CallerIdMappingResponse.builder()
                                .id(mapping.getId())
                                .fromPhoneNumber(mapping.getFromPhoneNumber())
                                .tenantId(mapping.getTenantId())
                                .tenantName(tenantName)
                                .description(mapping.getDescription())
                                .createdBy(mapping.getCreatedBy())
                                .createdByName(createdByName)
                                .isActive(mapping.getIsActive())
                                .createdAt(mapping.getCreatedAt())
                                .updatedAt(mapping.getUpdatedAt())
                                .build();
        }

        private Long getCurrentUserId() {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication != null && authentication.getPrincipal() instanceof UserPrincipal principal) {
                        return principal.getId();
                }
                return null;
        }
}
