<?php

namespace App\Http\Controllers;

use App\DashboardRepository;
use App\Facades\Feature;
use App\Facades\Reports;
use App\Facades\Settings;
use App\Reporting\Repositories\CRMReportRepository;
use App\Support\Period;
use Carbon\Carbon;
use App\FranchiseRepository;
use App\Http\Requests\SetDashboardWidgetsRequest;
use App\Http\Resources\BulkImportLogList;
use App\Http\Resources\GlobalContentElementList;
use App\Http\Resources\PageListResource;
use App\Http\Resources\PinnedItemResource;
use App\Http\Resources\VersionListResource;
use App\IntegrationRepository;
use App\Models\BulkImportLog;
use App\Reporting\PropertyCountTile;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Mtc\ContentManager\Http\Resources\MediaListResource;
use Mtc\ContentManager\Models\Version;
use Mtc\MercuryDataModels\GlobalContent;
use App\Http\Resources\EnquiryList;
use App\Http\Resources\FormList;
use Mtc\MercuryDataModels\Enquiry;
use Mtc\MercuryDataModels\Form;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\Page;
use Mtc\MercuryDataModels\PropertyCategory;
use Mtc\PinnedItems\Facades\PinnedItems;

class DashboardController extends Controller
{
    /**
     * View Dashboard data (kpis/stats/top items)
     *
     * @return array
     */
    public function index(DashboardRepository $repository)
    {
        return $repository->load(Auth::user(), 'home');
    }

    public function graph(Request $request, DashboardRepository $repository): array
    {
        return $repository->loadChartData([
            'date_range' => $request->input('date_range'),
            'metrics' => $request->input('metrics'),
            'from_date' => $request->input('from_date'),
            'to_date' => $request->input('to_date'),
        ]);
    }

    public function enquiriesByType(Request $request, CRMReportRepository $repository): array
    {
        $from = $request->filled('from_date')
            ? Carbon::parse($request->input('from_date'))->startOfDay()
            : Carbon::now()->subDays(30)->startOfDay();
        $to = $request->filled('to_date')
            ? Carbon::parse($request->input('to_date'))->endOfDay()
            : Carbon::now()->endOfDay();

        // typeBreakdown appends a "Total" summary row that is not a chart slice.
        $breakdown = $repository->typeBreakdown($from, $to)
            ->reject(fn ($row) => $row['type'] === __('labels.total'))
            ->values();

        return [
            'status' => 'ok',
            'labels' => $breakdown->pluck('type'),
            'data' => $breakdown->pluck('enquiry_count'),
        ];
    }

    public function rangeKpis(Request $request): array
    {
        $period = Period::create(
            $request->filled('from_date')
                ? Carbon::parse($request->input('from_date'))->startOfDay()
                : Carbon::now()->subDays(30)->startOfDay(),
            $request->filled('to_date')
                ? Carbon::parse($request->input('to_date'))->endOfDay()
                : Carbon::now()->endOfDay(),
        );

        return collect(config('dashboard.range_kpis', []))
            ->filter(fn ($feature) => empty($feature) || Feature::isEnabled($feature))
            ->keys()
            ->map(fn ($widget) => config("reports.kpis.$widget"))
            ->filter()
            ->map(fn ($class) => app($class)->forPeriod($period)->toArray())
            ->values()
            ->all();
    }

    public function popular(Request $request, DashboardRepository $repository): array
    {
        $from = $request->filled('from_date')
            ? Carbon::parse($request->input('from_date'))->startOfDay()
            : Carbon::now()->subDays(30)->startOfDay();
        $to = $request->filled('to_date')
            ? Carbon::parse($request->input('to_date'))->endOfDay()
            : Carbon::now()->endOfDay();

        return $repository->popularData($from, $to);
    }

    public function enquiriesByUtm(Request $request, CRMReportRepository $repository): array
    {
        $dimension = $repository->resolveDimension($request->input('dimension'));
        $from = $request->filled('from_date')
            ? Carbon::parse($request->input('from_date'))->startOfDay()
            : Carbon::now()->subDays(30)->startOfDay();
        $to = $request->filled('to_date')
            ? Carbon::parse($request->input('to_date'))->endOfDay()
            : Carbon::now()->endOfDay();

        $breakdown = $repository->utmBreakdown($dimension, $from, $to);

        return [
            'status' => 'ok',
            'dimension' => $dimension,
            'labels' => $breakdown->pluck('type'),
            'data' => $breakdown->pluck('enquiry_count'),
        ];
    }

