<?php

namespace App\Http\Controllers;

use App\Http\Traits\AuthenticatesUser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;

class ParkDetailController extends Controller
{
    use AuthenticatesUser;

    /**
     * 駐輪場詳細情報を取得（Ajax用）
     * 
     * @param string $management_code
     * @param int $park_id
     * @return \Illuminate\Http\JsonResponse
     */
    public function show($management_code, $park_id)
    {
        if ($redirect = $this->handleSessionExpired('駐輪場詳細', false)) {
            return $redirect;
        }

        $userId = session('user_id');
        $management = session('management');
        if (!$management) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 運営元情報取得失敗 user_id=" . $userId);
            return response()->json(['error' => 'Management not found'], 404);
        }

        // マルチテナント対応：運営元に紐づく駐輪場のみ取得
        $park = $this->getParkInfo($park_id, $management->management_id);
        if (!$park) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場情報取得失敗 park_id=" . $park_id . ", management_id=" . $management->management_id . ", user_id=" . $userId);
            return response()->json(['error' => 'Park not found'], 404);
        }

        // ゾーン情報取得
        $zones = $this->getZones($park_id);

        // 予約情報取得
        $reserves = $this->getReserves($park_id);

        // 車種別の基準台数集計
        $zoneStandardSum = $this->calculateZoneStandardSum($zones);

        // 車種別の空き台数計算
        $vacancyData = $this->calculateVacancy($zones, $reserves);

        // 駐輪場ごとの更新可能期間取得
        $parkGracePeriod = $this->getParkGracePeriod($park_id);

        \Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " 駐輪場詳細取得成功 park_id=" . $park_id . ", management_id=" . $management->management_id . ", user_id=" . $userId);

        try {
            $html = view('regular_contract.park_detail', compact(
                'park',
                'zones',
                'reserves',
                'zoneStandardSum',
                'vacancyData',
                'parkGracePeriod'
            ))->render();

            \Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " ビュー生成成功 park_id=" . $park_id . ", HTML長=" . strlen($html));


            return response()->json(['html' => $html]);
        } catch (\Exception $e) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " ビュー生成失敗 park_id=" . $park_id . ", error=" . $e->getMessage());
            return response()->json(['error' => 'View rendering failed'], 500);
        }
    }

    /**
     * 駐輪場情報取得（マルチテナントフィルタ適用）
     * 
     * 運営元に紐づく駐輪場のみを取得することで、他の運営元のデータが
     * 誤って表示されることを防ぐ。
     * 
     * @param int $parkId
     * @param int $managementId
     * @return object|null
     */
    private function getParkInfo(int $parkId, int $managementId)
    {
        try {
            return DB::table('park')
                ->where('park_id', $parkId)
                ->where('management_id', $managementId)
                ->first();
        } catch (\Exception $e) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場情報取得エラー park_id=" . $parkId . ", error=" . $e->getMessage());
            return null;
        }
    }

    /**
     * ゾーン情報取得
     * 
     * @param int $parkId
     * @return \Illuminate\Support\Collection
     */
    private function getZones(int $parkId)
    {
        try {
            return DB::table('zone')
                ->leftJoin('psection', 'zone.psection_id', '=', 'psection.psection_id')
                ->leftJoin('ptype', 'zone.ptype_id', '=', 'ptype.ptype_id')
                ->select(
                    'zone.*',
                    'psection.psection_subject',
                    'ptype.ptype_subject'
                )
                ->where('zone.park_id', $parkId)
                ->get();
        } catch (\Exception $e) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " zone情報取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
            return collect();
        }
    }

    /**
     * 予約情報取得
     * 
     * @param int $parkId
     * @return \Illuminate\Support\Collection
     */
    private function getReserves(int $parkId)
    {
        try {
            return DB::table('reserve')
                ->join('zone', function ($join) {
                    $join->on('reserve.psection_id', '=', 'zone.psection_id')
                        ->on('reserve.ptype_id', '=', 'zone.ptype_id');
                })
                ->join('ptype', 'zone.ptype_id', '=', 'ptype.ptype_id')
                ->where('reserve.park_id', $parkId)
                ->where('reserve.valid_flag', 1)
                ->select('reserve.*', 'ptype.ptype_subject')
                ->get();
        } catch (\Exception $e) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " reserve情報取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
            return collect();
        }
    }

    /**
     * 車種別の基準台数集計
     * 
     * 駐輪場の車種別定員（zone_standard の合計）を算出する。
     * 
     * @param \Illuminate\Support\Collection $zones
     * @return array
     */
    private function calculateZoneStandardSum($zones)
    {
        $zoneStandardSum = [];

        foreach ($zones as $zone) {
            $key = $zone->psection_subject; // 「自転車」「原付」など
            if (!isset($zoneStandardSum[$key])) {
                $zoneStandardSum[$key] = 0;
            }
            $zoneStandardSum[$key] += $zone->zone_standard;
        }

        return $zoneStandardSum;
    }

    /**
     * 車種別の空き台数計算
     * 
     * 予約を考慮した実際の空き台数を算出する。
     * 許容台数から現在台数を引き、さらに有効な予約件数分を減算することで、正確な空き状況を把握する。
     * 
     * @param \Illuminate\Support\Collection $zones
     * @param \Illuminate\Support\Collection $reserves
     * @return array
     */
    private function calculateVacancy($zones, $reserves)
    {
        $vacancyData = [];

        // zone_tolerance - zone_number を集計
        foreach ($zones as $zone) {
            $key = $zone->psection_id . '_' . $zone->ptype_subject;
            if (!isset($vacancyData[$key])) {
                $vacancyData[$key] = 0;
            }
            $vacancyData[$key] += ($zone->zone_tolerance - $zone->zone_number);
        }

        // reserve件数分を減算
        foreach ($reserves as $reserve) {
            $key = $reserve->psection_id . '_' . $reserve->ptype_subject;
            if (isset($vacancyData[$key])) {
                $vacancyData[$key] -= 1;
            }
        }

        return $vacancyData;
    }

    /**
     * 駐輪場の更新可能期間取得
     * 
     * @param int $parkId
     * @return object|null
     */
    private function getParkGracePeriod(int $parkId)
    {
        try {
            return DB::table('park')
                ->select(
                    'park_id',
                    'update_grace_period_start_date',
                    'update_grace_period_start_time',
                    'update_grace_period_end_date',
                    'update_grace_period_end_time'
                )
                ->where('park_id', $parkId)
                ->first();
        } catch (\Exception $e) {
            \Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場更新可能期間取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
            return null;
        }
    }

    public function showWait($reserve_id)
    {
        $reserve = DB::table('reserve')->where('reserve_id', $reserve_id)->first();
        $park = DB::table('park')->where('park_id', $reserve->park_id)->first();

        $zones = DB::table('zone')
            ->leftJoin('psection', 'zone.psection_id', '=', 'psection.psection_id')
            ->leftJoin('ptype', 'zone.ptype_id', '=', 'ptype.ptype_id')
            ->select('zone.*', 'psection.psection_subject', 'ptype.ptype_subject')
            ->where('zone.park_id', $park->park_id)
            ->get();

        $zoneStandardSum = [];
        foreach ($zones as $zone) {
            $key = $zone->psection_subject; // 「自転車」「原付」など
            if (!isset($zoneStandardSum[$key])) {
                $zoneStandardSum[$key] = 0;
            }
            $zoneStandardSum[$key] += $zone->zone_standard;
        }

        // 必要なら他テーブルJOINや追加情報も取得
        return response()->json([
            'html' => view('park_waitlist.park_detail', compact('park', 'zones', 'reserve', 'zoneStandardSum'))->render()
        ]);
    }
}
