<?php
namespace admin\Controllers;

use Domain\Article\ArticleRepository;
use Domain\Languages\LanguagesRepository;
use Domain\Layouts\LayoutsRepository;
use Domain\Pages\PagesRepository;
use admin\ViewModels\Forms\FormAction;
use admin\ViewModels\Forms\FormEditViewModel;
use admin\ViewModels\Forms\FormField;
use admin\ViewModels\Forms\FormTab;

class ArticlesController
{
    private ArticleRepository $repository;
    private LanguagesRepository $languagesRepository;
    private LayoutsRepository $layoutsRepository;
    private PagesRepository $pagesRepository;

    public function __construct(
        ArticleRepository $repository,
        LanguagesRepository $languagesRepository,
        LayoutsRepository $layoutsRepository,
        PagesRepository $pagesRepository
    )
    {
        $this->repository = $repository;
        $this->languagesRepository = $languagesRepository;
        $this->layoutsRepository = $layoutsRepository;
        $this->pagesRepository = $pagesRepository;
    }

    /**
     * Lista artykulow
     */
    public function list(): string
    {
        $sortableColumns = ['title', 'status', 'date_add', 'date_modify'];

        $filterDefinitions = [
            [
                'key' => 'title',
                'label' => 'Tytul',
                'type' => 'text',
            ],
            [
                'key' => 'status',
                'label' => 'Aktywny',
                'type' => 'select',
                'options' => [
                    '' => '- aktywny -',
                    '1' => 'tak',
                    '0' => 'nie',
                ],
            ],
        ];

        $listRequest = \admin\Support\TableListRequestFactory::fromRequest(
            $filterDefinitions,
            $sortableColumns,
            'date_add'
        );

        $result = $this->repository->listForAdmin(
            $listRequest['filters'],
            $listRequest['sortColumn'],
            $listRequest['sortDir'],
            $listRequest['page'],
            $listRequest['perPage']
        );

        $articleIds = [];
        foreach ($result['items'] as $item) {
            $id = (int)($item['id'] ?? 0);
            if ($id > 0) {
                $articleIds[] = $id;
            }
        }
        $pagesSummary = $this->repository->pagesSummaryForArticles($articleIds);

        $rows = [];
        $lp = ($listRequest['page'] - 1) * $listRequest['perPage'] + 1;
        foreach ($result['items'] as $item) {
            $id = (int)$item['id'];
            $title = (string)($item['title'] ?? '');
            $pages = (string)($pagesSummary[$id] ?? '');

            $rows[] = [
                'lp' => $lp++ . '.',
                'title' => '<a href="/admin/articles/edit/id=' . $id . '">' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '</a>'
                    . '<small class="text-muted">' . htmlspecialchars($pages, ENT_QUOTES, 'UTF-8') . '</small>',
                'status' => ((int)$item['status'] === 1) ? 'tak' : '<span style="color: #FF0000;">nie</span>',
                'date_add' => !empty($item['date_add']) ? date('Y-m-d H:i', strtotime((string)$item['date_add'])) : '-',
                'date_modify' => !empty($item['date_modify']) ? date('Y-m-d H:i', strtotime((string)$item['date_modify'])) : '-',
                'user' => htmlspecialchars((string)($item['user'] ?? ''), ENT_QUOTES, 'UTF-8'),
                '_actions' => [
                    [
                        'label' => 'Edytuj',
                        'url' => '/admin/articles/edit/id=' . $id,
                        'class' => 'btn btn-xs btn-primary',
                    ],
                    [
                        'label' => 'Usun',
                        'url' => '/admin/articles/delete/id=' . $id,
                        'class' => 'btn btn-xs btn-danger',
                        'confirm' => 'Na pewno chcesz usunac wybrany element?',
                    ],
                ],
            ];
        }

        $total = (int)$result['total'];
        $totalPages = max(1, (int)ceil($total / $listRequest['perPage']));

        $viewModel = new \admin\ViewModels\Common\PaginatedTableViewModel(
            [
                ['key' => 'lp', 'label' => 'Lp.', 'class' => 'text-center', 'sortable' => false],
                ['key' => 'title', 'sort_key' => 'title', 'label' => 'Tytul', 'sortable' => true, 'raw' => true],
                ['key' => 'status', 'sort_key' => 'status', 'label' => 'Aktywny', 'class' => 'text-center', 'sortable' => true, 'raw' => true],
                ['key' => 'date_add', 'sort_key' => 'date_add', 'label' => 'Data dodania', 'class' => 'text-center', 'sortable' => true],
                ['key' => 'date_modify', 'sort_key' => 'date_modify', 'label' => 'Data modyfikacji', 'class' => 'text-center', 'sortable' => true],
                ['key' => 'user', 'sort_key' => 'user', 'label' => 'Modyfikowany przez', 'class' => 'text-center', 'sortable' => true],
            ],
            $rows,
            $listRequest['viewFilters'],
            [
                'column' => $listRequest['sortColumn'],
                'dir' => $listRequest['sortDir'],
            ],
            [
                'page' => $listRequest['page'],
                'per_page' => $listRequest['perPage'],
                'total' => $total,
                'total_pages' => $totalPages,
            ],
            array_merge($listRequest['queryFilters'], [
                'sort' => $listRequest['sortColumn'],
                'dir' => $listRequest['sortDir'],
                'per_page' => $listRequest['perPage'],
            ]),
            $listRequest['perPageOptions'],
            $sortableColumns,
            '/admin/articles/list/',
            'Brak danych w tabeli.',
            '/admin/articles/edit/',
            'Dodaj artykul'
        );

        return \Shared\Tpl\Tpl::view('articles/articles-list', [
            'viewModel' => $viewModel,
        ]);
    }

