<?php

namespace Mtc\Plugins\Wisebee\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Src\Encryption;
use Carbon\Carbon;
use Illuminate\Contracts\View\Factory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Application;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
use Mtc\Core\AdminUser;
use Mtc\Core\PaginationTemplate;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeCategory;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeConsultation;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeDocument;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeMember;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeParticipant;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeSetting;
use Mtc\Plugins\Wisebee\Classes\WisebeeManager;
use Mtc\Shop\Category;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Wisebee\Resources\Rate;

class WisebeeController extends Controller
{
    const int PER_PAGE = 20;

    /**
     * Downloads a document
     *
     * @param $id
     * @return void
     */
    public function downloadDocument($id): void
    {
        $document = WisebeeDocument::query()
            ->find($id);
        if (empty($document)) {
            return;
        }

        $fileName = basename($document->file);

        $safeRoot = realpath($_SERVER['DOCUMENT_ROOT'] . WisebeeDocument::FILE_PATH);
        $realPath = realpath($_SERVER['DOCUMENT_ROOT'] . $document->file);
        if ($safeRoot === false || $realPath === false || !str_starts_with($realPath, $safeRoot)) {
            abort(404);
        }
        $fullPath = $realPath;

        $fp = fopen($fullPath, 'rb');
        if ($fp === false) {
            abort(404);
        }

        $mimeType = mime_content_type($fullPath) ?: 'application/octet-stream';

        header('Pragma: public');
        header('Content-Type: ' . $mimeType);
        header('Content-Disposition: attachment; filename="' . addcslashes($fileName, '"\\') . '"');
        header('Content-Length: ' . filesize($fullPath));

        fpassthru($fp);
        fclose($fp);
        exit;
    }

    /**
     * Wisebee configuration page
     *
     * @return Factory|View
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function configuration()
    {
        $title = 'Wisebee Configuration';
        $page_meta['title'] = config('app.name') . ' | ' . $title;

        $requiredCategoriesIds = WisebeeCategory::query()
            ->where('consultation_required', true)
            ->pluck('category_id');

        return template('wisebee/admin/configuration.twig', [
            'page_meta' => $page_meta,
            'wisebeeSettings' => WisebeeSetting::allSettings(),
            'wisebeeSettingsDefaults' => WisebeeSetting::$settings,
            'title' => $title,
            'success' => session()->get('success'),
            'categories' => Category::getCompleteFlatTree()
                ->map(function (Category $category) use ($requiredCategoriesIds) {
                    $category->required = $requiredCategoriesIds->contains($category->id);
                    return $category;
                }),
        ]);
    }

    /**
     * Save Wisebee configuration
     *
     * @param Request $request
     * @return Application|RedirectResponse|Redirector|object
     */
    public function configurationStore(Request $request)
    {
        WisebeeCategory::query()
            ->truncate();

        foreach ($request->input('categories', []) as $categoryID) {
            WisebeeCategory::query()
                ->create([
                    'category_id' => $categoryID,
                    'consultation_required' => true,
                ]);
        }

        $submittedSettings = $request->input('settings');

        foreach (WisebeeSetting::$settings as $key => $attributes) {
            if (isset($submittedSettings[$key])) {
                $value = $submittedSettings[$key];
            } else {
                $value = null;
            }
            WisebeeSetting::query()
                ->where('name', $key)
                ->update([
                    'value' => $value,
                ]);
        }

        session()->flash('success', 'Configuration updated successfully!');
        return redirect(route('wisebee-admin-configuration'));
    }

