package com.social.media.interfaces.web.controller;

import com.social.media.application.socialaccount.command.ConnectSocialAccountCommand;
import com.social.media.application.socialaccount.command.DisconnectSocialAccountCommand;
import com.social.media.application.socialaccount.command.UpdateSocialAccountCommand;
import com.social.media.application.socialaccount.dto.SocialAccountResponseDto;
import com.social.media.application.socialaccount.service.SocialAccountApplicationService;
import com.social.media.interfaces.web.dto.social.*;
import com.social.media.interfaces.web.dto.shared.ApiResponse;
import com.social.media.interfaces.web.dto.shared.PageResponse;
import jakarta.validation.Valid;
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.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * REST Controller for Social Account management
 * Provides CRUD operations and social account specific functionality
 */
@RestController
@RequestMapping("/api/v1/social-accounts")
@CrossOrigin(origins = "*", maxAge = 3600)
public class SocialAccountController {

    private final SocialAccountApplicationService socialAccountApplicationService;

    public SocialAccountController(SocialAccountApplicationService socialAccountApplicationService) {
        this.socialAccountApplicationService = socialAccountApplicationService;
    }

    /**
     * Get all social accounts with pagination and filtering
     */
    @GetMapping
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<PageResponse<SocialAccountResponseDto>>> getAllSocialAccounts(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "createdAt") String sortBy,
            @RequestParam(defaultValue = "desc") String sortDir,
            @RequestParam(required = false) String search,
            @RequestParam(required = false) String platform,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) Boolean active,
            Authentication authentication) {

        try {
            // Get company ID from authentication
            String companyId = extractCompanyId(authentication);
            
            // Create sort object
            Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
            Pageable pageable = PageRequest.of(page, size, sort);

            // Get social accounts for the company with filters
            List<SocialAccountResponseDto> accounts = socialAccountApplicationService
                .getSocialAccountsByCompany(companyId);

            // Apply filters if provided
            if (search != null && !search.trim().isEmpty()) {
                accounts = accounts.stream()
                    .filter(account -> 
                        account.username().toLowerCase().contains(search.toLowerCase()) ||
                        account.displayName().toLowerCase().contains(search.toLowerCase()))
                    .toList();
            }

            if (platform != null) {
                accounts = accounts.stream()
                    .filter(account -> account.socialNetworkId().equals(platform))
                    .toList();
            }

            if (status != null) {
                accounts = accounts.stream()
                    .filter(account -> account.status().equals(status))
                    .toList();
            }

            // Calculate pagination
            int totalElements = accounts.size();
            int totalPages = (int) Math.ceil((double) totalElements / size);
            int startIndex = page * size;
            int endIndex = Math.min(startIndex + size, totalElements);
            
            List<SocialAccountResponseDto> pageContent = accounts.subList(startIndex, endIndex);

            PageResponse<SocialAccountResponseDto> pageResponse = new PageResponse<>(
                pageContent,
                page,
                size,
                totalElements,
                totalPages,
                page == 0,
                endIndex >= totalElements
            );

            return ResponseEntity.ok(ApiResponse.success(pageResponse, "Social accounts retrieved successfully"));

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to retrieve social accounts: " + e.getMessage()));
        }
    }

    /**
     * Get all social accounts (simple list without pagination)
     */
    @GetMapping("/all")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<List<SocialAccountResponseDto>>> getAllSocialAccountsList(
            Authentication authentication) {

        try {
            String companyId = extractCompanyId(authentication);
            List<SocialAccountResponseDto> accounts = socialAccountApplicationService
                .getSocialAccountsByCompany(companyId);

            return ResponseEntity.ok(ApiResponse.success(accounts, "Social accounts list retrieved successfully"));

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to retrieve social accounts: " + e.getMessage()));
        }
    }

    /**
     * Get social account by ID
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> getSocialAccountById(
            @PathVariable String id,
            Authentication authentication) {

        try {
            SocialAccountResponseDto account = socialAccountApplicationService.getSocialAccountById(id);
            
            // Verify the account belongs to the user's company
            String companyId = extractCompanyId(authentication);
            if (!account.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            return ResponseEntity.ok(ApiResponse.success(account, "Social account retrieved successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to retrieve social account: " + e.getMessage()));
        }
    }

    /**
     * Connect a new social account
     */
    @PostMapping("/connect")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> connectSocialAccount(
            @Valid @RequestBody ConnectSocialAccountRequestDto request,
            Authentication authentication) {

        try {
            String companyId = extractCompanyId(authentication);
            String userId = extractUserId(authentication);

            ConnectSocialAccountCommand command = new ConnectSocialAccountCommand(
                userId,
                companyId,
                request.socialNetworkId(),
                request.username(),
                request.accessToken(),
                request.refreshToken(),
                request.tokenType(),
                request.expiresAt(),
                request.scope()
            );

            SocialAccountResponseDto account = socialAccountApplicationService.connectSocialAccount(command);

            return ResponseEntity.status(HttpStatus.CREATED)
                .body(ApiResponse.success(account, "Social account connected successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error("Invalid request: " + e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to connect social account: " + e.getMessage()));
        }
    }

    /**
     * Update social account
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> updateSocialAccount(
            @PathVariable String id,
            @Valid @RequestBody UpdateSocialAccountRequestDto request,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            UpdateSocialAccountCommand command = new UpdateSocialAccountCommand(
                id,
                request.displayName(),
                request.bio(),
                request.location(),
                request.website(),
                request.profilePhotoUrl(),
                request.contactPhone(),
                request.contactEmail(),
                request.category(),
                request.automationConfig(),
                request.responsibleUserId()
            );

            SocialAccountResponseDto account = socialAccountApplicationService.updateSocialAccount(command);

            return ResponseEntity.ok(ApiResponse.success(account, "Social account updated successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error("Invalid request: " + e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to update social account: " + e.getMessage()));
        }
    }

    /**
     * Delete social account
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<Void>> deleteSocialAccount(
            @PathVariable String id,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            DisconnectSocialAccountCommand command = new DisconnectSocialAccountCommand(id);
            socialAccountApplicationService.disconnectSocialAccount(command);

            return ResponseEntity.ok(ApiResponse.success(null, "Social account deleted successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to delete social account: " + e.getMessage()));
        }
    }

    /**
     * Disconnect social account (soft delete)
     */
    @DeleteMapping("/{id}/disconnect")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<Void>> disconnectSocialAccount(
            @PathVariable String id,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            DisconnectSocialAccountCommand command = new DisconnectSocialAccountCommand(id);
            socialAccountApplicationService.disconnectSocialAccount(command);

            return ResponseEntity.ok(ApiResponse.success(null, "Social account disconnected successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to disconnect social account: " + e.getMessage()));
        }
    }

    /**
     * Sync social account data
     */
    @PostMapping("/{id}/sync")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> syncSocialAccount(
            @PathVariable String id,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            // TODO: Implement sync functionality
            // This would typically involve calling external APIs to refresh account data
            SocialAccountResponseDto account = socialAccountApplicationService.getSocialAccountById(id);

            return ResponseEntity.ok(ApiResponse.success(account, "Social account synced successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to sync social account: " + e.getMessage()));
        }
    }

    /**
     * Refresh authentication token
     */
    @PostMapping("/{id}/refresh-token")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> refreshToken(
            @PathVariable String id,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            // TODO: Implement token refresh functionality
            // This would involve calling the platform's token refresh endpoint
            SocialAccountResponseDto account = socialAccountApplicationService.getSocialAccountById(id);

            return ResponseEntity.ok(ApiResponse.success(account, "Token refreshed successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to refresh token: " + e.getMessage()));
        }
    }

    /**
     * Toggle social account status (active/inactive)
     */
    @PutMapping("/{id}/toggle-status")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<SocialAccountResponseDto>> toggleSocialAccountStatus(
            @PathVariable String id,
            Authentication authentication) {

        try {
            // Verify the account belongs to the user's company
            SocialAccountResponseDto existingAccount = socialAccountApplicationService.getSocialAccountById(id);
            String companyId = extractCompanyId(authentication);
            if (!existingAccount.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            // TODO: Implement status toggle functionality
            SocialAccountResponseDto account = socialAccountApplicationService.getSocialAccountById(id);

            return ResponseEntity.ok(ApiResponse.success(account, "Social account status updated successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to update social account status: " + e.getMessage()));
        }
    }

    /**
     * Get authorization URL for connecting account
     */
    @PostMapping("/auth-url")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<AuthUrlResponseDto>> getAuthUrl(
            @Valid @RequestBody GetAuthUrlRequestDto request) {

        try {
            // TODO: Implement OAuth URL generation logic
            // This would typically involve building platform-specific OAuth URLs
            
            String authUrl = "https://api." + request.platform().toLowerCase() + 
                           ".com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=" + 
                           request.redirectUri() + "&scope=read_profile";

            AuthUrlResponseDto response = new AuthUrlResponseDto(authUrl);

            return ResponseEntity.ok(ApiResponse.success(response, "Authorization URL generated successfully"));

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to generate authorization URL: " + e.getMessage()));
        }
    }

    /**
     * Search social accounts
     */
    @GetMapping("/search")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<PageResponse<SocialAccountResponseDto>>> searchSocialAccounts(
            @RequestParam String search,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            Authentication authentication) {

        try {
            String companyId = extractCompanyId(authentication);
            
            // Get all accounts and filter by search term
            List<SocialAccountResponseDto> allAccounts = socialAccountApplicationService
                .getSocialAccountsByCompany(companyId);

            List<SocialAccountResponseDto> filteredAccounts = allAccounts.stream()
                .filter(account -> 
                    account.username().toLowerCase().contains(search.toLowerCase()) ||
                    account.displayName().toLowerCase().contains(search.toLowerCase()))
                .toList();

            // Calculate pagination
            int totalElements = filteredAccounts.size();
            int totalPages = (int) Math.ceil((double) totalElements / size);
            int startIndex = page * size;
            int endIndex = Math.min(startIndex + size, totalElements);
            
            List<SocialAccountResponseDto> pageContent = filteredAccounts.subList(startIndex, endIndex);

            PageResponse<SocialAccountResponseDto> pageResponse = new PageResponse<>(
                pageContent,
                page,
                size,
                totalElements,
                totalPages,
                page == 0,
                endIndex >= totalElements
            );

            return ResponseEntity.ok(ApiResponse.success(pageResponse, "Search results retrieved successfully"));

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to search social accounts: " + e.getMessage()));
        }
    }

    /**
     * Get social account metrics
     */
    @GetMapping("/{id}/metrics")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getSocialAccountMetrics(
            @PathVariable String id,
            Authentication authentication) {

        try {
            SocialAccountResponseDto account = socialAccountApplicationService.getSocialAccountById(id);
            
            // Verify the account belongs to the user's company
            String companyId = extractCompanyId(authentication);
            if (!account.companyId().equals(companyId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("Access denied to this social account"));
            }

            Map<String, Object> metrics = account.accountMetrics();

            return ResponseEntity.ok(ApiResponse.success(metrics, "Social account metrics retrieved successfully"));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error("Social account not found"));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error("Failed to retrieve social account metrics: " + e.getMessage()));
        }
    }

    // Helper methods
    
    private String extractCompanyId(Authentication authentication) {
        // TODO: Implement proper extraction from JWT token
        // For now, return a default value - this should be properly implemented
        return "1";
    }

    private String extractUserId(Authentication authentication) {
        // TODO: Implement proper extraction from JWT token
        // For now, return a default value - this should be properly implemented
        return authentication.getName();
    }
}
