<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\ParkRequest;
use App\Models\City;
use App\Services\ParkService;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ParkController extends Controller
{
    public function __construct(
        private readonly ParkService $parkService
    ) {
    }

    /**
     * 一覧
     * Route: GET /parks  name=parks  -> list()
     */
    public function list(ParkRequest $request)
    {
        $filters = $request->filters();

        $parks = $this->parkService->paginate($filters, \App\Utils::item_per_page);

        $cities = City::orderBy('city_id')->get();

        $sort      = $filters['sort'] ?? 'p.park_id';
        $sort_type = $filters['sort_type'] ?? 'asc';

        // list.blade.php
        return view('admin.parks.list', compact(
            'parks',
            'cities',
            'sort',
            'sort_type'
        ));
    }

    /**
     * 新規（画面）
     * Route: GET /parks/add name=parks.add -> add()
     */
    public function add()
    {
        $cities = City::orderBy('city_id')->get();

        // add.blade.php
        return view('admin.parks.add', compact('cities'));
    }

    /**
     * 新規（登録）
     * Route: POST /parks/add name=parks.store -> store()
     */
    public function store(ParkRequest $request)
    {
        $operatorId = (int) (auth()->user()->ope_id ?? 1);

        $payload = $request->payload();

        // 駐輪場五十音を設定
        $payload['park_syllabary'] = $this->toSyllabaryGroup(
            $payload['park_ruby'] ?? null
        );

        // 駐輪場五十音を設定してから Service に渡す
        $this->parkService->create(
            $payload,
            $operatorId
        );

        return redirect()
            ->route('parks')
            ->with('success', __('新規登録に完了しました。'));
    }

    /**
     * 編集（画面）
     * Route: GET /parks/edit/{id} name=parks.edit -> edit()
     */
    public function edit(int $id)
    {
        $record = $this->parkService->findOrFail($id);
        $cities = City::orderBy('city_id')->get();

        // edit.blade.php
        return view('admin.parks.edit', compact(
            'record',
            'cities'
        ));
    }

    /**
     * 編集（更新）
     * Route: PUT /parks/edit/{id} name=parks.update -> update()
     */
    public function update(ParkRequest $request, int $id)
    {
        $park = $this->parkService->findOrFail($id);

        $operatorId = (int) (auth()->user()->ope_id ?? 1);

        $payload = $request->payload();

        // 駐輪場五十音を設定
        $payload['park_syllabary'] = $this->toSyllabaryGroup(
            $payload['park_ruby'] ?? null
        );

        // ※二重更新をやめる（payload 上書き事故防止）
        $this->parkService->update(
            $park,
            $payload,
            $operatorId
        );

        return redirect()
            ->route('parks')
            ->with('success', __('更新に成功しました。'));
    }

    /**
     * 削除（複数）
     * Route: POST /parks/delete name=parks.delete -> delete()
     */
    public function delete(Request $request)
    {
        $ids = (array) $request->input('pk', []);

        if (empty($ids)) {
            return redirect()
                ->route('parks')
                ->with('error', __('削除するデータを選択してください。'));
        }

        $ok = $this->parkService->deleteByIds($ids);

        return redirect()
            ->route('parks')
            ->with(
                $ok ? 'success' : 'error',
                $ok ? __('削除が完了しました。') : __('削除に失敗しました。')
            );
    }

    /**
     * CSV 出力
     * Route: GET /parks/export name=parks.export -> export()
     */
    public function export(): StreamedResponse
    {
        $columns = [
            '駐輪場ID','市区','駐輪場名','駐輪場ふりがな','駐輪場五十音','住所',
            '閉設フラグ','閉設日','残警告チェックフラグ','印字数','最新キープアライブ',
            '更新オペレータID','更新期間開始日','更新期間開始時',
            '更新期間終了日','更新期間終了時','駐輪開始期間',
            'リマインダー種別','リマインダー時間','契約後即利用許可',
            '項目表示設定：性別','項目表示設定：生年月日','項目表示設定：防犯登録番号',
            '二点間距離','駐車場座標（緯度）','駐車場座標（経度）','電話番号',
            '駐輪場契約形態（定期）','駐輪場契約形態（一時利用）',
            '車種制限','手続方法','支払方法',
            '利用可能時間制限フラグ','利用可能時間（開始）','利用可能時間（終了）',
            '常駐管理人フラグ','常駐時間（開始）','常駐時間（終了）',
            '屋根フラグ','シール発行機フラグ','駐輪場利用方法',
            '定期更新期間','空き待ち予約','特記事項','学生証確認種別',
            '減免案内表示フラグ','減免対象年齢','減免案内表示開始月数','年跨ぎ',
        ];

        $rows = $this->parkService->exportRows();

        return response()->streamDownload(function () use ($rows, $columns) {
            $fp = fopen('php://output', 'w');

            fwrite($fp, "\xEF\xBB\xBF");
            fputcsv($fp, $columns);

            foreach ($rows as $r) {
                fputcsv($fp, [
                    $r->park_id,
                    $r->city_id,
                    $r->park_name,
                    $r->park_ruby,
                    $r->park_syllabary,
                    $r->park_adrs,
                    $r->park_close_flag,
                    $r->park_day,
                    $r->alert_flag,
                    $r->print_number,
                    $r->keep_alive,
                    $r->operator_id,
                    $r->update_grace_period_start_date,
                    $r->update_grace_period_start_time,
                    $r->update_grace_period_end_date,
                    $r->update_grace_period_end_time,
                    $r->parking_start_grace_period,
                    $r->reminder_type,
                    $r->reminder_time,
                    $r->immediate_use_permit,
                    $r->gender_display_flag,
                    $r->bd_display_flag,
                    $r->securityreg_display_flag,
                    $r->distance_twopoints,
                    $r->park_latitude,
                    $r->park_longitude,
                    $r->park_tel,
                    $r->park_fixed_contract,
                    $r->park_temporary_contract,
                    $r->park_restriction,
                    $r->park_procedure,
                    $r->park_payment,
                    $r->park_available_time_flag,
                    $r->park_available_time_from,
                    $r->park_available_time_to,
                    $r->park_manager_flag,
                    $r->park_manager_resident_from,
                    $r->park_manager_resident_to,
                    $r->park_roof_flag,
                    $r->park_issuing_machine_flag,
                    $r->park_using_method,
                    $r->park_contract_renewal_term,
                    $r->park_reservation,
                    $r->park_reference,
                    $r->student_id_confirm_type,
                    $r->reduction_guide_display_flag,
                    $r->reduction_age,
                    $r->reduction_guide_display_start_month,
                    $r->overyear_flag,
                ]);
            }

            fclose($fp);
        }, '駐輪場マスタ.csv', [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }

    /**
     * 重複チェック（AJAX）
     * Route: POST /parks/check-duplicate name=parks.check_duplicate -> checkDuplicate()
     */
    public function checkDuplicate(Request $request)
    {
        $parkName = (string) $request->input('park_name', '');

        if ($parkName === '') {
            return response()->json(['duplicate' => false]);
        }

        $dup = $this->parkService->checkDuplicateByName($parkName);

        if (!$dup) {
            return response()->json(['duplicate' => false]);
        }

        return response()->json([
            'duplicate' => true,
            'park_id'   => $dup->park_id,
            'park_name' => $dup->park_name,
        ]);
    }

    private function toSyllabaryGroup(?string $ruby): ?string
    {
        $ruby = trim((string) $ruby);
        if ($ruby === '') {
            return null;
        }

        // 先取第1文字（UTF-8）
        $first = mb_substr($ruby, 0, 1, 'UTF-8');

        // 小書き/濁点などを正規化（必要最低限）
        $map = [
            'が'=>'か','ぎ'=>'き','ぐ'=>'く','げ'=>'け','ご'=>'こ',
            'ざ'=>'さ','じ'=>'し','ず'=>'す','ぜ'=>'せ','ぞ'=>'そ',
            'だ'=>'た','ぢ'=>'ち','づ'=>'つ','で'=>'て','ど'=>'と',
            'ば'=>'は','び'=>'ひ','ぶ'=>'ふ','べ'=>'へ','ぼ'=>'ほ',
            'ぱ'=>'は','ぴ'=>'ひ','ぷ'=>'ふ','ぺ'=>'へ','ぽ'=>'ほ',
            'ぁ'=>'あ','ぃ'=>'い','ぅ'=>'う','ぇ'=>'え','ぉ'=>'お',
            'ゃ'=>'や','ゅ'=>'ゆ','ょ'=>'よ','っ'=>'つ',
            'ゎ'=>'わ',
        ];
        $first = $map[$first] ?? $first;

        // グループ判定（先頭文字で分類）
        $groups = [
            'あ' => ['あ','い','う','え','お'],
            'か' => ['か','き','く','け','こ'],
            'さ' => ['さ','し','す','せ','そ'],
            'た' => ['た','ち','つ','て','と'],
            'な' => ['な','に','ぬ','ね','の'],
            'は' => ['は','ひ','ふ','へ','ほ'],
            'ま' => ['ま','み','む','め','も'],
            'や' => ['や','ゆ','よ'],
            'ら' => ['ら','り','る','れ','ろ'],
            'わ' => ['わ','を','ん'],
        ];

        foreach ($groups as $head => $chars) {
            if (in_array($first, $chars, true)) {
                return $head;
            }
        }

        // ひらがな以外（空/英数など）は null
        return null;
    }
}
