<?php

namespace App\Http\Controllers\Api;

use App\Exports\EntryTablesExport;
use App\Http\Controllers\Controller;
use App\Models\GenericBackoffice\Entry;
use App\Http\Requests\Api\BaseShow;
use App\Http\Resources\Entries;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;

class EntryController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @param Entry $request
     * @return JsonResource|JsonResponse
     */


    public function index(Entry $request)
    {
        $query = Entry::full()
            ->select('slug')
            ->where('status', 'published')
            ->orderBy('website_objects.website_object_id', 'desc');


        $entry = $query->get();
        if ($entry) {
            return $entry;
        }
        return response()->json([], 404);

    }

    /**
     * Display the specified resource.
     *
     * @param BaseShow $request
     * @return JsonResource|JsonResponse
     */
    public function show(BaseShow $request)
    {
        $userData = Auth::user();
        $data = $request->validated();
        $query = Entry::full()
            ->select('*')
            ->where('status', 'published')
            ->where('lang_slug', $data['slug'])
            ->orderBy('position', 'asc');

        $query->with([
            'blocks' => function ($query) use ($userData) {
                $query
                    ->full()
                    ->with(['documentLists' => function ($query) use ($userData) {
                        $query
                            ->full()
                            ->where('status', 'published')
                            ->with(['documents' => function ($query) use ($userData) {
                                $query->full()
                                    ->where('status', 'published')
                                    ->where(function ($query) {
                                        $query->where('publish_date', '<=', now()->tz('Europe/Berlin'));
                                    })->where(function ($query) {
                                        $query->whereNull('expiration_date')
                                            ->orWhere('expiration_date', '>', now()->tz('Europe/Berlin'));
                                    })
                                    ->join('committees', 'committees.id', 'documents.committee_id')
                                    ->where(function ($query) use ($userData) {
                                        $query->where('committees.type', 'standard');

                                        if ($userData->member->legal_committee) {
                                            $query->orWhere('committees.type', 'legalCommittee');
                                        }

                                        $hasLegalOpinionsPermission = $userData->member->user_permission_level
                                            ? $userData->legal_opinion_permission
                                            : $userData->member->legal_opinions;

                                        if ($hasLegalOpinionsPermission) {
                                            $query->orWhere('committees.type', 'legalOpinions');
                                        }

                                        $hasFinanceSubCommitteePermission = $userData->finance_sub_committee_permission;
                                        if ($hasFinanceSubCommitteePermission) {
                                            $query->orWhere('committees.type', 'financeSubCommittee');
                                        }
                                    })
                                    ->orderBy('publish_date', 'desc');
                            }])
                            ->orderBy('pivot_position', 'asc');
                    }])
                    ->where('status', 'published')
                    ->orderBy('entry_block.position', 'asc');
            }
        ]);

        $entry = $query->first();

        if ($entry) {
            return new Entries($entry);
        }
        return response()->json([], 404);
    }

    /**
     * Export the entry's table editor blocks as a PDF.
     *
     * @param BaseShow $request
     * @return \Illuminate\Http\Response|JsonResponse
     */
    public function exportPdf(BaseShow $request)
    {
        $data  = $request->validated();
        $entry = $this->findPublishedEntryWithTableBlocks($data['slug']);

        if (!$entry) {
            return response()->json(['error' => 'Entry not found.'], 404);
        }

        $tables = $this->extractTableHtmlFromEntry($entry);

        if (empty($tables)) {
            return response()->json(['error' => 'No tables found for this page.'], 404);
        }

        $baseName = $this->buildBaseFileName($entry->title);

        return PDF::loadView('pdf.entry-tables', [
            'title'    => $entry->title,
            'subtitle' => $data['subtitle'] ?? null,
            'tables'   => $tables,
        ])->download($baseName . '.pdf');
    }

    /**
     * Export the entry's table editor blocks as an Excel file.
     *
     * @param BaseShow $request
     * @return \Illuminate\Http\Response|JsonResponse
     */
    public function exportExcel(BaseShow $request)
    {
        $data  = $request->validated();
        $entry = $this->findPublishedEntryWithTableBlocks($data['slug']);

        if (!$entry) {
            return response()->json(['error' => 'Entry not found.'], 404);
        }

        $tables = $this->extractTableHtmlFromEntry($entry);

        if (empty($tables)) {
            return response()->json(['error' => 'No tables found for this page.'], 404);
        }

        $baseName    = $this->buildBaseFileName($entry->title);
        $htmlSources = [];
        foreach ($entry->blocks as $block) {
            $htmlSources[] = (string) $block->wysiwyg;
        }

        return Excel::download(
            new EntryTablesExport($htmlSources, $entry->title, $data['subtitle'] ?? null),
            $baseName . '.xlsx'
        );
    }

    /**
     * Load a published entry by slug, eager loading only its published
     * blockTableEditor blocks (ordered by entry_block position).
     */
    private function findPublishedEntryWithTableBlocks(string $slug): ?Entry
    {
        return Entry::full()
            ->select('*')
            ->where('status', 'published')
            ->where('lang_slug', $slug)
            ->with(['blocks' => function ($query) {
                $query->full()
                    ->where('status', 'published')
                    ->where('type', 'blockTableEditor')
                    ->orderBy('entry_block.position', 'asc');
            }])
            ->first();
    }

    /**
     * Extract HTML <table> markup from blockTableEditor wysiwyg content.
     *
     * @return string[] Array of <table>...</table> HTML strings.
     */
    private function extractTableHtmlFromEntry(Entry $entry): array
    {
        $tables = [];

        foreach ($entry->blocks as $block) {
            $html = (string)$block->wysiwyg;
            if ($html === '') {
                continue;
            }

            if (preg_match_all('/<table\b[^>]*>.*?<\/table>/is', $html, $matches)) {
                foreach ($matches[0] as $tableHtml) {
                    $tables[] = $tableHtml;
                }
            }
        }

        return $tables;
    }

    private function buildBaseFileName(string $title): string
    {
        $slug = strtolower(preg_replace('/[^A-Za-z0-9]+/', '_', $title));
        $slug = trim($slug, '_');
        return $slug !== '' ? $slug . '_tables' : 'page_tables';
    }
}