    /**
     * Get a list of consultations
     *
     * @param Request $request
     * @return string
     */
    public function consultations(Request $request): string
    {
        $page = $request->input('page') ?: 1;
        $page_meta['title'] = config('app.name') . ' | View consultations';

        $query = WisebeeConsultation::query()
            ->with([
                'participants',
                'documents',
            ]);

        $consultations = self::filterConsultations($query, $request->all());

        $consultationsFound = $consultations->count();

        $pagination = new PaginationTemplate([
            'item_count' => $consultationsFound,
            'per_page' => self::PER_PAGE,
            'active_page' => $page,
            'show_view_all' => false,
            'page_url' => route('wisebee-admin-consultations', $request->all(), false),
        ]);
        $pagination = $pagination->render();

        $statusCounts['all'] = WisebeeConsultation::query()
            ->where('status', '!=', WisebeeConsultation::STATUS_TEMPORARY)
            ->count();
        foreach (WisebeeConsultation::$statuses as $status) {
            if ($status === WisebeeConsultation::STATUS_LIVE) {
                $statusCounts[$status] = WisebeeConsultation::query()
                    ->whereIn('status', [
                        WisebeeConsultation::STATUS_LIVE,
                        WisebeeConsultation::STATUS_COOLDOWN,
                    ])
                    ->count();
                continue;
            }
            $statusCounts[$status] = WisebeeConsultation::query()
                ->where('status', $status)
                ->count();
        }

        $allRates = (new WisebeeManager())->getRates();
        $ratesById = collect($allRates)
            ->mapWithKeys(function ($rate) {
                return [$rate->id => $rate];
            })
            ->toArray();

        // Get paginated consultations
        $paginatedConsultations = $consultations
            ->take(self::PER_PAGE)
            ->offset(($page - 1) * self::PER_PAGE)
            ->orderBy('consultation_date')
            ->get();

        // Collect all customer participant wisebee_user_ids to batch load WisebeeMembers
        $customerWisebeeIds = $paginatedConsultations
            ->flatMap(function ($consultation) {
                return $consultation->participants
                    ->where('type', WisebeeParticipant::TYPE_CUSTOMER)
                    ->pluck('wisebee_user_id');
            })
            ->filter()
            ->unique()
            ->values();

        // Batch load all WisebeeMembers keyed by wisebee_id
        $wisebeeMembersById = WisebeeMember::query()
            ->whereIn('wisebee_id', $customerWisebeeIds)
            ->get()
            ->keyBy('wisebee_id');

        return template('wisebee/admin/consultations/index.twig', [
            'page_meta' => $page_meta,
            'title' => 'Manage Wisebee Consultations',
            'consultations' => $paginatedConsultations
                ->map(function (WisebeeConsultation $consultation) use ($ratesById, $wisebeeMembersById) {
                    $consultation->patient = $consultation->participants
                        ->where('type', WisebeeParticipant::TYPE_CUSTOMER)
                        ->first();
                    if (!empty($consultation->patient)) {
                        $wisebeeMember = $wisebeeMembersById->get($consultation->patient->wisebee_user_id);
                        if (!empty($wisebeeMember)) {
                            $consultation->member_id = $wisebeeMember->member_id;
                        }
                    }
                    $consultation->specialist = $consultation->participants
                        ->where('type', WisebeeParticipant::TYPE_SPECIALIST)
                        ->first();
                    $consultation->dateTime = Carbon::parse($consultation->time_from)
                        ->format('M d, Y H:i');
                    $consultation->viewURL = config('wisebee.host') . 'consultations/view/' . $consultation->wisebee_id;
                    $consultation->videoURL = in_array($consultation->status, [
                        WisebeeConsultation::STATUS_PENDING,
                        WisebeeConsultation::STATUS_LIVE,
                        WisebeeConsultation::STATUS_COOLDOWN,
                    ]) ?
                        config('wisebee.host') . 'consultations/panel?id=' . $consultation->wisebee_id :
                        null;
                    if ($consultation->status === WisebeeConsultation::STATUS_COOLDOWN) {
                        $consultation->status = WisebeeConsultation::STATUS_LIVE;
                    }
                    $consultation->rate = '';
                    if (!empty($consultation->wisebee_rate_id) && isset($ratesById[$consultation->wisebee_rate_id])) {
                        $consultation->rate = $ratesById[$consultation->wisebee_rate_id]->name;
                    }
                    return $consultation;
                }),
            'statuses' => WisebeeConsultation::$statuses,
            'mediums' => WisebeeConsultation::$mediums,
            'request' => $request->all(),
            'pagination' => $pagination,
            'consultationsFound' => $consultationsFound,
            'statusCounts' => $statusCounts,
            'rates' => $allRates,
            'users' => AdminUser::query()
                ->whereHas('wisebee_user', function (Builder $query) {
                    $query->whereHas('participants');
                })
                ->get(),
        ]);
    }