    /**
     * Zapis kolejnosci galerii (AJAX)
     */
    public function galleryOrderSave(): void
    {
        if ($this->repository->saveGalleryOrder((int)\Shared\Helpers\Helpers::get('article_id'), (string)\Shared\Helpers\Helpers::get('order'))) {
            echo json_encode(['status' => 'ok', 'msg' => 'Artykul zostal zapisany.']);
        }

        exit;
    }

    /**
     * Zapis kolejnosci zalacznikow (AJAX)
     */
    public function filesOrderSave(): void
    {
        if ($this->repository->saveFilesOrder((int)\Shared\Helpers\Helpers::get('article_id'), (string)\Shared\Helpers\Helpers::get('order'))) {
            echo json_encode(['status' => 'ok', 'msg' => 'Artykul zostal zapisany.']);
        }

        exit;
    }

    /**
     * Zapis artykulu (AJAX)
     */
    public function save(): void
    {
        global $user;

        $values = $this->resolveSavePayload();
        $articleId = (int)($values['id'] ?? \Shared\Helpers\Helpers::get('id') ?? 0);
        $id = $this->repository->save($articleId, $values, (int)$user['id']);

        if ($id) {
            echo json_encode([
                'success' => true,
                'status' => 'ok',
                'message' => 'Artykul zostal zapisany.',
                'msg' => 'Artykul zostal zapisany.',
                'id' => (int)$id,
            ]);
            exit;
        }

        echo json_encode([
            'success' => false,
            'status' => 'error',
            'message' => 'Podczas zapisywania artykulu wystapil blad. Prosze sprobowac ponownie.',
            'msg' => 'Podczas zapisywania artykulu wystapil blad. Prosze sprobowac ponownie.',
        ]);
        exit;
    }

    public function imageAltChange(): void
    {
        $response = ['status' => 'error', 'msg' => 'Podczas zmiany atrybutu alt zdjecia wystapil blad. Prosze sprobowac ponownie.'];

        if ($this->repository->updateImageAlt((int)\Shared\Helpers\Helpers::get('image_id'), (string)\Shared\Helpers\Helpers::get('image_alt'))) {
            $response = ['status' => 'ok'];
        }

        echo json_encode($response);
        exit;
    }

