<?php

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

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Mtc\Modules\Members\Models\Member;
use Mtc\Modules\Members\Models\MemberAttribute;

/**
 * Class MemberAttributeController
 * @package App\Http\Controllers
 */
class MemberAttributeController extends ClinicController
{
    /**
     *
     *
     * @param Request $request
     * @return string
     */
    public function index($id): string
    {
        $page_meta['title'] = config('app.name') . ' | Manage Member Attributes';

        return template('admin/memberAttributes/index.twig', [
            'page_meta' => $page_meta,
            'title' => 'Manage member attributes',
            'attributes' => MemberAttribute::getFields(),
            'routes' => [
                'admin-member-attributes-load' => route('admin-member-attributes-load', [
                    'id' => $id,
                ]),
                'admin-member-attributes-store' => route('admin-member-attributes-store', [
                    'id' => $id,
                ]),
            ],
        ]);
    }

    /**
     * Loads member attributes
     *
     * @param $id
     * @return JsonResponse
     */
    public function load($id): JsonResponse
    {
        /** @var Member $member */
        $member = Member::query()
            ->with('attributes')
            ->findOrFail($id);

        return response()->json([
            'attributes' => MemberAttribute::unpackDataForForm($member),
        ]);
    }

    /**
     */
    public function store($id, Request $request): JsonResponse
    {
        if (!$member = Member::query()->find($id)) {
            return response()->json(['errors' => ['general' => 'Patient not found!']]);
        }

        // ---- normalize attributes into an array ----
        $attrs = $this->extractAttributes($request);

        if ($errors = MemberAttribute::validate($attrs)) {
            return response()->json(['errors' => $errors]);
        }

        $data = MemberAttribute::packDataForStore($attrs);
        MemberAttribute::logChanges($member, $data);

        foreach ($data as $key => $value) {
            MemberAttribute::query()->updateOrCreate(
                ['member_id' => $member->id, 'name' => $key],
                ['value' => $value]
            );
        }

        return response()->json(['success' => 'Patient data updated successfully!']);
    }

    /**
     * Accepts JSON body, JSON string, form-data with bracketed fields,
     * or even flat fields (text_example, …) and returns a normalized array.
     */
    private function extractAttributes(Request $request): array
    {
        // 1) direct nested array (ideal)
        $attrs = $request->input('attributes');
        if (is_array($attrs)) {
            return $attrs;
        }

        // 2) JSON string in "attributes"
        if (is_string($attrs) && $attrs !== '') {
            $decoded = json_decode($attrs, true);
            if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                return $decoded;
            }
        }

        // 3) multipart/form-data bracketed fields
        $all = $request->all();
        if (isset($all['attributes']) && is_array($all['attributes'])) {
            return $all['attributes'];
        }

        // 4) raw JSON body
        $raw = $request->getContent();
        if (is_string($raw) && $raw !== '') {
            $decoded = json_decode($raw, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                if (isset($decoded['attributes']) && is_array($decoded['attributes'])) {
                    return $decoded['attributes'];
                }
                if (is_array($decoded)) { // posted attributes at root
                    return $decoded;
                }
            }
        }

        // 5) last resort: collect flat fields by schema keys
        $keys = array_keys(MemberAttribute::getFields());
        $fallback = [];
        foreach ($keys as $k) {
            if ($request->has($k)) {
                $fallback[$k] = $request->input($k);
            }
            // handle datetime companion
            if ($request->has($k . '_time')) {
                $fallback[$k . '_time'] = $request->input($k . '_time');
            }
        }
        return $fallback;
    }

}
