<?php

namespace App\Services;

use App\Models\Branch;
use App\Models\Tenant;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

class BranchService
{
    public const HEAD_OFFICE_CODE = 'HQ';
    public const HEAD_OFFICE_NAME = 'Head Office';

    public function activeBranchesFor(Tenant $tenant): Collection
    {
        $this->defaultBranch($tenant);

        return Branch::withoutGlobalScopes()
            ->where('tenant_id', $tenant->id)
            ->where('is_active', true)
            ->orderByRaw("CASE WHEN code = ? THEN 0 ELSE 1 END", [self::HEAD_OFFICE_CODE])
            ->orderBy('name')
            ->get();
    }

    public function defaultBranch(Tenant $tenant): Branch
    {
        $activeBranches = Branch::withoutGlobalScopes()
            ->where('tenant_id', $tenant->id)
            ->where('is_active', true)
            ->orderBy('id')
            ->get();

        if ($activeBranches->count() === 1) {
            return $activeBranches->first();
        }

        $headOffice = $activeBranches->firstWhere('code', self::HEAD_OFFICE_CODE)
            ?: $activeBranches->firstWhere('name', self::HEAD_OFFICE_NAME);

        if ($headOffice) {
            return $headOffice;
        }

        $branch = Branch::withoutGlobalScopes()->firstOrCreate(
            ['tenant_id' => $tenant->id, 'code' => self::HEAD_OFFICE_CODE],
            [
                'name' => self::HEAD_OFFICE_NAME,
                'address' => $tenant->address,
                'phone' => $tenant->phone,
                'is_active' => true,
            ],
        );

        if (! $branch->is_active) {
            $branch->forceFill(['is_active' => true])->save();
        }

        return $branch;
    }

    public function shouldShowBranchField(Collection $branches): bool
    {
        return $branches->count() > 1;
    }

    public function formState(User $user, ?int $selectedBranchId = null): array
    {
        if (! $user->tenant) {
            throw new AuthorizationException('This account is not attached to a tenant.');
        }

        $branches = $this->activeBranchesFor($user->tenant);
        $defaultBranchId = $selectedBranchId ?: $this->defaultBranch($user->tenant)->id;

        return [
            'branches' => $branches,
            'showBranchField' => $this->shouldShowBranchField($branches),
            'defaultBranchId' => $defaultBranchId,
        ];
    }

    public function resolveSubmittedBranchId(Request $request, ?int $fallbackBranchId = null): ?int
    {
        $user = $request->user();

        if (! $user?->tenant) {
            return null;
        }

        $branches = $this->activeBranchesFor($user->tenant);

        if ($branches->isEmpty()) {
            return null;
        }

        $submitted = $request->input('branch_id');

        if ($this->shouldShowBranchField($branches) && filled($submitted)) {
            return (int) $submitted;
        }

        if (! $this->shouldShowBranchField($branches)) {
            return (int) $branches->first()->id;
        }

        if ($fallbackBranchId && $branches->contains('id', $fallbackBranchId)) {
            return $fallbackBranchId;
        }

        return $this->defaultBranch($user->tenant)->id;
    }
}