    public function fileNameChange(): void
    {
        $response = ['status' => 'error', 'msg' => 'Podczas zmiany nazwy zalacznika wystapil blad. Prosze sprobowac ponownie.'];

        if ($this->repository->updateFileName((int)\Shared\Helpers\Helpers::get('file_id'), (string)\Shared\Helpers\Helpers::get('file_name'))) {
            $response = ['status' => 'ok'];
        }

        echo json_encode($response);
        exit;
    }

    public function imageDelete(): void
    {
        $response = ['status' => 'error', 'msg' => 'Podczas usuwania zdjecia wystapil blad. Prosze sprobowac ponownie.'];

        if ($this->repository->markImageToDelete((int)\Shared\Helpers\Helpers::get('image_id'))) {
            $response = ['status' => 'ok'];
        }

        echo json_encode($response);
        exit;
    }

    public function fileDelete(): void
    {
        $response = ['status' => 'error', 'msg' => 'Podczas usuwania zalacznika wystapil blad. Prosze sprobowac ponownie.'];

        if ($this->repository->markFileToDelete((int)\Shared\Helpers\Helpers::get('file_id'))) {
            $response = ['status' => 'ok'];
        }

        echo json_encode($response);
        exit;
    }

    /**
     * Archiwizacja artykulu (ustawia status = -1)
     */
    public function delete(): void
    {
        if ($this->repository->archive((int)\Shared\Helpers\Helpers::get('id'))) {
            \Shared\Helpers\Helpers::alert('Artykul zostal przeniesiony do archiwum.');
        }

        header('Location: /admin/articles/list/');
        exit;
    }

    /**
     * Edycja artykulu
     */
    public function edit(): string
    {
        global $user;

        if (!$user) {
            header('Location: /admin/');
            exit;
        }

        $this->repository->deleteNonassignedImages();
        $this->repository->deleteNonassignedFiles();

        $article = $this->repository->find((int)\Shared\Helpers\Helpers::get('id')) ?: ['id' => 0, 'languages' => [], 'images' => [], 'files' => [], 'pages' => []];
        $languages = $this->languagesRepository->languagesList();
        $menus = $this->pagesRepository->menusList();
        $layouts = $this->layoutsRepository->listAll();

        $viewModel = $this->buildFormViewModel($article, $languages, $menus, $layouts);

        return \Shared\Tpl\Tpl::view('articles/article-edit', [
            'form' => $viewModel,
            'article' => $article,
            'user' => $user,
        ]);
    }

    private function resolveSavePayload(): array
    {
        $legacyValuesRaw = \Shared\Helpers\Helpers::get('values');
        if ($legacyValuesRaw !== null && $legacyValuesRaw !== '') {
            $legacyValues = json_decode((string)$legacyValuesRaw, true);
            if (is_array($legacyValues)) {
                return $legacyValues;
            }
        }

        $payload = $_POST;
        unset($payload['_form_id']);

        return is_array($payload) ? $payload : [];
    }

