<?php

declare(strict_types=1);

namespace App\Http\Controllers\Masters;

use App\Http\Controllers\Controller;
use App\Http\Requests\Masters\StoreTeamRequest;
use App\Http\Requests\Masters\UpdateTeamRequest;
use App\Models\Employee;
use App\Models\Team;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

/**
 * Teams.
 *
 * A plain resource controller with no service layer: nothing here spans more
 * than one model or needs a transaction, so a TeamService would be a file
 * that forwards to Eloquent.
 *
 * Deleting and restoring are guarded by the `master` middleware on those routes
 * rather than by a policy — the rule is "masters only", with no record-level
 * condition for a policy to express.
 */
class TeamController extends Controller
{
    public function index(Request $request): View
    {
        $showingDeleted = $request->boolean('trashed');

        $teams = Team::query()
            ->when($showingDeleted, fn ($query) => $query->onlyTrashed())
            ->with('headEmployee')
            ->search($request->string('search')->toString())
            ->when(
                $request->filled('status'),
                fn ($query) => $query->where('is_active', $request->string('status')->toString() === 'active'),
            )
            ->orderBy('name')
            ->paginate((int) setting('pagination_per_page', config('ams.pagination.per_page')))
            ->withQueryString();

        return view('masters.teams.index', [
            'teams' => $teams,
            'showingDeleted' => $showingDeleted,
            'deletedCount' => Team::onlyTrashed()->count(),
            'filters' => [
                'search' => $request->string('search')->toString(),
                'status' => $request->string('status')->toString(),
            ],
        ]);
    }

    public function create(): View
    {
        return view('masters.teams.create', [
            'team' => new Team(['is_active' => true]),
            'employees' => $this->headOptions(),
        ]);
    }

    public function store(StoreTeamRequest $request): RedirectResponse
    {
        // The Auditable trait records the creation.
        $team = Team::create($request->validated());

        return redirect()
            ->route('masters.teams.index')
            ->with('success', __('Team ":name" created.', ['name' => $team->name]));
    }

    public function edit(Team $team): View
    {
        return view('masters.teams.edit', [
            'team' => $team,
            'employees' => $this->headOptions(),
        ]);
    }

    public function update(UpdateTeamRequest $request, Team $team): RedirectResponse
    {
        // The Auditable trait records the change and its before/after diff.
        $team->update($request->validated());

        return redirect()
            ->route('masters.teams.index')
            ->with('success', __('Team ":name" updated.', ['name' => $team->name]));
    }

    public function destroy(Team $team): RedirectResponse
    {
        /*
         | Refuse rather than let the RESTRICT foreign key throw a raw database
         | error.
         */
        $employeeCount = $team->employees()->count();

        if ($employeeCount > 0) {
            return redirect()
                ->route('masters.teams.index')
                ->with('error', __('":name" has :employees and cannot be deleted. Move or reassign them first, or deactivate this team instead.', [
                    'name' => $team->name,
                    'employees' => trans_choice(
                        ':count employee|:count employees',
                        $employeeCount,
                        ['count' => $employeeCount],
                    ),
                ]));
        }

        $assetCount = $team->assets()->count();

        if ($assetCount > 0) {
            return redirect()
                ->route('masters.teams.index')
                ->with('error', __('":name" has :assets on the books and cannot be deleted. Reassign them first, or deactivate this team instead.', [
                    'name' => $team->name,
                    'assets' => trans_choice(
                        ':count asset|:count assets',
                        $assetCount,
                        ['count' => $assetCount],
                    ),
                ]));
        }

        $name = $team->name;

        $team->delete();

        return redirect()
            ->route('masters.teams.index')
            ->with('success', __('Team ":name" deleted. You can restore it from the deleted list.', [
                'name' => $name,
            ]));
    }

    /**
     * Bring a soft-deleted team back.
     */
    public function restore(Team $team): RedirectResponse
    {
        $team->restore();

        return redirect()
            ->route('masters.teams.index')
            ->with('success', __('Team ":name" restored.', ['name' => $team->name]));
    }

    /**
     * Every employee eligible to be picked as a team head.
     *
     * @return Collection<int, Employee>
     */
    private function headOptions(): Collection
    {
        return Employee::query()
            ->orderBy('first_name')
            ->orderBy('last_name')
            ->get();
    }
}
