<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreMedicalRecordRequest;
use App\Http\Requests\UpdateMedicalRecordRequest;
use App\Models\Client;
use App\Models\MedicalRecord;
use App\Models\MedicalRecordAttachment;
use App\Models\Patient;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class MedicalRecordController extends Controller
{
    protected function assertPatient(Client $client, Patient $patient): void
    {
        abort_unless($patient->client_id === $client->id, 404);
    }

    public function index(Client $client, Patient $patient): View
    {
        $this->assertPatient($client, $patient);
        $this->authorize('viewAny', MedicalRecord::class);

        $records = $patient->medicalRecords()->with('author')->withCount('attachments')->paginate(15);

        return view('medical_records.index', compact('client', 'patient', 'records'));
    }

    public function create(Client $client, Patient $patient): View
    {
        $this->assertPatient($client, $patient);
        $this->authorize('create', MedicalRecord::class);

        return view('medical_records.create', compact('client', 'patient'));
    }

    public function store(StoreMedicalRecordRequest $request, Client $client, Patient $patient): RedirectResponse
    {
        $this->assertPatient($client, $patient);

        $data = $request->safe()->except(['attachments']);
        $data['recorded_by'] = $request->user()->id;

        $record = DB::transaction(function () use ($data, $patient, $request) {
            $record = $patient->medicalRecords()->create($data);
            if ($request->hasFile('attachments')) {
                foreach ($request->file('attachments') as $file) {
                    $path = $file->store("medical-attachments/{$record->id}", 'public');
                    $record->attachments()->create([
                        'path' => $path,
                        'original_name' => $file->getClientOriginalName(),
                        'mime' => $file->getClientMimeType(),
                        'size' => $file->getSize(),
                    ]);
                }
            }

            return $record;
        });

        return redirect()->route('clients.patients.medical-records.show', [$client, $patient, $record])
            ->with('success', __('Historia guardada.'));
    }

    public function show(Client $client, Patient $patient, MedicalRecord $medicalRecord): View
    {
        $this->assertPatient($client, $patient);
        abort_unless($medicalRecord->patient_id === $patient->id, 404);
        $this->authorize('view', $medicalRecord);

        $medicalRecord->load(['attachments', 'author']);

        return view('medical_records.show', compact('client', 'patient', 'medicalRecord'));
    }

    public function print(Client $client, Patient $patient, MedicalRecord $medicalRecord): View
    {
        $this->assertPatient($client, $patient);
        abort_unless($medicalRecord->patient_id === $patient->id, 404);
        $this->authorize('view', $medicalRecord);

        $medicalRecord->load(['attachments', 'author']);

        return view('medical_records.print', compact('client', 'patient', 'medicalRecord'));
    }

    public function edit(Client $client, Patient $patient, MedicalRecord $medicalRecord): View
    {
        $this->assertPatient($client, $patient);
        abort_unless($medicalRecord->patient_id === $patient->id, 404);
        $this->authorize('update', $medicalRecord);

        $medicalRecord->load('attachments');

        return view('medical_records.edit', compact('client', 'patient', 'medicalRecord'));
    }

    public function update(UpdateMedicalRecordRequest $request, Client $client, Patient $patient, MedicalRecord $medicalRecord): RedirectResponse
    {
        $this->assertPatient($client, $patient);
        abort_unless($medicalRecord->patient_id === $patient->id, 404);

        $data = $request->safe()->except(['attachments', 'remove_attachment_ids']);

        DB::transaction(function () use ($request, $medicalRecord, $data): void {
            $medicalRecord->update($data);

            foreach ($request->input('remove_attachment_ids', []) as $id) {
                $att = MedicalRecordAttachment::query()
                    ->where('medical_record_id', $medicalRecord->id)
                    ->whereKey($id)
                    ->first();
                if ($att) {
                    Storage::disk('public')->delete($att->path);
                    $att->delete();
                }
            }

            if ($request->hasFile('attachments')) {
                foreach ($request->file('attachments') as $file) {
                    $path = $file->store("medical-attachments/{$medicalRecord->id}", 'public');
                    $medicalRecord->attachments()->create([
                        'path' => $path,
                        'original_name' => $file->getClientOriginalName(),
                        'mime' => $file->getClientMimeType(),
                        'size' => $file->getSize(),
                    ]);
                }
            }
        });

        return redirect()->route('clients.patients.medical-records.show', [$client, $patient, $medicalRecord])
            ->with('success', __('Historia actualizada.'));
    }

    public function destroy(Client $client, Patient $patient, MedicalRecord $medicalRecord): RedirectResponse
    {
        $this->assertPatient($client, $patient);
        abort_unless($medicalRecord->patient_id === $patient->id, 404);
        $this->authorize('delete', $medicalRecord);

        DB::transaction(function () use ($medicalRecord): void {
            foreach ($medicalRecord->attachments as $att) {
                Storage::disk('public')->delete($att->path);
            }
            $medicalRecord->delete();
        });

        return redirect()->route('clients.patients.medical-records.index', [$client, $patient])
            ->with('success', __('Historia eliminada.'));
    }
}