    private function buildFormViewModel(array $article, array $languages, array $menus, array $layouts): FormEditViewModel
    {
        $articleId = (int)($article['id'] ?? 0);
        $defaultLanguageId = (string)($this->languagesRepository->defaultLanguageId() ?? 'pl');
        $title = $articleId > 0
            ? 'Edycja artykulu: <u>' . $this->escapeHtml((string)($article['languages'][$defaultLanguageId]['title'] ?? '')) . '</u>'
            : 'Edycja artykulu';

        $layoutOptions = ['' => '---- szablon domyslny ----'];
        foreach ($layouts as $layout) {
            $layoutOptions[(string)$layout['id']] = (string)$layout['name'];
        }

        $copyFromOptions = ['' => '---- wersja jezykowa ----'];
        foreach ($languages as $language) {
            if (!empty($language['id'])) {
                $copyFromOptions[(string)$language['id']] = (string)$language['name'];
            }
        }

        $tabs = [
            new FormTab('content', 'Tresc', 'fa-file'),
            new FormTab('settings', 'Ustawienia', 'fa-wrench'),
            new FormTab('seo', 'SEO', 'fa-globe'),
            new FormTab('display', 'Wyswietlanie', 'fa-share-alt'),
            new FormTab('gallery', 'Galeria', 'fa-file-image-o'),
            new FormTab('files', 'Zalaczniki', 'fa-file-archive-o'),
        ];

        $fields = [
            FormField::hidden('id', $articleId),
            FormField::langSection('article_content', 'content', [
                FormField::select('copy_from', [
                    'label' => 'Wyswietlaj tresc z wersji',
                    'options' => $copyFromOptions,
                ]),
                FormField::text('title', [
                    'label' => 'Tytul',
                    'required' => true,
                    'attributes' => ['id' => 'title'],
                ]),
                FormField::image('main_image', [
                    'label' => 'Zdjecie tytulowe',
                    'filemanager' => true,
                    'attributes' => ['id' => 'main_image'],
                ]),
                FormField::editor('entry', [
                    'label' => 'Wstep',
                    'toolbar' => 'MyToolbar',
                    'height' => 250,
                    'attributes' => ['id' => 'entry'],
                ]),
                FormField::editor('text', [
                    'label' => 'Tresc',
                    'toolbar' => 'MyToolbar',
                    'height' => 250,
                    'attributes' => ['id' => 'text'],
                ]),
                FormField::editor('table_of_contents', [
                    'label' => 'Spis tresci',
                    'toolbar' => 'MyToolbar',
                    'height' => 250,
                    'attributes' => ['id' => 'table_of_contents'],
                ]),
            ]),
            FormField::switch('status', ['label' => 'Opublikowany', 'tab' => 'settings', 'value' => ((int)($article['status'] ?? 0) === 1) || $articleId === 0]),
            FormField::switch('show_title', ['label' => 'Pokaz tytul', 'tab' => 'settings', 'value' => (int)($article['show_title'] ?? 0) === 1]),
            FormField::switch('show_table_of_contents', ['label' => 'Pokaz spis tresci', 'tab' => 'settings', 'value' => (int)($article['show_table_of_contents'] ?? 0) === 1]),
            FormField::switch('show_date_add', ['label' => 'Pokaz date dodania', 'tab' => 'settings', 'value' => (int)($article['show_date_add'] ?? 0) === 1]),
            FormField::switch('show_date_modify', ['label' => 'Pokaz date modyfikacji', 'tab' => 'settings', 'value' => (int)($article['show_date_modify'] ?? 0) === 1]),
            FormField::switch('repeat_entry', ['label' => 'Powtorz wprowadzenie', 'tab' => 'settings', 'value' => (int)($article['repeat_entry'] ?? 0) === 1]),
            FormField::switch('social_icons', ['label' => 'Linki do portali spolecznosciowych', 'tab' => 'settings', 'value' => (int)($article['social_icons'] ?? 0) === 1]),
            FormField::langSection('article_seo', 'seo', [
                FormField::text('seo_link', ['label' => 'Link SEO', 'attributes' => ['id' => 'seo_link']]),
                FormField::text('meta_title', ['label' => 'Meta title']),
                FormField::textarea('meta_description', ['label' => 'Meta description', 'rows' => 4]),
                FormField::textarea('meta_keywords', ['label' => 'Meta keywords', 'rows' => 4]),
                FormField::switch('noindex', ['label' => 'Blokuj indeksacje']),
                FormField::switch('block_direct_access', ['label' => 'Blokuj bezposredni dostep']),
            ]),
            FormField::select('layout_id', [
                'label' => 'Szablon',
                'tab' => 'display',
                'options' => $layoutOptions,
                'value' => $article['layout_id'] ?? '',
            ]),
            FormField::custom('pages_tree', $this->renderPagesTree($menus, $article), ['tab' => 'display']),
            FormField::custom('images_box', $this->renderImagesBox($article), ['tab' => 'gallery']),
            FormField::custom('files_box', $this->renderFilesBox($article), ['tab' => 'files']),
        ];

        $actions = [
            FormAction::save('/admin/articles/save/' . ($articleId > 0 ? 'id=' . $articleId : ''), '/admin/articles/list/'),
            FormAction::cancel('/admin/articles/list/'),
        ];

        return new FormEditViewModel(
            'article-edit',
            $title,
            $article,
            $fields,
            $tabs,
            $actions,
            'POST',
            '/admin/articles/save/' . ($articleId > 0 ? 'id=' . $articleId : ''),
            '/admin/articles/list/',
            true,
            ['id' => $articleId],
            $languages
        );
    }

