<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\Branch;
use App\Models\Member;
use App\Models\Practitioner;
use App\Services\Care\AuditLogger;
use App\Services\Care\CarePermissions;
use App\Services\Identity\IdentityTeamClient;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class MemberController extends Controller
{
    use ScopesToAccount;

    public function index(Request $request): View
    {
        $this->authorizeAbility($request, 'admin.members.view');
        $organization = $this->organization($request);

        $members = Member::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->with('branch')
            ->orderBy('created_at')
            ->get();

        $adminRoles = ['super_admin', 'hospital_admin'];
        $clinicalRoles = app(CarePermissions::class)->clinicalPractitionerRoles();

        $heroStats = [
            'total' => $members->count(),
            'admins' => $members->whereIn('role', $adminRoles)->count(),
            'clinical' => $members->whereIn('role', $clinicalRoles)->count(),
            'branch_scoped' => $members->whereNotNull('branch_id')->count(),
        ];

        return view('care.admin.members.index', [
            'members' => $members,
            'organization' => $organization,
            'roles' => config('care.roles'),
            'heroStats' => $heroStats,
        ]);
    }

    public function create(Request $request, IdentityTeamClient $identity): View
    {
        $this->authorizeAbility($request, 'admin.members.manage');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $branches = Branch::owned($owner)
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        $mailboxOptions = [];
        try {
            $mailboxOptions = $identity->mailboxOptions($owner);
        } catch (\Throwable) {
            // Identity optional for form rendering.
        }

        return view('care.admin.members.create', [
            'organization' => $organization,
            'branches' => $branches,
            'roles' => config('care.roles'),
            'practitionerRoles' => app(CarePermissions::class)->clinicalPractitionerRoles(),
            'mailboxOptions' => $mailboxOptions,
            'specialties' => Practitioner::specialtyOptions(),
        ]);
    }

    public function store(Request $request, IdentityTeamClient $identity): RedirectResponse
    {
        $this->authorizeAbility($request, 'admin.members.manage');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $permissions = app(CarePermissions::class);
        $needsPractitionerDesk = $permissions->usesPractitionerBranchScope(
            new Member(['role' => $request->input('role')])
        );

        $validated = $request->validate([
            'email' => ['required', 'email', 'max:255'],
            'role' => ['required', 'string', 'in:'.implode(',', array_keys(config('care.roles')))],
            'branch_id' => [
                Rule::requiredIf(fn () => $needsPractitionerDesk),
                'nullable',
                'integer',
                'exists:care_branches,id',
            ],
            'create_practitioner' => ['sometimes', 'boolean'],
            'practitioner_name' => ['nullable', 'string', 'max:255'],
            'specialty' => ['nullable', 'string', 'max:255', Rule::in(Practitioner::specialtyOptions())],
        ]);

        if (($validated['specialty'] ?? '') === '') {
            $validated['specialty'] = null;
        }

        if (! empty($validated['branch_id'])) {
            $branch = Branch::owned($owner)->findOrFail($validated['branch_id']);
            abort_unless($branch->organization_id === $organization->id, 404);
        }

        $email = strtolower(trim($validated['email']));

        if ($email === strtolower((string) $request->user()->email)) {
            return back()->withErrors(['email' => 'You cannot invite yourself.']);
        }

        $identity->inviteAppMember(
            $owner,
            $email,
            ['care'],
            [
                'care' => [
                    'organization_id' => $organization->id,
                    'role' => $validated['role'],
                    'branch_id' => $validated['branch_id'] ?? null,
                ],
            ],
        );

        $member = Member::updateOrCreate(
            [
                'organization_id' => $organization->id,
                'user_ref' => $email,
            ],
            [
                'owner_ref' => $owner,
                'role' => $validated['role'],
                'branch_id' => $validated['branch_id'] ?? null,
            ],
        );

        AuditLogger::record($owner, 'member.invited', $organization->id, $owner, Member::class, $member->id);

        $createPractitioner = $request->boolean(
            'create_practitioner',
            app(CarePermissions::class)->usesPractitionerBranchScope(new Member(['role' => $validated['role']])),
        );
        if ($createPractitioner) {
            $name = trim((string) ($validated['practitioner_name'] ?? '')) ?: Str::headline(Str::before($email, '@'));
            $practitioner = Practitioner::query()->firstOrCreate(
                [
                    'organization_id' => $organization->id,
                    'member_id' => $member->id,
                ],
                [
                    'owner_ref' => $owner,
                    'branch_id' => $validated['branch_id'] ?? null,
                    'user_ref' => $email,
                    'name' => $name,
                    'specialty' => $validated['specialty'] ?? null,
                    'is_active' => true,
                ],
            );

            if (! empty($validated['branch_id'])) {
                $practitioner->syncAssignedBranches([(int) $validated['branch_id']]);
            }
        }

        return redirect()->route('care.members.index')->with('success', 'Invitation sent to '.$email.'.');
    }

    public function destroy(Request $request, Member $member): RedirectResponse
    {
        $this->authorizeAbility($request, 'admin.members.manage');
        $this->authorizeOwner($request, $member);

        abort_if($member->user_ref === $this->actorRef($request), 422, 'You cannot remove yourself.');

        $memberId = $member->id;
        $organizationId = $member->organization_id;
        $member->delete();

        AuditLogger::record($this->ownerRef($request), 'member.deleted', $organizationId, $this->actorRef($request), Member::class, $memberId);

        return redirect()->route('care.members.index')->with('success', 'Member removed.');
    }
}
