<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Manager;
use App\Models\Park;
use App\Models\Device;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ManagerController extends Controller
{
    /** 一覧 */
    public function list(Request $request)
    {
        $sortable = [
            'manager_id','manager_name','manager_parkid','manager_tel',
            'manager_alert1','manager_alert2','manager_quit_flag'
        ];
        $sort      = $request->input('sort', 'manager_id');
        $sort_type = $request->input('sort_type', 'asc');
        if (!in_array($sort, $sortable)) $sort = 'manager_id';
        if (!in_array(strtolower($sort_type), ['asc','desc'])) $sort_type = 'asc';

        $list = Manager::with(['park','device1','device2'])
            ->orderBy($sort, $sort_type)
            ->paginate(20);

        return view('admin.managers.list', compact('list','sort','sort_type'));
    }

    /** 新規登録画面・登録処理 */
    public function add(Request $request)
    {
        if ($request->isMethod('post')) {
            $validated = $this->validated($request);

            Manager::create($validated);

            return redirect()
                ->route('managers')
                ->with('success', '登録しました。');
        }

        return view('admin.managers.add', $this->viewVars());
    }

    /** 編集（GET:画面表示 / POST:更新） */
    public function edit(Request $request, $id)
    {
        $manager = Manager::findOrFail($id);

        if ($request->isMethod('post')) {
            $validated = $this->validated($request);

            $manager->update($validated);

            return redirect()
                ->route('managers')
                ->with('success', '更新されました。');
        }

        return view('admin.managers.edit', $this->viewVars($manager));
    }

    /** 詳細（閲覧） */
    public function info($manager_id)
    {
        $manager = Manager::with(['park','device1','device2'])->findOrFail($manager_id);
        $view = $this->viewVars($manager);
        return view('admin.managers.info', $view);
    }

    /** 一括削除（一覧・詳細・編集共通で pk[] を受ける） */
    public function delete(Request $request)
    {
        $ids = (array) $request->input('pk', []);
        if (!$ids) {
            return back()->with('error', '削除対象が選択されていません。');
        }

        DB::transaction(fn() => Manager::whereIn('manager_id', $ids)->delete());

        // 一覧画面へリダイレクト + 成功メッセージ
        return redirect()
            ->route('managers')
            ->with('success', '削除しました。');
    }


    /** CSV出力 */
    public function export(): StreamedResponse
    {
        $headers = [
            'Content-Type'        => 'text/csv; charset=UTF-8',
            'Content-Disposition' => 'attachment; filename=managers.csv',
        ];

        $columns = [
            'manager_id','manager_name','manager_type','manager_parkid',
            'manager_device1','manager_device2','manager_mail','manager_tel',
            'manager_alert1','manager_alert2','manager_quit_flag','manager_quitday'
        ];

        return response()->stream(function () use ($columns) {
            $out = fopen('php://output', 'w');
            fwrite($out, "\xEF\xBB\xBF"); // BOM
            fputcsv($out, $columns);

            Manager::chunk(500, function ($rows) use ($out, $columns) {
                foreach ($rows as $r) {
                    fputcsv($out, array_map(fn($c) => data_get($r, $c), $columns));
                }
            });

            fclose($out);
        }, 200, $headers);
    }

    /** CSVインポート（input name="file"） */
    public function import(Request $request)
    {
        if (!$request->hasFile('file')) {
            return back()->with('error', 'CSVファイルを選択してください。');
        }
        $fp = fopen($request->file('file')->getRealPath(), 'r');
        if (!$fp) return back()->with('error', 'CSVを読み込めませんでした。');

        $header = fgetcsv($fp);
        if (!$header) { fclose($fp); return back()->with('error', 'ヘッダ行が読み取れません。'); }

        $required = [
            'manager_id','manager_name','manager_type','manager_parkid',
            'manager_device1','manager_device2','manager_mail','manager_tel',
            'manager_alert1','manager_alert2','manager_quit_flag','manager_quitday'
        ];
        foreach ($required as $c) {
            if (!in_array($c, $header)) { fclose($fp); return back()->with('error', "CSVに {$c} がありません。"); }
        }

        DB::beginTransaction();
        try {
            while (($row = fgetcsv($fp)) !== false) {
                $data = array_combine($header, $row); if (!$data) continue;

                Manager::updateOrCreate(
                    ['manager_id' => $data['manager_id']],
                    [
                        'manager_name'      => $data['manager_name']      ?? null,
                        'manager_type'      => $data['manager_type']      ?? null,
                        'manager_parkid'    => $data['manager_parkid']    ?: null,
                        'manager_device1'   => $data['manager_device1']   ?: null,
                        'manager_device2'   => $data['manager_device2']   ?: null,
                        'manager_mail'      => $data['manager_mail']      ?? null,
                        'manager_tel'       => $data['manager_tel']       ?? null,
                        'manager_alert1'    => (int)($data['manager_alert1'] ?? 0),
                        'manager_alert2'    => (int)($data['manager_alert2'] ?? 0),
                        'manager_quit_flag' => (int)($data['manager_quit_flag'] ?? 0),
                        'manager_quitday'   => $data['manager_quitday']   ?: null,
                    ]
                );
            }
            fclose($fp);
            DB::commit();
            return back()->with('success', 'インポートが完了しました。');
        } catch (\Throwable $e) {
            if (is_resource($fp)) fclose($fp);
            DB::rollBack();
            return back()->with('error', 'インポートに失敗しました：'.$e->getMessage());
        }
    }

    /** バリデーション + 前処理 */
    private function validated(Request $request): array
    {
        // 電話番号を全角に変換（半角入力があっても自動で全角に揃える）
        $request->merge([
            'manager_tel' => mb_convert_kana($request->input('manager_tel'), 'N')  // 半角数字→全角数字
        ]);

        // select の未選択 "" を null に補正
        foreach (['manager_device2'] as $f) {
            if ($request->input($f) === "") {
                $request->merge([$f => null]);
            }
        }

        return $request->validate([
            'manager_name'      => ['required','string','max:32'],
            'manager_type'      => ['required','string','max:10'],
            'manager_parkid'    => ['required','integer','exists:park,park_id'],
            'manager_device1'   => ['required','integer','exists:device,device_id'],
            'manager_device2'   => ['nullable','integer','exists:device,device_id'],
            'manager_mail'      => ['nullable','email','max:128'],
            'manager_tel'       => ['required','regex:/^[０-９]+$/u','max:13'], // 全角数字のみ
            'manager_alert1'    => ['nullable','boolean'],
            'manager_alert2'    => ['nullable','boolean'],
            'manager_quit_flag' => ['required','in:0,1'],
            'manager_quitday'   => ['nullable','date'],
        ], [], [
            'manager_name'      => '駐輪場管理者名',
            'manager_type'      => '種別',
            'manager_parkid'    => '所属駐輪場ID',
            'manager_device1'   => '管理デバイス1',
            'manager_device2'   => '管理デバイス2',
            'manager_mail'      => 'メールアドレス',
            'manager_tel'       => '電話番号',
            'manager_alert1'    => 'アラート1送信',
            'manager_alert2'    => 'アラート2送信',
            'manager_quit_flag' => '退職フラグ',
            'manager_quitday'   => '退職日',
        ]);
    }


    /** 画面に渡す変数を作る（_form.blade.php が個別変数を参照するため） */
    private function viewVars(?Manager $m = null): array
    {
        $parks   = Park::orderBy('park_name')->pluck('park_name','park_id')->toArray();
        $devices = Device::orderBy('device_subject')->pluck('device_subject','device_id')->toArray();

        return [
            // _form が参照する個別変数
            'manager_id'        => $m->manager_id        ?? null,
            'manager_name'      => $m->manager_name      ?? null,
            'manager_type'      => $m->manager_type      ?? null,
            'manager_parkid'    => $m->manager_parkid    ?? null,
            'manager_device1'   => $m->manager_device1   ?? null,
            'manager_device2'   => $m->manager_device2   ?? null,
            'manager_mail'      => $m->manager_mail      ?? null,
            'manager_tel'       => $m->manager_tel       ?? null,
            'manager_alert1'    => (int)($m->manager_alert1 ?? 0),
            'manager_alert2'    => (int)($m->manager_alert2 ?? 0),
            'manager_quit_flag' => isset($m) ? (int)$m->manager_quit_flag : 0,
            'manager_quitday'   => isset($m) && $m->manager_quitday ? $m->manager_quitday->format('Y-m-d') : null,

            // セレクトの候補
            'parks'   => $parks,
            'devices' => $devices,

            // _form で必要なフラグ（各ビューで上書きしてもOK）
            'isEdit'  => isset($m),
            'isInfo'  => false,
            'record'  => $m,  // 互換用（あなた的 edit.blade.php で参照しているなら）
        ];
    }
}