    private function renderPagesTree(array $menus, array $article): string
    {
        $html = '<div class="form-group row">';
        $html .= '<label class="col-lg-4 control-label">Wyswietlaj na:</label>';
        $html .= '<div class="col-lg-8">';

        foreach ($menus as $menu) {
            $menuId = (int)($menu['id'] ?? 0);
            $menuName = $this->escapeHtml((string)($menu['name'] ?? ''));
            $menuStatus = (int)($menu['status'] ?? 0);
            $menuPages = $this->pagesRepository->menuPages($menuId);

            $html .= '<div class="menu_sortable">';
            $html .= '<ol class="sortable" id="sortable_' . $menuId . '">';
            $html .= '<li id="list_' . $menuId . '" class="menu_' . $menuId . '" menu="' . $menuId . '">';
            $html .= '<div class="context_0 content content_menu"' . ($menuStatus ? '' : ' style="color: #cc0000;"') . '>';
            $html .= '<button type="button" class="disclose layout-tree-toggle" aria-expanded="false" title="Rozwin / zwin">'
                . '<i class="fa fa-caret-right"></i>'
                . '</button>Menu: <b>' . $menuName . '</b>';
            $html .= '</div>';
            $html .= \Shared\Tpl\Tpl::view('articles/subpages-list', [
                'pages' => $menuPages,
                'article_pages' => $article['pages'] ?? [],
                'parent_id' => $menuId,
                'step' => 1,
            ]);
            $html .= '</li></ol></div>';
        }

        $html .= '</div><div class="clear"></div></div>';

        return $html;
    }

    private function renderImagesBox(array $article): string
    {
        $html = '<ul id="images-list">';
        $images = is_array($article['images'] ?? null) ? $article['images'] : [];
        foreach ($images as $img) {
            $id = (int)($img['id'] ?? 0);
            $src = $this->escapeHtml((string)($img['src'] ?? ''));
            $alt = $this->escapeHtml((string)($img['alt'] ?? ''));

            $html .= '<li id="image-' . $id . '">';
            $html .= '<img class="article-image lozad" data-src="/libraries/thumb.php?img=' . $src . '&w=300&h=300">';
            $html .= '<a href="#" class="input-group-addon btn btn-danger article_image_delete" image-id="' . $id . '"><i class="fa fa-trash"></i></a>';
            $html .= '<input type="text" class="form-control image-alt" value="' . $alt . '" image-id="' . $id . '" placeholder="atrybut alt...">';
            $html .= '</li>';
        }
        $html .= '</ul><div id="images-uploader">You browser doesn\'t have Flash installed.</div>';

        return $html;
    }

    private function renderFilesBox(array $article): string
    {
        $html = '<ul id="files-list">';
        $files = is_array($article['files'] ?? null) ? $article['files'] : [];
        foreach ($files as $file) {
            $id = (int)($file['id'] ?? 0);
            $src = (string)($file['src'] ?? '');
            $name = trim((string)($file['name'] ?? ''));
            if ($name === '') {
                $parts = explode('/', $src);
                $name = (string)end($parts);
            }
            $name = $this->escapeHtml($name);

            $html .= '<li id="file-' . $id . '"><div class="input-group">';
            $html .= '<input type="text" class="article_file_edit form-control" file_id="' . $id . '" value="' . $name . '" />';
            $html .= '<a href="#" class="input-group-addon btn btn-info article_file_delete" file_id="' . $id . '"><i class="fa fa-trash"></i></a>';
            $html .= '</div></li>';
        }
        $html .= '</ul><div id="files-uploader">You browser doesn\'t have Flash installed.</div>';

        return $html;
    }

    private function escapeHtml(string $value): string
    {
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }
}
