<?php

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

use App\Enums\UserRole;
use App\Enums\UserStatus;
use App\Exceptions\DomainException;
use App\Http\Controllers\Controller;
use App\Models\Assistant;
use App\Models\User;
use App\Services\AuditService;
use App\Support\ApiResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AssistantAdminController extends Controller
{
    use ApiResponse;

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

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

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

    public function store(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:150'],
            'email' => ['required', 'email', 'max:190'],
            'phone' => ['nullable', 'string', 'max:40'],
            'password' => ['required', 'string', 'min:8', 'max:255'],
            'employee_code' => ['nullable', 'string', 'max:80'],
        ]);

        $assistant = DB::transaction(function () use ($request, $data) {
            if (User::where('organization_id', $request->user()->organization_id)->where('email', $data['email'])->exists()) {
                throw new DomainException('EMAIL_ALREADY_IN_USE', 'This email is already used in the organization.', 409);
            }

            $user = User::create([
                'organization_id' => $request->user()->organization_id,
                'name' => $data['name'],
                'email' => $data['email'],
                'phone' => $data['phone'] ?? null,
                'password' => $data['password'],
                'role' => UserRole::ASSISTANT,
                'status' => UserStatus::ACTIVE,
            ]);

            return Assistant::create([
                'organization_id' => $request->user()->organization_id,
                'user_id' => $user->id,
                'phone' => $data['phone'] ?? null,
                'employee_code' => $data['employee_code'] ?? null,
                'is_active' => true,
            ]);
        });

        $this->audit->log('assistant.created', $request->user(), $assistant, null, $assistant->load('user')->toArray());

        return $this->success($assistant->load('user'), 'Assistant created.', 201);
    }

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

        $data = $request->validate([
            'name' => ['sometimes', 'string', 'max:150'],
            'email' => ['sometimes', 'email', 'max:190'],
            'phone' => ['nullable', 'string', 'max:40'],
            'password' => ['nullable', 'string', 'min:8', 'max:255'],
            'employee_code' => ['nullable', 'string', 'max:80'],
            'is_active' => ['sometimes', 'boolean'],
            'status' => ['sometimes', 'in:active,disabled,suspended'],
        ]);

        $before = $assistant->load('user')->toArray();

        if (isset($data['email'])) {
            $emailInUse = User::query()
                ->where('organization_id', $request->user()->organization_id)
                ->where('email', strtolower(trim($data['email'])))
                ->whereKeyNot($assistant->user_id)
                ->exists();

            if ($emailInUse) {
                throw new DomainException('EMAIL_ALREADY_IN_USE', 'This email is already used in the organization.', 409);
            }
        }

        DB::transaction(function () use ($assistant, $data) {
            $assistant->update(array_intersect_key($data, array_flip(['phone', 'employee_code', 'is_active'])));
            $userFields = array_intersect_key($data, array_flip(['name', 'email', 'phone', 'password', 'status']));
            if (($data['is_active'] ?? true) === false && ! isset($userFields['status'])) {
                $userFields['status'] = 'disabled';
            }
            if ($userFields) {
                $assistant->user->update($userFields);
            }
        });

        $assistant->refresh()->load('user');
        $this->audit->log('assistant.updated', $request->user(), $assistant, $before, $assistant->toArray());

        return $this->success($assistant, 'Assistant updated.');
    }

    public function destroy(Request $request, Assistant $assistant)
    {
        return $this->update($request->merge(['is_active' => false, 'status' => 'disabled']), $assistant);
    }
}
