package com.social.media.controller;

import com.social.media.dto.SocialNetworkDto;
import com.social.media.service.SocialNetworkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
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.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * REST Controller for managing social networks
 */
@RestController
@RequestMapping("/api/social-networks")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "Social Networks", description = "Social Network Management API")
public class SocialNetworkController {
    
    private final SocialNetworkService socialNetworkService;
    
    @PostMapping
    @Operation(summary = "Create a new social network", description = "Creates a new social network configuration")
    public ResponseEntity<SocialNetworkDto> createSocialNetwork(
            @Valid @RequestBody SocialNetworkDto socialNetworkDto) {
        log.info("Creating new social network: {}", socialNetworkDto.getNetworkCode());
        SocialNetworkDto created = socialNetworkService.create(socialNetworkDto);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }
    
    @PutMapping("/{id}")
    @Operation(summary = "Update a social network", description = "Updates an existing social network configuration")
    public ResponseEntity<SocialNetworkDto> updateSocialNetwork(
            @Parameter(description = "Social Network ID") @PathVariable Long id,
            @Valid @RequestBody SocialNetworkDto socialNetworkDto) {
        log.info("Updating social network with ID: {}", id);
        SocialNetworkDto updated = socialNetworkService.update(id, socialNetworkDto);
        return ResponseEntity.ok(updated);
    }
    
