<?php

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Models\Article;
use App\Models\Site;
use App\Models\Topic;
use App\Services\WordPressService;
use App\Helpers\Logger;

class ArticleController extends Controller
{
    public function index(): void
    {
        Auth::requireLogin();

        $page = max(1, (int) ($this->input('page', 1)));
        $selectedSiteId = max(0, (int) $this->input('site_id', 0));
        $perPage = 20;
        $offset = ($page - 1) * $perPage;

        $articles = Article::findAllWithRelations(
            $perPage,
            $offset,
            $selectedSiteId > 0 ? $selectedSiteId : null
        );

        $total = $selectedSiteId > 0
            ? Article::count('site_id = :site_id', ['site_id' => $selectedSiteId])
            : Article::count();

        $totalPages = (int) ceil($total / $perPage);
        $sites = Site::findAll('name ASC');

        $this->view('articles/index', [
            'articles' => $articles,
            'sites' => $sites,
            'selectedSiteId' => $selectedSiteId,
            'page' => $page,
            'totalPages' => $totalPages,
            'total' => $total,
        ]);
    }

    public function show(string $id): void
    {
        Auth::requireLogin();

        $article = Article::findWithRelations((int) $id);
        if (!$article) {
            $this->flash('danger', 'Artykuł nie znaleziony.');
            $this->redirect('/articles');
            return;
        }

        $this->view('articles/show', ['article' => $article]);
    }

    public function importFromWordPress(): void
    {
        Auth::requireLogin();

        $siteId = max(0, (int) $this->input('site_id', 0));
        if ($siteId <= 0) {
            $this->flash('danger', 'Wybierz strone do importu artykulow.');
            $this->redirect('/articles');
            return;
        }

        $site = Site::find($siteId);
        if (!$site) {
            $this->flash('danger', 'Nie znaleziono wybranej strony.');
            $this->redirect('/articles');
            return;
        }

        $topics = Topic::findBySite($siteId);
        $defaultTopicId = $this->resolveImportFallbackTopicId($siteId, $topics);
        if ($defaultTopicId <= 0) {
            $this->flash('danger', 'Nie udalo sie przygotowac tematu dla importu artykulow.');
            $this->redirect('/articles?site_id=' . $siteId);
            return;
        }

        $topicByCategory = [];
        foreach ($topics as $topic) {
            if (!empty($topic['wp_category_id'])) {
                $topicByCategory[(int) $topic['wp_category_id']] = (int) $topic['id'];
            }
        }

        $wp = new WordPressService();
        $posts = $wp->getPublishedPosts($site);
        if ($posts === false) {
            $this->flash('danger', 'Nie udalo sie pobrac artykulow z WordPress.');
            $this->redirect('/articles?site_id=' . $siteId);
            return;
        }
        $uncategorizedIds = $this->resolveUncategorizedCategoryIds($site, $wp);

        $imported = 0;
        $skipped = 0;
        $failed = 0;

        foreach ($posts as $post) {
            $wpPostId = (int) ($post['id'] ?? 0);
            if ($wpPostId <= 0) {
                $skipped++;
                continue;
            }

            if (Article::existsBySiteAndWpPostId($siteId, $wpPostId)) {
                $skipped++;
                continue;
            }

            $topicId = $defaultTopicId;
            $categories = $post['categories'] ?? [];
            $categoryIds = is_array($categories) ? array_map('intval', $categories) : [];
            $categoryIds = array_values(array_filter($categoryIds, function (int $categoryId) use ($uncategorizedIds): bool {
                return $categoryId > 0 && !in_array($categoryId, $uncategorizedIds, true);
            }));

            foreach ($categoryIds as $categoryId) {
                if (isset($topicByCategory[$categoryId])) {
                    $topicId = $topicByCategory[$categoryId];
                    break;
                }
            }

            $rawTitle = (string) ($post['title']['rendered'] ?? '');
            $title = trim(html_entity_decode(strip_tags($rawTitle), ENT_QUOTES | ENT_HTML5, 'UTF-8'));
            if ($title === '') {
                $title = 'WP Post #' . $wpPostId;
            }

            $content = (string) ($post['content']['rendered'] ?? '');
            $postUrl = trim((string) ($post['link'] ?? ''));
            $postDate = (string) ($post['date'] ?? '');
            $publishedAt = $postDate !== '' ? date('Y-m-d H:i:s', strtotime($postDate)) : date('Y-m-d H:i:s');
            if ($publishedAt === '1970-01-01 00:00:00') {
                $publishedAt = date('Y-m-d H:i:s');
            }

            try {
                Article::create([
                    'site_id' => $siteId,
                    'topic_id' => $topicId,
                    'title' => $title,
                    'content' => $content,
                    'wp_post_id' => $wpPostId,
                    'wp_post_url' => $postUrl !== '' ? $postUrl : null,
                    'status' => 'published',
                    'published_at' => $publishedAt,
                ]);

                Topic::incrementArticleCount($topicId);
                $imported++;
            } catch (\Throwable $e) {
                $failed++;
                Logger::error(
                    "Import WP post failed. site_id={$siteId}, wp_post_id={$wpPostId}, error=" . $e->getMessage(),
                    'import'
                );
            }
        }

        if ($imported > 0) {
            $this->flash('success', "Zaimportowano {$imported} artykulow. Pominieto: {$skipped}. Bledy: {$failed}.");
        } else {
            $this->flash('info', "Brak nowych artykulow do importu. Pominieto: {$skipped}. Bledy: {$failed}.");
        }

        $this->redirect('/articles?site_id=' . $siteId);
    }

