<?php

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

use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Mtc\Core\Admin\User;
use Mtc\Core\AdminUser;
use Mtc\Core\PaginationTemplate;
use Mtc\Plugins\Clinic\Src\Logger;
use Mtc\Plugins\Clinic\Src\Models\Review;
use Mtc\Plugins\Clinic\Src\Models\ReviewType;
use Mtc\Shop\Assessment\Answer;
use Mtc\Shop\Assessment\Assessment;
use Mtc\Shop\Assessment\Form;
use Mtc\Shop\Category;

/**
 * Class ReviewController
 */
class ReviewController extends ClinicController
{

    const PER_PAGE = 20;

    /**
     * List of database entries
     *
     * @param Request $request
     * @return string
     */
    public function index(Request $request): string
    {
        $title = 'Manage Reviews';
        $page_meta['title'] = config('app.name') . ' | ' . $title;
        $page = $request->input('page') ?: 1;

        $reviews = Review::query()
            ->with('member.addressBilling')
            ->with('category')
            ->with('form')
            ->with('user')
            ->orderByDesc('due_date');
        $reviews = Review::filterReviews($reviews, $request->all());

        $pagination = new PaginationTemplate([
            'item_count' => $reviews->count(),
            'per_page' => self::PER_PAGE,
            'active_page' => $page,
            'show_view_all' => false,
            'page_url' => route('admin-reviews', [], false),
        ]);
        $pagination = $pagination->render();

        return template('admin/reviews/index.twig', [
            'page_meta' => $page_meta,
            'title' => $title,
            'mediums' => Review::$mediums,
            'types' => Review::$types,
            'categories' => Category::getCompleteFlatTree(),
            'statuses' => Review::$statuses,
            'users' => AdminUser::query()
                ->orderBy('name')
                ->get(),
            'forms' => Form::query()
                ->orderBy('name')
                ->get(),
            'reviews' => $reviews->take(self::PER_PAGE)->offset(($page - 1) * self::PER_PAGE)->get()
                ->map(function (Review $review) {
                    $review->due_date = Carbon::parse($review->due_date)
                        ->format('d/m/Y');
                    return $review;
                }),
            'reviewTypes' => ReviewType::query()
                ->with('form')
                ->with('category')
                ->orderBy('name')
                ->get(),
            'request' => $request->all(),
            'pagination' => $pagination,
        ]);
    }

    /**
     * Load reviews
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function load(Request $request): JsonResponse
    {
        // Base query with only the fields the list needs
        $q = Review::query()
            ->select(['id','user_id','status','type','medium','due_date'])
            ->with(['user:id,name'])                 // only id+name for the assignee
            ->orderByDesc('due_date');

        // Keep existing filters (they don’t require eager-loaded relations)
        $q = Review::filterReviews($q, $request->all());

        // Map to a minimal, UI-friendly shape
        $reviews = $q->get()->map(function (Review $r) {
            return [
                'id'       => $r->id,
                'due_date' => $r->due_date
                    ? Carbon::parse($r->due_date)->format('d/m/Y')
                    : null,
                'status'   => Review::$statuses[$r->status] ?? $r->status,
                'type'     => Review::$types[$r->type]       ?? $r->type,
                'medium'   => Review::$mediums[$r->medium]   ?? $r->medium,
                'user'     => $r->user ? ['name' => $r->user->name] : null,
            ];
        })->values();

        return response()->json(['reviews' => $reviews]);
    }


    /**
     * Load single review
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function loadReview(Request $request): JsonResponse
    {
        $id = (int) $request->input('id');

        // --- Lookups (trimmed) ---
        $mediums  = Review::$mediums;   // code => label
        $types    = Review::$types;     // code => label
        $statuses = Review::$statuses;  // code => label
        $dateOptions = Review::getDateOptions();

        // Only what's needed for selects
        $forms = Form::query()
            ->orderBy('name')
            ->get(['id','name']);

        $users = AdminUser::query()
            ->orderBy('name')
            ->get(['id','name']);

        // Keep the pretty tree label if you use it in a <select>; otherwise just 'name'
        $categories = Category::getCompleteFlatTree()
            ->map(fn ($c) => [
                'id'            => $c->id,
                'name'          => $c->name,
                'intended_name' => $c->intended_name ?? $c->name,  // safe fallback
                'form_id'       => $c->form_id,
            ])
            ->values();

        // Review types used to prefill fields when a “type” is chosen
        $reviewTypes = ReviewType::query()
            ->orderBy('name')
            ->get(['id','name','form_id','category_id','type','medium']);

        // --- Review payload (editing) OR last assignee (creating) ---
        $review = null;
        $lastReview = null;

        if ($id) {
            /** @var Review|null $r */
            $r = Review::query()
                ->select(['id','member_id','form_id','category_id','user_id','status','type','medium','due_date','notes'])
                ->with([
                    // Minimal patient summary for the drawer header
                    'member:id',
                    'member.addressBilling:id,member_id,firstname,lastname,address1,address2,city,postcode',
                ])
                ->find($id);

