<?php

namespace App\Services;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use App\Models\City;
use App\Models\Management;

/**
 * メニュー・アクセス制御サービス
 *
 * ログイン中のオペレータが属する運営元に基づいて、
 * 表示可能なメニュー項目およびアクセス可能な画面を制御します。
 * ソーリンは全メニュー/全画面OK、その他は所属自治体のみアクセス可。
 */
class MenuAccessService
{
    /**
     * ログイン中のオペレータを取得
     */
    private function getAuthOperator()
    {
        return Auth::user();
    }

    /**
     * ログイン中のオペレータが属する運営元を取得
     */
    private function getAuthManagement(): ?Management
    {
        $operator = $this->getAuthOperator();
        if (!$operator || !isset($operator->management_id)) {
            return null;
        }

        return Management::find($operator->management_id);
    }

    /**
     * ログイン中のオペレータがソーリンであるか判定
     *
     * ソーリン（management_name === 'ソーリン'）の場合は全メニュー表示可能
     *
     * @return bool true: ソーリン, false: その他
     */
    public function isSorin(): bool
    {
        $management = $this->getAuthManagement();
        if (!$management) {
            return false;
        }

        return $management->management_name === 'ソーリン';
    }

    /**
     * オペレータが表示可能な自治体リストを取得
     *
     * ソーリン: 全自治体（削除フラグなどは既存仕様に合わせる）
     * その他: ope.city_id で指定された1つの自治体のみ
     *
     * @return Collection<City>
     */
    public function visibleCities(): Collection
    {
        if ($this->isSorin()) {
            return City::query()
                ->orderBy('city_name')
                ->get();
        }

        // 非ソーリン時は ope.city_id で指定された自治体のみ
        $operator = $this->getAuthOperator();
        if (!$operator || !isset($operator->city_id)) {
            return collect();
        }

        // ope.city_id に一致する city のみを返す
        $city = City::find($operator->city_id);
        if (!$city) {
            return collect();
        }

        return collect([$city]);
    }

    /**
     * 指定された自治体へのアクセスが許可されているか判定
     *
     * ソーリン: 常に true
     * その他: city.management_id == ope.management_id の場合のみ true
     *
     * @param int $cityId 自治体ID
     * @return bool true: アクセス許可, false: アクセス拒否
     */
    public function canAccessCity(int $cityId): bool
    {
        if ($this->isSorin()) {
            return true;
        }

        $operator = $this->getAuthOperator();
        if (!$operator || !isset($operator->management_id)) {
            return false;
        }

        // city.management_id が ope.management_id と一致するか確認
        $city = City::find($cityId);
        if (!$city) {
            return false;
        }

        return (int)$city->management_id === (int)$operator->management_id;
    }

    /**
     * 複数の自治体へのアクセス許可を一括確認
     *
     * @param array<int> $cityIds 自治体IDの配列
     * @return bool すべての自治体へのアクセスが許可されている場合のみ true
     */
    public function canAccessCities(array $cityIds): bool
    {
        foreach ($cityIds as $cityId) {
            if (!$this->canAccessCity($cityId)) {
                return false;
            }
        }

        return true;
    }
}
