package kz.konturai.parser.service;

import kz.konturai.parser.exception.FacebookTokenExpiredException;
import kz.konturai.parser.exception.LinkedInTokenExpiredException;
import kz.konturai.parser.exception.TelegramTokenExpiredException;
import kz.konturai.parser.model.MarketingStrategy;
import kz.konturai.parser.model.PostingTask;
import kz.konturai.parser.repository.MarketingStrategyRepository;
import kz.konturai.parser.repository.PostingTaskRepository;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class PostingTaskService {

    private static final Logger logger = LoggerFactory.getLogger(PostingTaskService.class);
    private static final String TEST_RECIPIENT_ID = "25769470256007187";

    private final PostingTaskRepository taskRepository;
    private final MarketingStrategyRepository strategyRepository;
    private final SocialMediaCredentialsService credentialsService;
    private final FacebookPostingService facebookPostingService;
    private final LinkedInPostingService linkedInPostingService;
    private final TelegramPostingService telegramPostingService;
    private final MinIOService minIOService;

    public List<PostingTask> createTasksFromStrategy(String strategyId) {
        Optional<MarketingStrategy> optStrategy = strategyRepository.findById(strategyId);
        if (optStrategy.isEmpty()) {
            throw new IllegalArgumentException("Strategy not found: " + strategyId);
        }

        MarketingStrategy strategy = optStrategy.get();

        if (!"completed".equals(strategy.getStatus())) {
            throw new IllegalStateException("Strategy is not completed yet. Status: " + strategy.getStatus());
        }

        if (strategy.getPostCalendar() == null || strategy.getPostCalendar().isEmpty()) {
            logger.warn("Strategy {} has no post calendar items", strategyId);
            return new ArrayList<>();
        }

        List<String> platforms = strategy.getPostCalendar().stream()
                .map(MarketingStrategy.PostCalendarItem::getPlatform)
                .distinct()
                .toList();

        for (String platform : platforms) {
            if ("facebook".equalsIgnoreCase(platform)) {
                continue; // Игнорируем проверку БД, так как Facebook берет ключи из application.properties
            }
            if (!credentialsService.hasCredentials(strategy.getUserId(), platform)) {
                throw new IllegalStateException(
                        "Credentials not found for platform: " + platform + ". Please configure credentials first.");
            }
        }

        List<PostingTask> existingTasks = taskRepository.findByStrategyId(strategyId);
        if (!existingTasks.isEmpty()) {
            logger.info("Tasks already exist for strategy {}. Returning existing tasks.", strategyId);
            return existingTasks;
        }

        List<PostingTask> tasks = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();

        for (MarketingStrategy.PostCalendarItem calendarItem : strategy.getPostCalendar()) {
            PostingTask task = new PostingTask(
                    strategyId,
                    strategy.getUserId(),
                    calendarItem.getPlatform(),
                    calendarItem.getPostText(),
                    calendarItem.getHashtags(),
                    calendarItem.getPublishDate());

            task.setImageUrl(calendarItem.getImageUrl());
            task.setImageFilename(calendarItem.getImageFilename());

            if (task.getPublishDate().isBefore(now) || task.getPublishDate().isEqual(now)) {
                task.setStatus("pending");
            }

            tasks.add(task);
        }

        List<PostingTask> savedTasks = taskRepository.saveAll(tasks);
        logger.info("Created {} posting tasks from strategy {}", savedTasks.size(), strategyId);

        for (PostingTask task : savedTasks) {
            if (task.getPublishDate().isBefore(now) || task.getPublishDate().isEqual(now)) {
                if ("pending".equals(task.getStatus())) {
                    executeTaskAsync(task.getId());
                }
            }
        }

        return savedTasks;
    }

    public List<PostingTask> getPendingTasks(LocalDateTime beforeDate) {
        return taskRepository.findByStatusAndPublishDateLessThanEqual("pending", beforeDate);
    }

    public void executeTask(String taskId) {
        Optional<PostingTask> optTask = taskRepository.findById(taskId);
        if (optTask.isEmpty()) {
            logger.error("Task not found: {}", taskId);
            return;
        }

        PostingTask task = optTask.get();

        if (!"pending".equals(task.getStatus())) {
            logger.warn("Task {} is not in pending status. Current status: {}", taskId, task.getStatus());
            return;
        }

        task.setStatus("processing");
        taskRepository.save(task);

        try {
            String credentials = null;
            if (!"facebook".equalsIgnoreCase(task.getPlatform())) {
                credentials = credentialsService.getCredentials(task.getUserId(), task.getPlatform());
                if (credentials == null || credentials.isEmpty()) {
                    throw new IllegalStateException("Credentials not found for platform: " + task.getPlatform());
                }
            }

            byte[] videoData = null;
            if (task.getVideoFilename() != null && !task.getVideoFilename().isEmpty()) {
                try {
                    java.io.InputStream videoStream = minIOService.downloadFile(task.getVideoFilename());
                    videoData = videoStream.readAllBytes();
                    logger.info("Loaded video for task {}: {} bytes", taskId, videoData.length);
                } catch (Exception e) {
                    logger.warn("Failed to load video for task {}: {}", taskId, e.getMessage());
                }
            }

            byte[] imageData = null;
            if (videoData == null && task.getImageFilename() != null && !task.getImageFilename().isEmpty()) {
                try {
                    java.io.InputStream imageStream = minIOService.downloadFile(task.getImageFilename());
                    imageData = imageStream.readAllBytes();
                } catch (Exception e) {
                    logger.warn("Failed to load image for task {}: {}", taskId, e.getMessage());
                }
            }

            String postId = null;

            if ("facebook".equalsIgnoreCase(task.getPlatform())) {

                if (videoData != null && videoData.length > 0) {
                    logger.info("Publishing Facebook post WITH VIDEO for task {}", taskId);
                    postId = facebookPostingService.postToPageWithVideo(task.getPostText(), task.getHashtags(), videoData);
                } else if (imageData != null && imageData.length > 0) {
                    postId = facebookPostingService.postToPageWithImage(task.getPostText(), task.getHashtags(), imageData);
                } else {
                    postId = facebookPostingService.postToPage(task.getPostText(), task.getHashtags());
                }

                if (postId != null) {
                    try {
                        String reportText = "✅ НОВЫЙ ПОСТ ОПУБЛИКОВАН!\n\n" +
                                "📜 Текст поста:\n" + task.getPostText() + "\n\n" +
                                "🔗 Ссылка: https://facebook.com/" + postId + "\n" +
                                "🕒 Время: " + LocalDateTime.now();

                        facebookPostingService.sendPrivateMessage(TEST_RECIPIENT_ID, reportText);

                        if (imageData != null && imageData.length > 0) {
                            facebookPostingService.sendPrivateImageMessage(TEST_RECIPIENT_ID, imageData);
                        }
                    } catch (Exception msgEx) {
                        logger.warn("Post published but failed to send private notification: {}", msgEx.getMessage());
                    }
                }

            } else if ("linkedin".equalsIgnoreCase(task.getPlatform())) {
                if (imageData != null && imageData.length > 0) {
                    postId = linkedInPostingService.postToLinkedInWithImage(
                            credentials, task.getPostText(), task.getHashtags(), imageData, "image/png");
                } else {
                    postId = linkedInPostingService.postToLinkedIn(
                            credentials, task.getPostText(), task.getHashtags());
                }
            } else if ("telegram".equalsIgnoreCase(task.getPlatform())) {
                if (imageData != null && imageData.length > 0) {
                    postId = telegramPostingService.postToTelegramWithImage(
                            credentials, task.getPostText(), task.getHashtags(), imageData, "image/png");
                } else {
                    postId = telegramPostingService.postToTelegram(
                            credentials, task.getPostText(), task.getHashtags());
                }
            } else {
                throw new UnsupportedOperationException("Platform not supported: " + task.getPlatform());
            }

            task.setStatus("completed");
            task.setExecutedAt(LocalDateTime.now());
            task.setErrorMessage(null);
            taskRepository.save(task);

            logger.info("Task {} executed successfully. Post ID: {}", taskId, postId);

        } catch (FacebookTokenExpiredException e) {
            handleError(task, "Facebook token expired: " + e.getErrorMessage());
        } catch (LinkedInTokenExpiredException e) {
            handleError(task, "LinkedIn token expired: " + e.getErrorMessage());
        } catch (TelegramTokenExpiredException e) {
            handleError(task, "Telegram token expired: " + e.getErrorMessage());
        } catch (Exception e) {
            logger.error("Failed to execute task {}", taskId, e);
            handleError(task, e.getMessage());
        }
    }

    private void handleError(PostingTask task, String message) {
        task.setStatus("failed");
        task.setExecutedAt(LocalDateTime.now());
        task.setErrorMessage(message);
        taskRepository.save(task);
    }

    @Async("reportGenerationExecutor")
    public void executeTaskAsync(String taskId) {
        executeTask(taskId);
    }

    public void executeTaskManually(String taskId) {
        Optional<PostingTask> optTask = taskRepository.findById(taskId);
        if (optTask.isEmpty()) {
            throw new IllegalArgumentException("Task not found: " + taskId);
        }

        PostingTask task = optTask.get();
        String status = task.getStatus();

        if (!"pending".equals(status) && !"failed".equals(status)) {
            throw new IllegalStateException(
                    "Task cannot be executed manually. Current status: " + status);
        }

        if ("failed".equals(status)) {
            task.setStatus("pending");
            task.setErrorMessage(null);
            taskRepository.save(task);
        }

        executeTask(taskId);
    }

    public List<PostingTask> getUserTasks(String userId) {
        return taskRepository.findByUserId(userId);
    }

    public List<PostingTask> getStrategyTasks(String strategyId) {
        return taskRepository.findByStrategyId(strategyId);
    }

    public Optional<PostingTask> getTaskById(String taskId) {
        return taskRepository.findById(taskId);
    }
}