    private function resolveImportFallbackTopicId(int $siteId, array &$topics): int
    {
        if (!empty($topics)) {
            return (int) $topics[0]['id'];
        }

        $fallbackTopicId = Topic::create([
            'site_id' => $siteId,
            'name' => 'Import z WordPress',
            'description' => 'Temat techniczny dla wpisow importowanych bez mapowania kategorii.',
            'is_active' => 1,
        ]);

        if ($fallbackTopicId > 0) {
            $topics[] = [
                'id' => $fallbackTopicId,
                'wp_category_id' => null,
            ];
        }

        return (int) $fallbackTopicId;
    }

    private function resolveUncategorizedCategoryIds(array $site, WordPressService $wp): array
    {
        $categories = $wp->getCategories($site);
        if (!is_array($categories)) {
            return [];
        }

        $ids = [];
        foreach ($categories as $category) {
            $id = (int) ($category['id'] ?? 0);
            if ($id <= 0) {
                continue;
            }

            $slug = strtolower(trim((string) ($category['slug'] ?? '')));
            $name = strtolower(trim((string) ($category['name'] ?? '')));

            if (in_array($slug, ['uncategorized', 'bez-kategorii'], true)
                || in_array($name, ['uncategorized', 'bez kategorii'], true)
            ) {
                $ids[] = $id;
            }
        }

        return array_values(array_unique($ids));
    }

    public function destroy(string $id): void
    {
        Auth::requireLogin();

        $article = Article::findWithRelations((int) $id);
        if (!$article) {
            $this->flash('danger', 'Artykul nie znaleziony.');
            $this->redirect('/articles');
            return;
        }

        $redirectUrl = '/articles?site_id=' . (int) $article['site_id'];

        if (!empty($article['wp_post_id'])) {
            $site = [
                'url' => $article['site_url'],
                'api_user' => $article['site_api_user'],
                'api_token' => $article['site_api_token'],
            ];

            $wp = new WordPressService();
            if (!$wp->deletePost($site, (int) $article['wp_post_id'])) {
                $this->flash('danger', 'Nie udalo sie usunac artykulu z WordPress. Lokalny wpis nie zostal usuniety.');
                $this->redirect($redirectUrl);
                return;
            }
        }

        $deleted = Article::delete((int) $id);

        if ($deleted && ($article['status'] ?? '') === 'published' && !empty($article['topic_id'])) {
            Topic::decrementArticleCount((int) $article['topic_id']);
        }

        if ($deleted) {
            $this->flash('success', 'Artykul zostal usuniety.');
        } else {
            $this->flash('danger', 'Nie udalo sie usunac artykulu z systemu.');
        }

        $this->redirect($redirectUrl);
    }

    public function replaceImage(string $id): void
    {
        Auth::requireLogin();

        $article = Article::findWithRelations((int) $id);
        if (!$article) {
            $this->json(['success' => false, 'message' => 'Artykuł nie znaleziony.']);
            return;
        }

        if (empty($article['wp_post_id'])) {
            $this->json(['success' => false, 'message' => 'Artykuł nie jest opublikowany w WordPress.']);
            return;
        }

        $site = [
            'url' => $article['site_url'],
            'api_user' => $article['site_api_user'],
            'api_token' => $article['site_api_token'],
        ];

        // Validate uploaded file
        if (empty($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
            $this->json(['success' => false, 'message' => 'Nie przesłano pliku lub wystąpił błąd uploadu.']);
            return;
        }

        $file = $_FILES['image'];
        $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);

        if (!in_array($mimeType, $allowedTypes)) {
            $this->json(['success' => false, 'message' => 'Niedozwolony format pliku. Dozwolone: JPG, PNG, GIF, WebP.']);
            return;
        }

        $imageData = file_get_contents($file['tmp_name']);
        $filename = $file['name'] ?: ('article-' . time() . '.jpg');

        $wp = new WordPressService();

        // 1. Delete old featured image from WP
        $oldMediaId = $wp->getPostFeaturedMedia($site, $article['wp_post_id']);
        if ($oldMediaId) {
            $wp->deleteMedia($site, $oldMediaId);
            Logger::info("Deleted old media ID: {$oldMediaId} for article {$id}", 'image');
        }

        // 2. Upload new image to WP
        $newMediaId = $wp->uploadMedia($site, $imageData, $filename);
        if (!$newMediaId) {
            $this->json(['success' => false, 'message' => 'Nie udało się wgrać zdjęcia do WordPress.']);
            return;
        }

        // 3. Set as featured image on the post
        $updated = $wp->updatePostFeaturedMedia($site, $article['wp_post_id'], $newMediaId);
        if (!$updated) {
            $this->json(['success' => false, 'message' => 'Nie udało się ustawić zdjęcia jako wyróżniającego.']);
            return;
        }

        Logger::info("Replaced image for article {$id}: old={$oldMediaId}, new={$newMediaId}", 'image');

        $this->json([
            'success' => true,
            'message' => 'Zdjęcie zostało podmienione.',
            'media_id' => $newMediaId,
        ]);
    }
}
