<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Traits\AuthenticatesUser;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Carbon\Carbon;

class RegularContractController extends Controller
{
    use AuthenticatesUser;
    public function showInfo(Request $request)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }
        $user_name = DB::table('user')->where('user_id', $user_id)->value('user_name');

        $today = date('Y-m-d');
        // 定期契約情報を取得（park/usertype/psection/ptypeテーブルもJOIN）
        $contracts = DB::table('regular_contract')
            ->join('park', 'regular_contract.park_id', '=', 'park.park_id')
            ->join('usertype', 'regular_contract.user_categoryid', '=', 'usertype.user_categoryid')
            ->leftJoin('city', 'park.city_id', '=', 'city.city_id')
            ->leftJoin('psection', 'regular_contract.psection_id', '=', 'psection.psection_id')
            ->leftJoin('ptype', 'regular_contract.ptype_id', '=', 'ptype.ptype_id')
            ->where('regular_contract.user_id', $user_id)
            ->where('regular_contract.contract_flag', 1)
            ->where('regular_contract.contract_cancel_flag', 0)
            ->where(function ($query) use ($today) {
                $query->where('regular_contract.contract_periode', '>', $today)
                    ->orWhere(function ($q) use ($today) {
                        $q->where('regular_contract.contract_periode', '<=', $today)
                            ->whereRaw('DATEDIFF(?, regular_contract.contract_periode) <= 5', [$today]);
                    });
            })
            ->select(
                'regular_contract.contract_id',
                'park.park_name',
                'usertype.usertype_subject1',
                'regular_contract.contract_periods',
                'regular_contract.contract_periode',
                'regular_contract.enable_months',
                'regular_contract.contract_renewal',
                'regular_contract.park_id',
                'city.update_grace_period_start_date',
                'city.update_grace_period_start_time',
                'city.update_grace_period_end_date',
                'city.update_grace_period_end_time',
                'psection.psection_subject',
                'ptype.ptype_subject',
                'regular_contract.pplace_no'
            )
            ->get();

        if ($request->route()->getName() === 'regular_contract.info') {
            // 契約情報表示画面の処理
            \Log::info('契約情報表示画面にアクセス', [
                'user_id' => $user_id,
            ]);
            $view = 'regular_contract.info';
            $active_menu = 'SWC-3-1';
        } else {
            // 契約更新画面の処理
            \Log::info('契約更新画面にアクセス', [
                'user_id' => $user_id,
            ]);
            $view = 'regular_contract.update';
            $active_menu = 'SWC-4-1';
        }

        return view($view, [
            'active_menu' => $active_menu, // マイページメニューの選択状態用
            'user_name' => $user_name, // ユーザー名（ヘッダー用）
            'contracts' => $contracts,
        ]);
    }

    public function showHistory(Request $request): mixed
    {
        /**
         * 定期契約履歴を表示する。
         * ユーザーの契約履歴を取得し、ページネーション付きでビューに渡す。
         * 
         * @param Request $request 受信したHTTPリクエスト
         * @return mixed ビュー応答またはリダイレクト
         */
        if ($redirect = $this->handleSessionExpired('定期契約履歴確認')) {
            return $redirect;
        }

        // ヘッダー表示のためユーザー名取得
        $user_id = session('user_id');
        $user_name = DB::table('user')->where('user_id', $user_id)->value('user_name');

        // マルチテナント対応のため、運営元コード、IDを取得
        $management = session('management');
        $management_code = $management->management_code;
        $management_id = $management->management_id;

        // 定期契約情報を取得（ページネーション付き）
        $contracts_query = DB::table('regular_contract')
            ->join('park', 'regular_contract.park_id', '=', 'park.park_id')
            ->join('usertype', 'regular_contract.user_categoryid', '=', 'usertype.user_categoryid')
            ->where('regular_contract.user_id', $user_id)
            ->where('park.management_id', $management_id)
            ->whereNotNull('regular_contract.contract_money')
            ->select(
                'regular_contract.contract_id',
                'park.park_name',
                'usertype.usertype_subject1',
                'usertype.usertype_subject3',
                'regular_contract.contract_periods',
                'regular_contract.contract_periode',
                'regular_contract.enable_months',
                'regular_contract.park_id',
                'park.update_grace_period_start_date',
                'park.update_grace_period_end_date',
            )
            ->orderBy('regular_contract.contract_id', 'desc');

        // ページネーション（4件ずつ）
        $contracts = $contracts_query->paginate(4);

        // 日付をyyyy/MM/dd形式で画面表示するため加工
        $contracts->getCollection()->transform(function ($contract) {
            $periode = $contract->contract_periode;
            $grace_day = $contract->update_grace_period_start_date;
            $ym = date('Y/m', strtotime($periode));
            $day = str_pad($grace_day, 2, '0', STR_PAD_LEFT);
            $contract->periode_with_grace = $ym . '/' . $day;
            $contract->formatted_periods = \Carbon\Carbon::parse($contract->contract_periods)->format('Y/m/d');
            $contract->has_receipt = DB::table('inv_publish')->where('contract_id', $contract->contract_id)->exists();
            return $contract;
        });

        // システム操作の追跡のため、アクセスを記録
        \Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " 契約履歴表示画面にアクセス: user_id=" . $user_id . ", management_code=" . $management_code);

        return view('regular_contract.history', [
            'active_menu' => 'SWC-6-1', // マイページメニューの選択状態用
            'user_name' => $user_name, // ユーザー名（ヘッダー用）
            'contracts' => $contracts,
            'management_code' => $management_code,
        ]);
    }

    public function update($contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }

        // 元契約データ取得
        $old_contract = DB::table('regular_contract')->where('contract_id', $contract_id)->first();

        // 新規レコード作成（必要な項目を元契約データから引き継ぐ）
        $new_contract_id = DB::table('regular_contract')->insertGetId([
            'old_contract_id' => $old_contract->contract_id,
            'user_id' => $old_contract->user_id,
            'user_categoryid' => $old_contract->user_categoryid,
            'created_at' => now(),
            'updated_at' => now(),
            'park_id' => $old_contract->park_id,
            'price_parkplaceid' => $old_contract->price_parkplaceid,
            'user_securitynum' => $old_contract->user_securitynum,
            'contract_created_at' => now(),
            'contract_reduction' => $old_contract->contract_reduction,
            'update_flag' => 1,
            'contract_cancel_flag' => 0,
            '800m_flag' => 0,
            'psection_id' => $old_contract->psection_id,
            'ptype_id' => $old_contract->ptype_id,
            'zone_id' => $old_contract->zone_id,
            'pplace_no' => $old_contract->pplace_no
        ]);

        // contract_qr_id生成（AES-256-CBC暗号化）
        $key = "LJLASR4FAS34SAADFA72ASDFALLSDRGT";
        $iv = substr(hash('sha256', $key), 0, 16); // IVは16バイト
        $encrypted = openssl_encrypt($new_contract_id, 'AES-256-CBC', $key, 0, $iv);

        // contract_qr_idを更新
        DB::table('regular_contract')->where('contract_id', $new_contract_id)->update([
            'contract_qr_id' => $encrypted
        ]);

        // 完了後の遷移
        return redirect()->route('regular_contract.confirm_category', ['contract_id' => $new_contract_id]);
    }

    public function confirmCategory($contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }
        $user = DB::table('user')->where('user_id', $user_id)->first();

        // regular_contractとparkをJOINしてsecurityreg_display_flagを取得
        $contract = DB::table('regular_contract')
            ->join('park', 'regular_contract.park_id', '=', 'park.park_id')
            ->where('regular_contract.contract_id', $contract_id)
            ->select('regular_contract.*', 'park.securityreg_display_flag')
            ->first();

        return view('regular_contract.confirm_category', [
            'active_menu' => 'SWC-4-1', // マイページメニューの選択状態用
            'user_name' => $user ? $user->user_name : '', // ユーザー名（ヘッダー用）
            'user' => $user,
            'contract' => $contract
        ]);
    }

    /**
     * 契約区分確認画面の「確認して進む」ボタン押下時の分岐処理
     * 本人確認書類アップロード画面 or 利用期間選択画面へ遷移
     */
    public function confirmCategoryNext($contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }
        // 契約情報取得
        $contract = DB::table('regular_contract')->where('contract_id', $contract_id)->first();
        if (!$contract) {
            return redirect()->back()->with('error', '契約情報が見つかりません');
        }
        // ユーザー情報取得
        $user = DB::table('user')->where('user_id', $user_id)->first();
        // ユーザー区分取得
        $usertype = DB::table('usertype')->where('user_categoryid', $user->user_categoryid)->first();
        // 駐輪場情報取得
        $park = DB::table('park')->where('park_id', $contract->park_id)->first();
        // 減免確認種別取得
        $reduction_confirm = DB::table('reduction_confirm')
            ->where('park_id', $contract->park_id)
            ->where('user_categoryid', $contract->user_categoryid)
            ->first();

        // 分岐条件
        $reduction_confirm_type = isset($reduction_confirm) ? $reduction_confirm->reduction_confirm_type : 0;
        $student_id_confirm_type = isset($park) ? $park->student_id_confirm_type : 0;
        // $overyear_flag = isset($park) ? $park->overyear_flag : 0;

        // 契約期間に4/1が含まれるか判定
        // $contract_start = new \DateTime($contract->contract_periods);
        // $contract_end = new \DateTime($contract->contract_periode);
        // 4/1の年は契約開始年
        // $april_first = new \DateTime($contract_start->format('Y') . '-04-01');
        // 契約終了日が4/1より前なら翌年の4/1も考慮
        /**if ($contract_end < $april_first) {
            $april_first->modify('+1 year');
        }
        $includes_april_first = ($contract_start <= $april_first && $contract_end >= $april_first);*/

        // ユーザー区分が「学生」の場合のみ卒業年月日判定
        /**$exceeds_graduation = false;
        if (isset($usertype) && $usertype->usertype_subject1 === '学生') {
            $graduation_date = isset($user) ? $user->user_graduate : null;
            if ($graduation_date) {
                $graduation_dt = new \DateTime($graduation_date);
                $exceeds_graduation = ($contract_end > $graduation_dt);
            }
        }*/

        // 本人確認書類アップロード画面へ遷移する条件
        // 1. reduction_confirm_typeが1（年1回）または2（毎更新時）
        // 2. student_id_confirm_typeが1（年1回）または2（毎更新時）
        // 3. 年度跨ぎ（overyear_flag=1以外）かつ契約期間に4/1が含まれる場合
        $need_identity = false;
        // 減免確認種別：reduction_confirm_type=1は年度跨ぎのみ、2は無条件で本人確認
        /**if ($reduction_confirm_type == 1 && $includes_april_first) {
            $need_identity = true;
        }*/
        /**if ($reduction_confirm_type == 2) {*/
        if (in_array($reduction_confirm_type, [1, 2])) {
            $need_identity = true;
        }
        // 学生証確認種別：学生の場合かつ減免でない場合のみ判定
        if (isset($usertype) && $usertype->usertype_subject1 === '学生' && in_array($student_id_confirm_type, [1, 2]) && $contract->contract_reduction == 0) {
            $need_identity = true;
        }
        // 年度跨ぎ判定
        /**if ($overyear_flag != 1 && $includes_april_first) {
            $need_identity = true;
        }*/
        // 卒業年月日超過判定
        /**if ($exceeds_graduation) {
            $need_identity = true;
        }*/

        if ($need_identity) {
            // 本人確認書類アップロード画面へ
            return redirect()->route('regular_contract.upload_identity', ['contract_id' => $contract_id]);
        } else {
            // 利用期間選択画面へ
            return redirect()->route('regular_contract.select_period', ['contract_id' => $contract_id]);
        }
    }

    public function uploadIdentity($contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }
        $user_name = DB::table('user')->where('user_id', $user_id)->value('user_name');

        \Log::info('契約更新用本人確認書類アップロード画面にアクセス', [
            'user_id' => $user_id,
        ]);

        return view('regular_contract.upload_identity', [
            'active_menu' => 'SWC-4-1', // マイページメニューの選択状態用
            'user_name' => $user_name, // ユーザー名（ヘッダー用）
            'contract_id' => $contract_id,
        ]);
    }

    public function uploadIdentitySubmit(Request $request, $contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }

        // バリデーション
        $rules = [
            'user_idcard' => 'required|file|mimes:jpeg,png,jpg,gif,webp',
            'user_idcard2' => 'nullable|file|mimes:jpeg,png,jpg,gif,webp',
        ];
        $messages = [
            'user_idcard.required' => '本人確認書類をアップロードしてください。',
            'user_idcard.file' => '本人確認書類（おもて）はファイルで指定してください。',
            'user_idcard.mimes' => '本人確認書類（おもて）は画像ファイルで指定してください。',
            'user_idcard2.file' => '本人確認書類（ウラ）はファイルで指定してください。',
            'user_idcard2.mimes' => '本人確認書類（ウラ）は画像ファイルで指定してください。',
        ];

        $validator = \Validator::make($request->all(), $rules, $messages);

        if ($validator->fails()) {
            return redirect()->route('regular_contract.upload_identity', ['contract_id' => $contract_id])
                ->withErrors($validator)
                ->withInput();
        }

        // おもて画像保存
        $front = $request->file('user_idcard');
        $filename_front = uniqid('photo1_') . '.' . $front->getClientOriginalExtension();
        $front->storeAs('photo', $filename_front, 'public');
        // userテーブルに保存 本人確認書類チェック済フラグや更新日時も更新項目に追加
        $updateData = [
            'photo_filename1' => $filename_front,
            'user_idcard_chk_flag' => 1,
            'user_chk_day' => null,
            'user_chk_opeid' => null,
            'updated_at' => now(),
        ];
        // ウラ画像がある場合保存し更新項目に追加
        if ($request->hasFile('user_idcard2')) {
            $back = $request->file('user_idcard2');
            $filename_back = uniqid('photo2_') . '.' . $back->getClientOriginalExtension();
            $back->storeAs('photo', $filename_back, 'public');
            $updateData['photo_filename2'] = $filename_back;
        }
        DB::table('user')->where('user_id', $user_id)->update($updateData);

        // 更新対象の旧契約を検索
        $old_contract_id = DB::table('regular_contract')->where('contract_id', $contract_id)->value('old_contract_id');

        // 旧契約を契約更新済に更新
        DB::table('regular_contract')->where('contract_id', $old_contract_id)->update(['contract_renewal' => 0]);

        // 利用者マスタから学校とユーザー名、定期契約マスタから駐輪場IDを取得
        $user = DB::table('user')->where('user_id', $user_id)->first();
        $park_id = DB::table('regular_contract')->where('contract_id', $contract_id)->value('park_id');

        // que_classの分岐
        $que_class = is_null($user->user_school) ? 1 : 2;

        // オペレーターキュー発行
        DB::table('operator_que')->insert([
            'que_class' => $que_class,
            'user_id' => $user_id,
            'contract_id' => $contract_id,
            'park_id' => $park_id,
            'que_status' => 1,
            'que_status_comment' => '本人確認手動処理を行ってください',
            'created_at' => now(),
        ]);

        \Log::info('本人確認書類確認中画面にアクセス', [
            'user_id' => $user_id,
        ]);

        // 本人確認書類確認中画面へ遷移
        return view('regular_contract.identity_checking', [
            'active_menu' => 'SWC-4-1', // マイページメニューの選択状態用
            'user_name' => $user->user_name // ユーザー名（ヘッダー用）
        ]);
    }

    public function selectPeriod($contract_id)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }

        // 必要な各マスタ情報を取得
        $user = DB::table('user')->where('user_id', $user_id)->first();
        $contract = DB::table('regular_contract')->where('contract_id', $contract_id)->first();
        $park = DB::table('park')->where('park_id', $contract->park_id)->first();
        $city = DB::table('city')->where('city_id', $park->city_id)->first();
        $regular_type = DB::table('regular_type')->where('city_id', $city->city_id)->first();
        $usertype = DB::table('usertype')->where('user_categoryid', $contract->user_categoryid)->first();

        // 2重化しているマスタのため現在のテーブル名を取得
        $master_setting = DB::table('setting')->value('web_master');
        $tableName = 'price' . $master_setting;

        // 利用者区分に応じた逆利用フラグを取得
        $inverse_use_flag_column = ($usertype->usertype_subject1 == '一般') ? 'inverse_use_flag1' : 'inverse_use_flag2';
        $inverse_use_flag = $park->$inverse_use_flag_column;

        if ($inverse_use_flag == 0) {
            // regident_cityまたはrelate_cityが一致するか
            $is_same = (
                strpos($user->user_regident_city, $city->city_name) !== false ||
                strpos($user->user_relate_city, $city->city_name) !== false
            );
        } else {
            // regident_cityのみ一致するか
            $is_same = (strpos($user->user_regident_city, $city->city_name) !== false);
        }

        $target_subject2 = $is_same ? '区民' : '区民外';
        $user_categoryid = DB::table('usertype')
            ->where('usertype_subject1', $usertype->usertype_subject1)
            ->where('usertype_subject2', $target_subject2)
            ->where('usertype_subject3', $usertype->usertype_subject3)
            ->value('user_categoryid');

        // 駐輪場所マスタから料金を取得
        $prices = DB::table($tableName)
            ->where('park_id', $contract->park_id)
            ->where('psection_id', $contract->psection_id)
            ->where('ptype_id', $contract->ptype_id)
            ->where('user_categoryid', $user_categoryid)
            ->get();

        \Log::info('契約区分取得', [
            'user_categoryid' => $user_categoryid,
            'target_subject2' => $target_subject2,
            'park_id' => $contract->park_id,
            'psection_id' => $contract->psection_id,
            'ptype_id' => $contract->ptype_id,
            'prices' => $prices->toArray(),
        ]);

        \Log::info('利用期間選択画面にアクセス', [
            'user_id' => $user_id,
        ]);

        // 利用期間選択画面へ遷移
        return view('regular_contract.select_period', [
            'active_menu' => 'SWC-4-1', // マイページメニューの選択状態用
            'user_name' => $user->user_name, // ユーザー名（ヘッダー用）
            'contract_id' => $contract_id,
            'regular_type' => $regular_type,
            'prices' => $prices,
        ]);
    }

    public function updatePeriod(Request $request)
    {
        $user_id = session('user_id');
        if (!$user_id) {
            return redirect('/login');
        }

        // 期間選択チェック
        $request->validate([
            'month' => 'required',
        ], [
            'month.required' => '契約期間が選択されていません。',
        ]);

        $contract_id = $request->input('contract_id');
        $month = $request->input('month');
        $price = $request->input('price_' . $month);

        \Log::info('契約期間更新処理', [
            'month' => $month,
            'price' => $price,
        ]);
        $today = now();
        $day = $today->day;
        if ($day <= 19) {
            // 今月の1日
            $contract_periods = $today->copy()->startOfMonth()->format('Y-m-d');
        } else {
            // 翌月の1日
            $contract_periods = $today->copy()->addMonth()->startOfMonth()->format('Y-m-d');
        }
        $contract_periode = Carbon::parse($contract_periods)->addMonths($month - 1)->endOfMonth()->format('Y-m-d');
        // 契約更新
        DB::table('regular_contract')->where('contract_id', $contract_id)->update([
            'enable_months' => $month,
            'billing_amount' => $price,
            'contract_periods' => $contract_periods,
            'contract_periode' => $contract_periode,
            'updated_at' => now(),
        ]);

        // 完了後はウェルネット決済画面（仮）へリダイレクト
        return redirect()->route('wellnet.payment');
    }
}