    /**
     * View Dashboard data (kpis/stats/top items)
     *
     * @return array
     */
    public function content()
    {
        $pages = Page::query()
            ->with([
                'primaryMediaUse.media',
                'template',
                'users'
            ])
            ->latest('updated_at')
            ->whereNull('category')
            ->take(6)
            ->get();

        $globalContent = GlobalContent::query()
            ->with('users')
            ->latest('updated_at')
            ->take(6)
            ->get();

        $media = Media::query()
            ->latest('updated_at')
            ->take(4)
            ->get();

        return [
            'review_pages' => $this->pagesToReview(),
            'pages' => new PageListResource($pages),
            'globalContent' => new GlobalContentElementList($globalContent),
            'media' => new MediaListResource($media),
            'by_type' => collect(config('pages.page_types'))
                ->filter(fn ($type) => Settings::get($type['config_key']))
                ->map(function ($type) {
                    $type['pages'] = new PageListResource(Page::query()
                        ->with([
                            'primaryMediaUse.media',
                            'template',
                            'users'
                        ])
                        ->latest('updated_at')
                        ->where('category', $type)
                        ->take(6)
                        ->get());

                    return $type;
                })
                ->values(),
        ];
    }

    /**
     * View Dashboard data (kpis/stats/top items)
     *
     * @param Request $request
     * @return array
     */
    public function crm(Request $request): array
    {
        $forms = Form::query()->with('type')->latest('updated_at')->take(4)->get();
        $enquiries = Enquiry::query()
            ->with([
                'type',
                'status',
                'form',
            ])
            ->latest('updated_at')
            ->take(6)->get();

        return [
            'tiles' => Reports::getTiles('crm'),
            'forms' => new FormList($forms),
            'enquiries' => new EnquiryList($enquiries),
        ];
    }

    public function taxonomies(Request $request): array
    {
        return [
            'tiles' => PropertyCategory::query()
                ->withActivePropertyCount()
                ->active()
                ->get()
                ->map(fn (PropertyCategory $taxonomyCategory) => new PropertyCountTile($taxonomyCategory)),
        ];
    }

    /**
     * Data for sidebar
     *
     * @return array
     */
    public function sidebar()
    {
        return [
            'release_notes' => Auth::user()->latestUnreadReleaseNote(),
            'pinned_items' => new PinnedItemResource(PinnedItems::get(Auth::user())),
            'franchises' => new FranchiseRepository()->getEnabled(),
            'integrations' => new IntegrationRepository()->getEnabled(),
            'marketing' => true,
        ];
    }

    private function pagesToReview(): array
    {
        $changesRequested = [
            'value' => 'changes-requested',
            'filter' => 'changes-requested',
            'name' => 'Changes requested on my edits',
            'pages' => new VersionListResource(Version::query()
                ->with([
                    'page.primaryMediaUse.media',
                    'author'
                ])
                ->where('author_id', Auth::id())
                ->where('request_changes', 1)
                ->take(6)
                ->get())
        ];

        if (Auth::user()->hasPermissionTo('publish-content')) {
            return [
                [
                    'value' => 'review-versions',
                    'filter' => 'pending-versions',
                    'name' => 'Edits waiting on review',
                    'pages' => new VersionListResource(Version::query()
                        ->with([
                            'page.primaryMediaUse.media',
                            'author'
                        ])
                        ->where('pending_review', 1)
                        ->take(6)
                        ->get())
                ],
                $changesRequested
            ];
        }

        return [ $changesRequested ];
    }

    public function getDashboardWidgets(DashboardRepository $repository, string $section)
    {
        return response($repository->getAvailable(Auth::user(), $section));
    }

    public function setDashboardWidgets(
        SetDashboardWidgetsRequest $request,
        DashboardRepository $repository,
        string $section
    ) {
        $repository->setForUser(Auth::user(), $request->input('widgets', []), $section);
    }

    public function bulkImportLog(string $type): BulkImportLogList
    {
        return new BulkImportLogList(BulkImportLog::query()
            ->with('author')
            ->where('object_type', $type)
            ->latest()
            ->get());
    }

    public function bulkImportLogFile(BulkImportLog $log)
    {
        return Storage::disk('file-storage')->get($log->filename);
    }
}
