<?php

namespace Modules\DermatologyClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\DermatologyClinic\Entities\DermaLesion;

/**
 * AJAX endpoints for the dermatology lesion register (body-map editor, ABCDE
 * checklist, per-lesion photo links). The plugin owns dermatology data; the UI
 * is rendered into ClinicCore's shared patient/appointment screens by the
 * DermatologySpecialtyDriver fragments.
 *
 * Business-scoped throughout (session user.business_id + patient business_id),
 * gated by the derma.lesions.manage permission.
 */
class DermaLesionController extends Controller
{
    private function biz()
    {
        return session('user.business_id');
    }

    private function guardPatient($patientId): ClcPatient
    {
        if (! auth()->user() || ! auth()->user()->can('derma.lesions.manage')) {
            abort(403, 'Unauthorized action.');
        }
        return ClcPatient::where('business_id', $this->biz())->findOrFail($patientId);
    }

    /** Persist a lesion (create or update) for a patient. */
    public function store(Request $request, $patientId)
    {
        $patient = $this->guardPatient($patientId);

        $data = $request->validate([
            'id'               => 'nullable|integer',
            'appointment_id'   => 'nullable|integer',
            'body_region'      => 'required|string|in:' . implode(',', array_keys(DermaLesion::BODY_REGIONS)),
            'position_x'       => 'nullable|integer|min:0|max:100',
            'position_y'       => 'nullable|integer|min:0|max:100',
            'morphology'       => 'required|string|in:' . implode(',', array_keys(DermaLesion::MORPHOLOGIES)),
            'size_mm'          => 'nullable|numeric|min:0|max:9999',
            'color'            => 'nullable|string|max:100',
            'border'           => 'nullable|string|in:' . implode(',', array_keys(DermaLesion::BORDERS)),
            'evolution'        => 'nullable|string|in:' . implode(',', array_keys(DermaLesion::EVOLUTIONS)),
            'dermoscopy_notes' => 'nullable|string|max:2000',
            'biopsy_taken'     => 'nullable|boolean',
            'biopsy_type'      => 'nullable|string|in:' . implode(',', array_keys(DermaLesion::BIOPSY_TYPES)),
            'status'           => 'nullable|string|in:' . implode(',', array_keys(DermaLesion::STATUSES)),
            // ABCDE checklist booleans.
            'abcde'            => 'nullable|array',
        ]);

        $abcde = [];
        foreach (array_keys(DermaLesion::ABCDE_KEYS) as $k) {
            $abcde[$k] = ! empty($data['abcde'][$k]);
        }

        $attrs = [
            'appointment_id'   => $data['appointment_id'] ?? null,
            'body_region'      => $data['body_region'],
            'position_x'       => $data['position_x'] ?? null,
            'position_y'       => $data['position_y'] ?? null,
            'morphology'       => $data['morphology'],
            'size_mm'          => $data['size_mm'] ?? null,
            'color'            => $data['color'] ?? null,
            'border'           => $data['border'] ?? null,
            'evolution'        => $data['evolution'] ?? null,
            'dermoscopy_notes' => $data['dermoscopy_notes'] ?? null,
            'biopsy_taken'     => ! empty($data['biopsy_taken']),
            'biopsy_type'      => $data['biopsy_type'] ?? null,
            'status'           => $data['status'] ?? 'active',
            'abcde_flags'      => $abcde,
        ];

        if (! empty($data['id'])) {
            $lesion = DermaLesion::where('business_id', $this->biz())
                ->where('patient_id', $patient->id)->findOrFail($data['id']);
            $lesion->update($attrs);
        } else {
            $lesion = DermaLesion::create($attrs + [
                'business_id' => $this->biz(),
                'patient_id'  => $patient->id,
                'created_by'  => auth()->id(),
            ]);
        }

        return response()->json([
            'success'         => true,
            'lesion'          => $this->present($lesion),
            'suggest_biopsy'  => $lesion->suggestsBiopsy(),
            'msg'             => 'Lesion saved.',
        ]);
    }

    /** Delete a lesion. */
    public function destroy($patientId, $lesionId)
    {
        $patient = $this->guardPatient($patientId);

        $lesion = DermaLesion::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)->findOrFail($lesionId);
        $lesion->delete();

        return response()->json(['success' => true, 'msg' => 'Lesion deleted.']);
    }

    /**
     * Link / unlink clc_clinical_photos ids to a lesion (chronological photo
     * strip). Photos themselves are uploaded through ClinicCore's shared
     * clinic.patients.photos.store endpoint; here we only record the association.
     */
    public function linkPhotos(Request $request, $patientId, $lesionId)
    {
        $patient = $this->guardPatient($patientId);

        $data = $request->validate([
            'photo_ids'   => 'nullable|array',
            'photo_ids.*' => 'integer',
        ]);

        $lesion = DermaLesion::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)->findOrFail($lesionId);

        // Keep only ids that actually belong to THIS patient's clinical photos.
        $valid = \Modules\ClinicCore\Entities\ClcClinicalPhoto::where('business_id', $this->biz())
            ->where('clc_patient_id', $patient->id)
            ->whereIn('id', $data['photo_ids'] ?? [])
            ->pluck('id')->all();

        $lesion->update(['photo_ids' => array_values(array_map('intval', $valid))]);

        return response()->json(['success' => true, 'photo_ids' => $lesion->photo_ids, 'msg' => 'Photos linked.']);
    }

    private function present(DermaLesion $l): array
    {
        return [
            'id'           => $l->id,
            'body_region'  => $l->body_region,
            'position_x'   => $l->position_x,
            'position_y'   => $l->position_y,
            'morphology'   => $l->morphology,
            'size_mm'      => $l->size_mm,
            'color'        => $l->color,
            'border'       => $l->border,
            'evolution'    => $l->evolution,
            'status'       => $l->status,
            'biopsy_taken' => $l->biopsy_taken,
            'abcde_count'  => $l->abcdeCount(),
        ];
    }
}
