<?php

namespace App\Http\Controllers\Api\V1\Admin;

use App\Exceptions\DomainException;
use App\Http\Controllers\Controller;
use App\Models\Doctor;
use App\Models\DoctorLocationAssignment;
use App\Models\Location;
use App\Services\AuditService;
use App\Support\ApiResponse;
use Illuminate\Http\Request;

class DoctorLocationAssignmentAdminController extends Controller
{
    use ApiResponse;

    public function __construct(private readonly AuditService $audit) {}

    public function index(Request $request)
    {
        $rows = DoctorLocationAssignment::query()
            ->with(['doctor.user', 'location'])
            ->where('organization_id', $request->user()->organization_id)
            ->orderByDesc('id')
            ->get();

        return $this->success($rows);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'doctor_id' => ['required', 'integer'],
            'location_id' => ['required', 'integer'],
            'consultation_fee' => ['required', 'numeric', 'min:0'],
            'followup_fee' => ['required', 'numeric', 'min:0'],
            'slot_minutes' => ['required', 'integer', 'min:5', 'max:240'],
            'booking_window_days' => ['required', 'integer', 'min:1', 'max:365'],
            'cancellation_cutoff_minutes' => ['required', 'integer', 'min:0', 'max:43200'],
            'is_active' => ['sometimes', 'boolean'],
        ]);

        Doctor::where('organization_id', $request->user()->organization_id)->findOrFail($data['doctor_id']);
        Location::where('organization_id', $request->user()->organization_id)->findOrFail($data['location_id']);

        $assignment = DoctorLocationAssignment::query()->updateOrCreate(
            ['doctor_id' => $data['doctor_id'], 'location_id' => $data['location_id']],
            $data + ['organization_id' => $request->user()->organization_id]
        );

        $this->audit->log('assignment.changed', $request->user(), $assignment, null, $assignment->toArray());

        return $this->success($assignment->load(['doctor.user', 'location']), 'Doctor-location assignment saved.', 201);
    }

    public function update(Request $request, DoctorLocationAssignment $assignment)
    {
        if ($assignment->organization_id !== $request->user()->organization_id) {
            throw new DomainException('FORBIDDEN', 'Assignment belongs to another organization.', 403);
        }

        $data = $request->validate([
            'consultation_fee' => ['sometimes', 'numeric', 'min:0'],
            'followup_fee' => ['sometimes', 'numeric', 'min:0'],
            'slot_minutes' => ['sometimes', 'integer', 'min:5', 'max:240'],
            'booking_window_days' => ['sometimes', 'integer', 'min:1', 'max:365'],
            'cancellation_cutoff_minutes' => ['sometimes', 'integer', 'min:0', 'max:43200'],
            'is_active' => ['sometimes', 'boolean'],
        ]);

        $before = $assignment->toArray();
        $assignment->update($data);
        $this->audit->log('assignment.changed', $request->user(), $assignment, $before, $assignment->fresh()->toArray());

        return $this->success($assignment->fresh(['doctor.user', 'location']), 'Assignment updated.');
    }

    public function destroy(Request $request, DoctorLocationAssignment $assignment)
    {
        if ($assignment->organization_id !== $request->user()->organization_id) {
            throw new DomainException('FORBIDDEN', 'Assignment belongs to another organization.', 403);
        }

        $assignment->update(['is_active' => false]);
        $this->audit->log('assignment.changed', $request->user(), $assignment, null, ['is_active' => false]);

        return $this->success(null, 'Assignment deactivated.');
    }
}
