<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;

// モデル
use App\Models\OperatorQue;   // operator_que テーブル
use App\Models\User;          // 利用者候補（user_seq / user_name / user_mobile / user_homephone）
use App\Models\Park;          // 駐輪場候補（park_id / park_name）

class OperatorQueController extends Controller
{
    /**
     * 一覧
     * ルート: operator_ques
     */
    public function list(Request $request)
    {
        $sort      = $request->input('sort', 'que_id');
        $sort_type = $request->input('sort_type', 'asc');
        $que_status = $request->input('que_status');

        // 許可されたカラム名のリスト（DB定義に合わせて）
        $allowedSorts = ['que_id', 'ope_id', 'que_status', 'created_at', 'updated_at', 'user_id', 'park_id', 'que_class'];

        if (!in_array($sort, $allowedSorts)) {
            $sort = 'que_id';

        }

        if (!in_array($sort_type, ['asc', 'desc'])) {
            $sort_type = 'desc';
        }

        $query = OperatorQue::query();

        // フィルタリング（絞り込み）
        if (!empty($que_status)) {
            $query->where('que_status', $que_status);
        }

        $list = $query->orderBy($sort, $sort_type)
                    ->paginate(\App\Utils::item_per_page ?? 20);

        // view に $que_status を渡す
        return view('admin.operator_ques.list', compact('list', 'sort', 'sort_type', 'que_status'));
    }



    /**
     * 新規登録（画面/処理）
     */
    public function add(Request $request)
    {
        if ($request->isMethod('get')) {
            // 新規時は空のレコードを用意してフォーム描画
            return view('admin.operator_ques.add', array_merge(
                $this->formPayload(),
                [
                    'isEdit' => false,
                    'record' => new OperatorQue(), // ← ★ _form.blade.php で使う用
                    'que_id' => null,
                ]
            ));
        }

        // POST時：バリデーション
        $data = $this->validateRequest($request);

        // 登録処理
        OperatorQue::create($data);

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


    /**
     * 編集（画面/処理）
     */
    public function edit($id, Request $request)
    {
        $que = OperatorQue::findOrFail($id);

        if ($request->isMethod('get')) {
            return view('admin.operator_ques.edit', array_merge(
                $this->formPayload($que),
                [
                    'que_id' => $que->que_id,
                    'record' => $que,
                ]
            ));
        }

        $data = $this->validateRequest($request, $que->que_id);

        $que->fill($data)->save();

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

    /**
     * 詳細（参照）
     */
    public function info($id)
    {
        $que = OperatorQue::findOrFail($id);

        return view('admin.operator_ques.info', array_merge(
            $this->formPayload($que),
            ['que_id' => $que->que_id]
        ));
    }

    /**
     * 削除（複数可）
     */
    public function delete(Request $request)
    {
        $ids = [];
        if ($request->filled('id')) {
            $ids[] = (int) $request->input('id');
        }
        if (is_array($request->input('pk'))) {
            $ids = array_merge($ids, $request->input('pk'));
        }
        $ids = array_values(array_unique(array_map('intval', $ids)));

        if (!$ids) {
            return back()->with('error', '削除対象が選択されていません。');
        }

        OperatorQue::whereIn('que_id', $ids)->delete();

        return redirect()->route('operator_ques')->with('success', '削除しました。');
    }

    /**
     * CSV インポート
     */
    public function import(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'file' => 'required|file|mimes:csv,txt|max:20480',
        ]);
        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $file = $request->file('file')->getRealPath();
        if (!$handle = fopen($file, 'r')) {
            return back()->with('error', 'CSVを読み取れません。');
        }

        $header = fgetcsv($handle) ?: [];
        $header = array_map(fn($h) => trim(ltrim($h ?? '', "\xEF\xBB\xBF")), $header);

        $fillable = (new OperatorQue())->getFillable();
        $rows = [];

        while (($row = fgetcsv($handle)) !== false) {
            $assoc = [];
            foreach ($header as $i => $key) {
                if (in_array($key, $fillable, true)) {
                    $assoc[$key] = $row[$i] ?? null;
                }
            }
            if ($assoc) {
                $rows[] = $assoc;
            }
        }
        fclose($handle);

        DB::transaction(function () use ($rows) {
            foreach ($rows as $data) {
                OperatorQue::create($data);
            }
        });

        return redirect()->route('operator_ques')->with('success', count($rows) . '件をインポートしました。');
    }