            if ($r) {
                $review = [
                    'id'         => $r->id,
                    'member_id'  => $r->member_id,
                    'form_id'    => $r->form_id,
                    'category_id'=> $r->category_id,
                    'user_id'    => $r->user_id,
                    'status'     => $r->status,
                    'type'       => $r->type,
                    'medium'     => $r->medium,
                    'due_date'   => $r->due_date ? Carbon::parse($r->due_date)->format('d/m/Y') : '',
                    'notes'      => (string) $r->notes,
                    // Keep the structure the Vue uses: review.member.address_billing.*
                    'member'     => $r->member ? [
                        'id' => $r->member->id,
                        'address_billing' => $r->member->addressBilling ? [
                            'firstname' => $r->member->addressBilling->firstname,
                            'lastname'  => $r->member->addressBilling->lastname,
                            'address1'  => $r->member->addressBilling->address1,
                            'address2'  => $r->member->addressBilling->address2,
                            'city'      => $r->member->addressBilling->city,
                            'postcode'  => $r->member->addressBilling->postcode,
                        ] : null,
                    ] : null,
                    // DO NOT include assessments, hashes, timestamps, emails, phones, etc.
                ];
            }
        } else {
            // New review: just provide last assignee convenience
            $lastUserId = Review::query()->orderByDesc('due_date')->value('user_id');
            $lastReview = $lastUserId ? ['user_id' => (int) $lastUserId] : null;
        }

        return response()->json([
            'mediums'      => $mediums,
            'types'        => $types,
            'categories'   => $categories,
            'statuses'     => $statuses,
            'users'        => $users,       // [{id,name}]
            'forms'        => $forms,       // [{id,name}]
            'reviewTypes'  => $reviewTypes, // [{id,name,form_id,category_id,type,medium}]
            'dateOptions'  => $dateOptions, // {"dd/mm/YYYY":"x weeks",...}
            'review'       => $review,      // null when creating
            'lastReview'   => $lastReview,  // {user_id} or null
        ]);
    }

    /**
     * Add / edit page
     *
     * @param $id
     * @return string
     */
    public function edit($id = null): string
    {
        $title = !empty($id) ?
            'Edit Review' :
            'Add Review';
        $page_meta['title'] = config('app.name') . ' | ' . $title;

        return template('admin/reviews/edit.twig', [
            'page_meta' => $page_meta,
            'title' => $title,
            'reviewID' => $id,
            'routes' => [
                'admin-reviews-store' => route('admin-reviews-store'),
                'admin-patients-search' => route('admin-patients-search'),
                'admin-patients-profile' => route('admin-patients-profile', [
                    'id' => '---id---',
                ]),
                'admin-reviews-load-review' => route('admin-reviews-load-review'),
            ],
        ]);
    }

    /**
     * Creates / updates entry in database
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function store(Request $request): JsonResponse
    {
        if ($errors = Review::validate($request->all())) {
            return response()
                ->json([
                    'errors' => $errors,
                ]);
        }

        /** @var Review $review */
        $review = Review::query()
            ->findOrNew($request->input('id'));

        $action = empty($review->id) ?
            Logger::ACTION_CREATED :
            Logger::ACTION_UPDATED;

        $data = $request->all();
        $data['due_date'] = Carbon::createFromFormat('d/m/Y', $data['due_date'])
            ->format('Y-m-d');

        $review->fill($data);
        if (empty($review->hash)) {
            $review->generateHash();
        }
        $review->save();

        (new Logger($review, User::getAdminUser(), $request->input('member_id')))
            ->log(Logger::REVIEW, $action, $review->toArray());

        $review->due_date = $request->input('due_date');

        return response()
            ->json([
                'success' => 'Data saved successfully!',
                'review' => $review,
            ]);
    }

}