    /**
     * Apply filter to consultations
     *
     * @param Builder $query
     * @param array $filters
     * @return Builder
     */
    public static function filterConsultations(Builder $query, array $filters): Builder
    {
        if (!empty($filters['id'])) {
            $query->where('wisebee_consultations.id', $filters['id']);
        }

        if (!empty($filters['medium'])) {
            $query->where('wisebee_consultations.medium', $filters['medium']);
        }

        if (!empty($filters['status'])) {
            if ($filters['status'] === WisebeeConsultation::STATUS_LIVE) {
                $query->whereIn('wisebee_consultations.status', [
                    WisebeeConsultation::STATUS_LIVE,
                    WisebeeConsultation::STATUS_COOLDOWN,
                ]);
            } else {
                $query->where('wisebee_consultations.status', $filters['status']);
            }
        } else {
            $query->whereNotIn('wisebee_consultations.status', [
                WisebeeConsultation::STATUS_TEMPORARY,
                WisebeeConsultation::STATUS_CANCELLED,
            ]);
        }

        if (!empty($filters['price'])) {
            if ($filters['price'] === 'free') {
                $query->where('wisebee_consultations.cost', 0);
            } else {
                $query->where('wisebee_consultations.cost', '>', 0);
            }
        }

        if (!empty($filters['member_id'])) {
            $query->whereHas('participants', function (Builder $query) use ($filters) {
                $query->whereHas('customer', function (Builder $query) use ($filters) {
                    $query->where('wisebee_members.member_id', $filters['member_id']);
                });
            });
        }

        if (!empty($filters['user_id'])) {
            $query->whereHas('participants', function (Builder $query) use ($filters) {
                $query->whereHas('user', function (Builder $query) use ($filters) {
                    $query->where('wisebee_users.admin_user_id', $filters['user_id']);
                });
            });
        }

        if (!empty($filters['rate_id'])) {
            $query->where('wisebee_consultations.wisebee_rate_id', $filters['rate_id']);
        }

        if (!empty($filters['date_from']) && preg_match('#^\d{2}/\d{2}/\d{4}$#', $filters['date_from'])) {
            $dateFrom = Carbon::createFromFormat('d/m/Y', $filters['date_from'])
                ->format('Y-m-d');
            $query->where('consultation_date', '>=', $dateFrom);
        }

        if (!empty($filters['date_to']) && preg_match('#^\d{2}/\d{2}/\d{4}$#', $filters['date_to'])) {
            $dateTo = Carbon::createFromFormat('d/m/Y', $filters['date_to'])
                ->format('Y-m-d');
            $query->where('consultation_date', '<=', $dateTo);
        }

        if (!empty($filters['booked_from']) && preg_match('#^\d{2}/\d{2}/\d{4}$#', $filters['booked_from'])) {
            $bookedFrom = Carbon::createFromFormat('d/m/Y', $filters['booked_from']);
            $query->where('wisebee_consultations.created_at', '>=', $bookedFrom);
        }

        if (!empty($filters['booked_to']) && preg_match('#^\d{2}/\d{2}/\d{4}$#', $filters['booked_to'])) {
            $bookedTo = Carbon::createFromFormat('d/m/Y', $filters['booked_to'])
                ->addDay();
            $query->where('wisebee_consultations.created_at', '<=', $bookedTo);
        }

        if (!empty($filters['email'])) {
            $query->whereHas('participants', function (Builder $query) use ($filters) {
                $query->where('wisebee_participants.type', WisebeeParticipant::TYPE_CUSTOMER)
                    ->where('wisebee_participants.email_hash', Encryption::makeHash($filters['email']));
            });
        }

        if (!empty($filters['firstname'])) {
            $query->whereHas('participants', function (Builder $query) use ($filters) {
                $query->where('wisebee_participants.type', WisebeeParticipant::TYPE_CUSTOMER)
                    ->where('wisebee_participants.firstname_hash', Encryption::makeHash($filters['firstname']));
            });
        }

        if (!empty($filters['lastname'])) {
            $query->whereHas('participants', function (Builder $query) use ($filters) {
                $query->where('wisebee_participants.type', WisebeeParticipant::TYPE_CUSTOMER)
                    ->where('wisebee_participants.lastname_hash', Encryption::makeHash($filters['lastname']));
            });
        }

        return $query;
    }
}