    /**
     * CSV エクスポート
     */
    public function export(): StreamedResponse
    {
        $filename = 'operator_que_' . now()->format('Ymd_His') . '.csv';
        $fillable = (new OperatorQue())->getFillable(); // 見出しは fillable を流用

        $response = new StreamedResponse(function () use ($fillable) {
            $out = fopen('php://output', 'w');
            // UTF-8 BOM
            fprintf($out, chr(0xEF) . chr(0xBB) . chr(0xBF));

            fputcsv($out, $fillable);

            OperatorQue::orderBy('que_id')->chunk(500, function ($chunk) use ($out, $fillable) {
                foreach ($chunk as $row) {
                    $line = [];
                    foreach ($fillable as $f) {
                        $line[] = $row->$f ?? '';
                    }
                    fputcsv($out, $line);
                }
            });
            fclose($out);
        });

        $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
        $response->headers->set('Content-Disposition', "attachment; filename={$filename}");

        return $response;
    }

    /**
     * フォームに渡す値/候補
     */
    private function formPayload(?OperatorQue $que = null): array
    {
        // 値
        $payload = [
            'que_id'             => $que->que_id            ?? '',
            'user_id'            => $que->user_id           ?? '',
            'contract_id'        => $que->contract_id       ?? '',
            'park_id'            => $que->park_id           ?? '',
            'que_class'          => $que->que_class         ?? '',
            'que_comment'        => $que->que_comment       ?? '',
            'que_status'         => $que->que_status        ?? '',
            'que_status_comment' => $que->que_status_comment?? '',
            'work_instructions'  => $que->work_instructions ?? '',
        ];

        // 候補
        $payload['users'] = $this->fetchUsers();
        $payload['parks'] = $this->fetchParks();

        return $payload;
    }

    /**
     * バリデーション
     * ※ 実テーブルの型に合わせて必要に応じて調整
     */
    private function validateRequest(Request $request, $queId = null): array
    {
        $rules = [
            'user_id'            => 'nullable|integer',
            'contract_id'        => 'nullable|integer',
            'park_id'            => 'nullable|integer',
            'que_class'          => 'required|integer',  
            'que_comment'        => 'nullable|string|max:2000',
            'que_status'         => 'required|integer',   
            'que_status_comment' => 'nullable|string|max:2000',
            'work_instructions'  => 'nullable|string|max:2000',
            // 'operator_id'      => 'nullable|integer',  // ログインユーザIDを使うなら不要
        ];

        return $request->validate($rules);
    }

    /**
     * 利用者候補（user_seq, user_name, user_mobile, user_homephone）
     * Blade 側では $users をそのまま @foreach
     */
    private function fetchUsers()
    {
        try {
            return User::select('user_seq', 'user_name', 'user_mobile', 'user_homephone')
                ->orderBy('user_name')
                ->get();
        } catch (\Throwable $e) {
            return DB::table('users')
                ->select(['user_seq', 'user_name', 'user_mobile', 'user_homephone'])
                ->orderBy('user_name')
                ->get();
        }
    }

    /**
     * 駐輪場候補（park_id => park_name）
     */
    private function fetchParks()
    {
        try {
            return Park::orderBy('park_name')->pluck('park_name', 'park_id');
        } catch (\Throwable $e) {
            return DB::table('parks')->orderBy('park_name')->pluck('park_name', 'park_id');
        }
    }
}
