<?php
namespace App\Http\Controllers\Admin;

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

class OpeController extends Controller
{
    /**
     * 一覧
     */
    public function list(Request $request)
    {
        $inputs = [
            'isMethodPost' => $request->isMethod('post'),
            'sort'         => $request->input('sort', 'ope_id'),
            'sort_type'    => $request->input('sort_type', 'desc'),
            'isExport'     => false,
        ];

        // Blade 側は $list / $sort / $sort_type を参照
        $list       = Ope::search($inputs);
        $sort       = $inputs['sort'];
        $sort_type  = $inputs['sort_type'];

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

    /**
     * 新規登録（GET 画面 / POST 保存）
     */
    public function add(Request $request)
    {
        if ($request->isMethod('get')) {
            // add.blade.php は include する _form が期待する変数名を使う
            return view('admin.opes.add', [
                'isEdit' => 0,
                'isInfo' => 0,
                // 初期値（存在しなくてもOKだが、Notice 防止のために入れておく）
                'ope_id'   => null,
                'ope_name' => '',
                'ope_type' => '',
                'ope_mail' => '',
                'ope_phone'=> '',
                // 以下はフォームで参照される可能性のあるキーを空で用意
                'ope_sendalart_que1' => 0, 'ope_sendalart_que2' => 0, 'ope_sendalart_que3' => 0,
                'ope_sendalart_que4' => 0, 'ope_sendalart_que5' => 0, 'ope_sendalart_que6' => 0,
                'ope_sendalart_que7' => 0, 'ope_sendalart_que8' => 0, 'ope_sendalart_que9' => 0,
                'ope_sendalart_que10'=> 0, 'ope_sendalart_que11'=> 0, 'ope_sendalart_que12'=> 0,
                'ope_sendalart_que13'=> 0,
                'ope_auth1' => '', 'ope_auth2' => '', 'ope_auth3' => '', 'ope_auth4' => '',
                'ope_quit_flag' => 0, 'ope_quitday' => '',
            ]);
        }

        $rules = [
            'ope_name'  => 'required|string|max:255',
            'ope_type'  => 'required|string|max:50',
            'ope_mail'  => 'nullable|email|max:255',
            'ope_phone' => 'nullable|string|max:50',
        ];
        $this->validate($request, $rules);

        $ope = new Ope();
        $ope->fill($request->only($ope->getFillable()));
        $ope->save();

        return redirect()->route('opes')->with('success', 'オペレータを登録しました。');
    }

    /**
     * 編集（GET 画面 / POST 更新）
     */
    public function edit($id, Request $request)
    {
        $ope = Ope::getByPk($id);
        if (!$ope) abort(404);

        if ($request->isMethod('get')) {
            // edit.blade.php が参照する変数名に合わせて渡す
            return view('admin.opes.edit', array_merge(
                [
                    'isEdit' => 1,
                    'isInfo' => 0,
                    'ope_id' => $ope->ope_id,
                ],
                $ope->toArray()
            ));
        }

        $rules = [
            'ope_name'  => 'required|string|max:255',
            'ope_type'  => 'required|string|max:50',
            'ope_mail'  => 'nullable|email|max:255',
            'ope_phone' => 'nullable|string|max:50',
        ];
        $this->validate($request, $rules);

        $ope->fill($request->only($ope->getFillable()));
        $ope->save();

        return redirect()->route('opes')->with('success', 'オペレータを更新しました。');
    }

    /**
     * 詳細
     */
    public function info($id)
    {
        $ope = Ope::getByPk($id);
        if (!$ope) abort(404);

        // info.blade.php が参照する変数に合わせてセット
        return view('admin.opes.info', array_merge(
            [
                'isEdit' => 0,
                'isInfo' => 1,
                'ope_id' => $ope->ope_id,
            ],
            $ope->toArray()
        ));
    }

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

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

        Ope::deleteByPk($ids);

        return redirect()->route('opes')->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();
        $handle = fopen($file, 'r');
        if (!$handle) return back()->with('error', 'CSVを読み取れません。');

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

        $fillable = (new Ope())->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) {
                Ope::create($data);
            }
        });

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

    /**
     * CSVエクスポート
     */
    public function export(): StreamedResponse
    {
        $filename = 'ope_' . now()->format('Ymd_His') . '.csv';
        $fillable = (new Ope())->getFillable();

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

            Ope::orderBy('ope_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;
    }
}
