package kz.konturai.parser.controller;

import kz.konturai.parser.dto.*;
import kz.konturai.parser.model.*;
import kz.konturai.parser.repository.MarketingAnalysisV3Repository;
import kz.konturai.parser.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/api/marketing/targeting")
@RequiredArgsConstructor
@Slf4j
public class TargetingCampaignController {

    private final TargetingCampaignService campaignService;
    private final AudienceSegmentationService audienceService;
    private final BudgetOptimizerService budgetOptimizerService;
    private final ABTestingService abTestingService;
    private final MarketingAnalysisV3Repository analysisRepository;
    private final SocialMediaCredentialsService credentialsService;
    private final JwtService jwtService;
    private final CampaignPredictionService predictionService;
    private final MarketingStrategyV3Service marketingStrategyV3Service;

    private String resolveUserId(String userIdHeader, String authHeader) {
        if (StringUtils.hasText(userIdHeader)) {
            return userIdHeader;
        }
        try {
            String userId = jwtService.extractUserIdFromHeader(authHeader);
            return userId; // Может быть null если токен истёк
        } catch (Exception e) {
            log.warn("[Targeting] Failed to extract userId from token: {}", e.getMessage());
            return null;
        }
    }

    @PostMapping("/campaigns")
    public ResponseEntity<TargetingCampaign> createCampaign(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestBody TargetingCampaignRequest request) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Create campaign requested by {}", userId);
        return ResponseEntity.ok(campaignService.createCampaign(request, userId));
    }

    @GetMapping("/campaigns")
    public ResponseEntity<Page<TargetingCampaign>> getUserCampaigns(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Get campaigns for {}", userId);
        return ResponseEntity.ok(campaignService.getUserCampaigns(userId, page, size));
    }

    @GetMapping("/campaigns/{id}")
    public ResponseEntity<TargetingCampaign> getCampaign(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Get campaign {} for {}", id, userId);
        return ResponseEntity.ok(campaignService.getCampaignById(id, userId));
    }

    @PostMapping("/campaigns/{id}/pause")
    public ResponseEntity<TargetingCampaign> pauseCampaign(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Pause campaign {}", id);
        return ResponseEntity.ok(campaignService.pauseCampaign(id, userId));
    }

    @PostMapping("/campaigns/{id}/resume")
    public ResponseEntity<TargetingCampaign> resumeCampaign(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Resume campaign {}", id);
        return ResponseEntity.ok(campaignService.resumeCampaign(id, userId));
    }

    @GetMapping("/campaigns/{id}/insights")
    public ResponseEntity<TargetingPerformanceDto> getInsights(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id,
            @RequestParam(defaultValue = "last_7d") String datePreset) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Get insights for campaign {}", id);
        return ResponseEntity.ok(campaignService.getCampaignInsights(id, userId, datePreset));
    }

    @PostMapping("/campaigns/{id}/sync-insights")
    public ResponseEntity<Void> syncInsights(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Force sync insights for campaign {}", id);
        campaignService.getCampaignById(id, userId);
        campaignService.syncInsights(id);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/campaigns/{id}/ab-test/evaluate")
    public ResponseEntity<String> evaluateAbTest(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Evaluate AB Test for {}", id);
        TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
        return ResponseEntity.ok(abTestingService.evaluateABTest(campaign));
    }

    // --- Audience endpoints ---

    @PostMapping("/audience/segment")
    public ResponseEntity<List<AudienceSegmentDto>> segmentAudience(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestBody Map<String, String> body) {
        String analysisId = body.get("analysisId");
        log.info("[Targeting] Segment audience for analysis {}", analysisId);
        MarketingAnalysisV3Document doc = analysisRepository.findById(analysisId).orElseThrow();
        return ResponseEntity.ok(audienceService.segmentAudience(doc));
    }

    @PostMapping("/audience/estimate")
    public ResponseEntity<Map<String, Long>> estimateAudience(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestParam String platform,
            @RequestBody TargetingAudienceProfile profile) {
        log.info("[Targeting] Estimate audience for platform {}", platform);
        return ResponseEntity.ok(audienceService.estimateAudienceSize(profile, platform));
    }

    // --- Budget endpoint ---

    @PostMapping("/budget/optimize")
    public ResponseEntity<BudgetOptimizationDto> optimizeBudget(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestBody Map<String, String> body) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        String campaignId = body.get("campaignId");
        log.info("[Targeting] Optimize budget for campaign {}", campaignId);
        TargetingCampaign campaign = campaignService.getCampaignById(campaignId, userId);
        MarketingAnalysisV3Document doc = analysisRepository.findById(campaign.getAnalysisId()).orElseThrow();
        return ResponseEntity.ok(budgetOptimizerService.optimizeBudget(campaign, doc));
    }

    // --- Account Selection endpoint ---

    @PostMapping("/account/select")
    public ResponseEntity<Void> selectAdAccount(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestBody Map<String, String> body) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        String platform = body.get("platform");
        String adAccountId = body.get("adAccountId");

        log.info("[Targeting] Select ad account {} for platform {} by user {}", adAccountId, platform, userId);
        credentialsService.updateAdAccountId(userId, platform, adAccountId);

        return ResponseEntity.ok().build();
    }

    // ── Polling статуса ───────────────────────────────────────────────────────

    @GetMapping("/campaigns/{id}/status")
    public ResponseEntity<Map<String, Object>> getCampaignStatus(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
        String status = campaign.getStatus();
        boolean isTerminal = "active".equals(status) || "failed".equals(status) || "paused".equals(status);
        java.util.Map<String, Object> response = new java.util.LinkedHashMap<>();
        response.put("id", campaign.getId());
        response.put("status", status);
        response.put("isTerminal", isTerminal);
        response.put("completedAt", campaign.getCompletedAt() != null ? campaign.getCompletedAt().toString() : null);
        response.put("statusHistory", campaign.getStatusHistory() != null ? campaign.getStatusHistory() : List.of());
        return ResponseEntity.ok(response);
    }

    // ── AI Предсказания ───────────────────────────────────────────────────────

    @GetMapping("/campaigns/{id}/prediction")
    public ResponseEntity<?> getPrediction(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        // Проверяем существование кампании и права доступа
        TargetingCampaign campaign = campaignService.getCampaignById(id, userId);

        Optional<CampaignPrediction> predictionOpt = predictionService.getLatest(id);
        if (predictionOpt.isPresent()) {
            return ResponseEntity.ok(predictionOpt.get());
        }

        // Если предсказания еще нет — запускаем генерацию автоматически
        log.info("[Targeting] Prediction missing for campaign {}, triggering auto-generate", id);
        predictionService.generateAsync(campaign);

        return ResponseEntity.accepted().body(Map.of(
                "status", "PROCESSING",
                "message", "Предсказание еще не готово и было запущено автоматически. Попробуйте через 5-10 секунд."));
    }

    @PostMapping("/campaigns/{id}/predict")
    public ResponseEntity<?> triggerPrediction(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
        log.info("[Targeting] Manual predict trigger for campaign {}", id);
        predictionService.generateAsync(campaign);
        return ResponseEntity.accepted().body(Map.of("message", "Генерация предсказания запущена"));
    }

    // ── Инсайты ───────────────────────────────────────────────────────────────

    @GetMapping("/campaigns/{id}/insights/raw")
    public ResponseEntity<?> getRawInsights(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        TargetingCampaign campaign = campaignService.getCampaignById(id, userId);
        return ResponseEntity.ok(campaign.getInsights() != null ? campaign.getInsights() : List.of());
    }

    // ── Retry ─────────────────────────────────────────────────────────────────

    @PostMapping("/campaigns/{id}/retry")
    public ResponseEntity<TargetingCampaign> retryCampaign(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Retry campaign {}", id);
        return ResponseEntity.ok(campaignService.retryCampaign(id, userId));
    }

    // ── Обновление бюджета и аудитории ───────────────────────────────────────

    @PutMapping("/campaigns/{id}/budget")
    public ResponseEntity<TargetingCampaign> updateBudget(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id,
            @RequestBody Map<String, Double> body) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Update budget for campaign {}", id);
        return ResponseEntity.ok(campaignService.updateBudget(id, userId,
                body.get("totalBudget"), body.get("dailyBudget")));
    }

    @PutMapping("/campaigns/{id}/audience")
    public ResponseEntity<TargetingCampaign> updateAudience(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id,
            @RequestBody TargetingAudienceProfile audience) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Update audience for campaign {}", id);
        return ResponseEntity.ok(campaignService.updateAudience(id, userId, audience));
    }

    // ── Direct Facebook Publish ──────────────────────────────────────────────

    @PostMapping("/strategy/{strategyId}/facebook/publish")
    public ResponseEntity<?> publishFirstFacebookPostFromStrategy(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String strategyId) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Direct Facebook publish for strategy {} requested by {}", strategyId, userId);

        try {
            String postId = marketingStrategyV3Service.publishFirstFacebookPost(strategyId);
            return ResponseEntity.ok(Map.of(
                    "success", true,
                    "message", "Пост успешно опубликован в Facebook",
                    "postId", postId));
        } catch (IllegalArgumentException | IllegalStateException e) {
            return ResponseEntity.badRequest().body(Map.of("success", false, "error", e.getMessage()));
        } catch (kz.konturai.parser.exception.FacebookTokenExpiredException e) {
            log.error("Facebook token expired: {}", e.getMessage());
            return ResponseEntity.badRequest().body(Map.of("success", false, "error",
                    "Токен Facebook истёк. Пожалуйста, обновите токен (facebook.page.token) в файле application.properties."));
        } catch (RuntimeException e) {
            if (e.getMessage() != null && e.getMessage().contains("[Facebook] API Error")) {
                log.error("Facebook API Error: {}", e.getMessage());
                if (e.getMessage().contains("publish_actions")) {
                    return ResponseEntity.badRequest().body(Map.of("success", false, "error",
                            "Указан токен Пользователя, а не Страницы (User Token). Facebook запрещает публикацию через личные токены. Сгенерируйте именно Page Access Token."));
                }
                return ResponseEntity.badRequest()
                        .body(Map.of("success", false, "error", "Ошибка со стороны Facebook API: " + e.getMessage()));
            }
            log.error("Failed to publish post: ", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
        } catch (Exception e) {
            log.error("Failed to publish post: ", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of("success", false, "error", "Не удалось опубликовать пост"));
        }
    }

    // ── AdSets ───────────────────────────────────────────────────────────────

    @GetMapping("/campaigns/{id}/adsets")
    public ResponseEntity<List<TargetingAdSet>> getAdSets(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        return ResponseEntity.ok(campaignService.getAdSets(id, userId));
    }

    @PutMapping("/campaigns/{id}/adsets/{adSetId}")
    public ResponseEntity<TargetingCampaign> updateAdSet(
            @RequestHeader(value = "X-User-Id", required = false) String userIdHeader,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @PathVariable String id,
            @PathVariable String adSetId,
            @RequestBody TargetingAdSet adSet) {
        String userId = resolveUserId(userIdHeader, authHeader);
        if (userId == null)
            return unauthorizedResponse();
        log.info("[Targeting] Update adSet {} for campaign {}", adSetId, id);
        return ResponseEntity.ok(campaignService.updateAdSet(id, adSetId, userId, adSet));
    }

    // ── Helper methods ───────────────────────────────────────────────────────

    @SuppressWarnings("unchecked")
    private <T> ResponseEntity<T> unauthorizedResponse() {
        return (ResponseEntity<T>) ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body(ApiResponse.error(
                        "Не авторизован",
                        new ErrorResponse("UNAUTHORIZED", "Требуется авторизация. Предоставьте валидный JWT токен.")));
    }

    @SuppressWarnings("unchecked")
    private <T> ResponseEntity<T> forbiddenResponse() {
        return (ResponseEntity<T>) ResponseEntity.status(HttpStatus.FORBIDDEN)
                .body(ApiResponse.error(
                        "Доступ запрещён",
                        new ErrorResponse("FORBIDDEN", "У вас нет прав для доступа к этому ресурсу.")));
    }
}