    @GetMapping("/{id}")
    @Operation(summary = "Get social network by ID", description = "Retrieves a social network by its ID")
    public ResponseEntity<SocialNetworkDto> getSocialNetworkById(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        return socialNetworkService.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
    
    @GetMapping("/code/{networkCode}")
    @Operation(summary = "Get social network by code", description = "Retrieves a social network by its network code")
    public ResponseEntity<SocialNetworkDto> getSocialNetworkByCode(
            @Parameter(description = "Network Code") @PathVariable String networkCode) {
        return socialNetworkService.findByNetworkCode(networkCode)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
    
    @GetMapping
    @Operation(summary = "Get all social networks", description = "Retrieves all social networks with pagination")
    public ResponseEntity<Page<SocialNetworkDto>> getAllSocialNetworks(
            @Parameter(description = "Page number") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "Page size") @RequestParam(defaultValue = "20") int size,
            @Parameter(description = "Sort field") @RequestParam(defaultValue = "sortOrder") String sortBy,
            @Parameter(description = "Sort direction") @RequestParam(defaultValue = "ASC") String sortDir) {
        
        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<SocialNetworkDto> networks = socialNetworkService.findAll(pageable);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/active")
    @Operation(summary = "Get all active social networks", description = "Retrieves all active social networks")
    public ResponseEntity<List<SocialNetworkDto>> getActiveSocialNetworks() {
        List<SocialNetworkDto> networks = socialNetworkService.findAllActive();
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/active/paged")
    @Operation(summary = "Get active social networks with pagination", description = "Retrieves active social networks with pagination")
    public ResponseEntity<Page<SocialNetworkDto>> getActiveSocialNetworksPaged(
            @Parameter(description = "Page number") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "Page size") @RequestParam(defaultValue = "20") int size) {
        
        Pageable pageable = PageRequest.of(page, size);
        Page<SocialNetworkDto> networks = socialNetworkService.findAllActive(pageable);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/platform/{platform}")
    @Operation(summary = "Get social networks by platform", description = "Retrieves social networks by platform type")
    public ResponseEntity<List<SocialNetworkDto>> getSocialNetworksByPlatform(
            @Parameter(description = "Platform name") @PathVariable String platform) {
        List<SocialNetworkDto> networks = socialNetworkService.findByPlatform(platform);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/platform/{platform}/active")
    @Operation(summary = "Get active social networks by platform", description = "Retrieves active social networks by platform type")
    public ResponseEntity<List<SocialNetworkDto>> getActiveSocialNetworksByPlatform(
            @Parameter(description = "Platform name") @PathVariable String platform) {
        List<SocialNetworkDto> networks = socialNetworkService.findActiveByPlatform(platform);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/feature/{feature}")
    @Operation(summary = "Get networks supporting a feature", description = "Retrieves social networks that support a specific feature")
    public ResponseEntity<List<SocialNetworkDto>> getNetworksWithFeature(
            @Parameter(description = "Feature name") @PathVariable String feature) {
        List<SocialNetworkDto> networks = socialNetworkService.findNetworksWithFeature(feature);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/feature/{feature}/active")
    @Operation(summary = "Get active networks supporting a feature", description = "Retrieves active social networks that support a specific feature")
    public ResponseEntity<List<SocialNetworkDto>> getActiveNetworksWithFeature(
            @Parameter(description = "Feature name") @PathVariable String feature) {
        List<SocialNetworkDto> networks = socialNetworkService.findActiveNetworksWithFeature(feature);
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/approval-required")
    @Operation(summary = "Get networks requiring approval", description = "Retrieves social networks that require approval for connections")
    public ResponseEntity<List<SocialNetworkDto>> getNetworksRequiringApproval() {
        List<SocialNetworkDto> networks = socialNetworkService.findNetworksRequiringApproval();
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/production-ready")
    @Operation(summary = "Get production-ready networks", description = "Retrieves social networks that are ready for production use")
    public ResponseEntity<List<SocialNetworkDto>> getProductionReadyNetworks() {
        List<SocialNetworkDto> networks = socialNetworkService.findProductionReadyNetworks();
        return ResponseEntity.ok(networks);
    }
    
    @GetMapping("/search")
    @Operation(summary = "Search social networks by name", description = "Searches social networks by name (case-insensitive)")
    public ResponseEntity<List<SocialNetworkDto>> searchSocialNetworks(
            @Parameter(description = "Search query") @RequestParam String query) {
        List<SocialNetworkDto> networks = socialNetworkService.searchByName(query);
        return ResponseEntity.ok(networks);
    }
    
    @PostMapping("/{id}/activate")
    @Operation(summary = "Activate a social network", description = "Activates a social network")
    public ResponseEntity<Void> activateSocialNetwork(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        socialNetworkService.activate(id);
        return ResponseEntity.ok().build();
    }
    
    @PostMapping("/{id}/deactivate")
    @Operation(summary = "Deactivate a social network", description = "Deactivates a social network")
    public ResponseEntity<Void> deactivateSocialNetwork(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        socialNetworkService.deactivate(id);
        return ResponseEntity.ok().build();
    }
    
    @PostMapping("/{id}/enable-approval")
    @Operation(summary = "Enable approval requirement", description = "Enables approval requirement for a social network")
    public ResponseEntity<Void> enableApproval(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        socialNetworkService.enableApproval(id);
        return ResponseEntity.ok().build();
    }
    
    @PostMapping("/{id}/disable-approval")
    @Operation(summary = "Disable approval requirement", description = "Disables approval requirement for a social network")
    public ResponseEntity<Void> disableApproval(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        socialNetworkService.disableApproval(id);
        return ResponseEntity.ok().build();
    }
    
    @PutMapping("/{id}/sort-order")
    @Operation(summary = "Update sort order", description = "Updates the sort order for a social network")
    public ResponseEntity<Void> updateSortOrder(
            @Parameter(description = "Social Network ID") @PathVariable Long id,
            @Parameter(description = "New sort order") @RequestParam Integer sortOrder) {
        socialNetworkService.updateSortOrder(id, sortOrder);
        return ResponseEntity.ok().build();
    }
    
    @PutMapping("/{id}/api-config")
    @Operation(summary = "Update API configuration", description = "Updates the API configuration for a social network")
    public ResponseEntity<Void> updateApiConfig(
            @Parameter(description = "Social Network ID") @PathVariable Long id,
            @RequestBody String apiConfig) {
        socialNetworkService.updateApiConfig(id, apiConfig);
        return ResponseEntity.ok().build();
    }
    
    @PutMapping("/{id}/rate-limits")
    @Operation(summary = "Update rate limits", description = "Updates the rate limits for a social network")
    public ResponseEntity<Void> updateRateLimits(
            @Parameter(description = "Social Network ID") @PathVariable Long id,
            @RequestBody String rateLimits) {
        socialNetworkService.updateRateLimits(id, rateLimits);
        return ResponseEntity.ok().build();
    }
    
    @PutMapping("/{id}/supported-features")
    @Operation(summary = "Update supported features", description = "Updates the supported features for a social network")
    public ResponseEntity<Void> updateSupportedFeatures(
            @Parameter(description = "Social Network ID") @PathVariable Long id,
            @RequestBody String supportedFeatures) {
        socialNetworkService.updateSupportedFeatures(id, supportedFeatures);
        return ResponseEntity.ok().build();
    }
    
    @DeleteMapping("/{id}")
    @Operation(summary = "Delete a social network", description = "Soft deletes a social network by deactivating it")
    public ResponseEntity<Void> deleteSocialNetwork(
            @Parameter(description = "Social Network ID") @PathVariable Long id) {
        socialNetworkService.delete(id);
        return ResponseEntity.ok().build();
    }
    
    @GetMapping("/stats")
    @Operation(summary = "Get social network statistics", description = "Retrieves various statistics about social networks")
    public ResponseEntity<Map<String, Object>> getSocialNetworkStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalCount", socialNetworkService.getTotalCount());
        stats.put("activeCount", socialNetworkService.getActiveCount());
        stats.put("approvalRequiredCount", socialNetworkService.getApprovalRequiredCount());
        stats.put("productionReadyCount", socialNetworkService.getProductionReadyCount());
        return ResponseEntity.ok(stats);
    }
    
    @GetMapping("/{networkCode}/exists")
    @Operation(summary = "Check if network code exists", description = "Checks if a network code already exists")
    public ResponseEntity<Map<String, Boolean>> checkNetworkCodeExists(
            @Parameter(description = "Network Code") @PathVariable String networkCode) {
        boolean exists = socialNetworkService.existsByNetworkCode(networkCode);
        Map<String, Boolean> response = new HashMap<>();
        response.put("exists", exists);
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/{networkCode}/active-status")
    @Operation(summary = "Check if network is active", description = "Checks if a social network is currently active")
    public ResponseEntity<Map<String, Boolean>> checkNetworkActiveStatus(
            @Parameter(description = "Network Code") @PathVariable String networkCode) {
        boolean isActive = socialNetworkService.isNetworkActive(networkCode);
        Map<String, Boolean> response = new HashMap<>();
        response.put("isActive", isActive);
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/{networkCode}/supports/{feature}")
    @Operation(summary = "Check feature support", description = "Checks if a social network supports a specific feature")
    public ResponseEntity<Map<String, Boolean>> checkFeatureSupport(
            @Parameter(description = "Network Code") @PathVariable String networkCode,
            @Parameter(description = "Feature name") @PathVariable String feature) {
        boolean supports = socialNetworkService.supportsFeature(networkCode, feature);
        Map<String, Boolean> response = new HashMap<>();
        response.put("supports", supports);
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/{networkCode}/rate-limit/{limitType}")
    @Operation(summary = "Get rate limit", description = "Gets the rate limit for a specific network and limit type")
    public ResponseEntity<Map<String, Integer>> getRateLimit(
            @Parameter(description = "Network Code") @PathVariable String networkCode,
            @Parameter(description = "Limit type") @PathVariable String limitType) {
        Integer rateLimit = socialNetworkService.getRateLimit(networkCode, limitType);
        Map<String, Integer> response = new HashMap<>();
        response.put("rateLimit", rateLimit);
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/{networkCode}/validate-config")
    @Operation(summary = "Validate API configuration", description = "Validates the API configuration for a social network")
    public ResponseEntity<Map<String, Boolean>> validateApiConfig(
            @Parameter(description = "Network Code") @PathVariable String networkCode) {
        boolean isValid = socialNetworkService.validateApiConfig(networkCode);
        Map<String, Boolean> response = new HashMap<>();
        response.put("isValid", isValid);
        return ResponseEntity.ok(response);
    }
    
    @PostMapping("/{networkCode}/test-connection")
    @Operation(summary = "Test network connection", description = "Tests the connection to a social network")
    public ResponseEntity<Map<String, Boolean>> testConnection(
            @Parameter(description = "Network Code") @PathVariable String networkCode) {
        boolean connectionSuccessful = socialNetworkService.testConnection(networkCode);
        Map<String, Boolean> response = new HashMap<>();
        response.put("connectionSuccessful", connectionSuccessful);
        return ResponseEntity.ok(response);
    }
}
