<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\ChangePasswordRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Validation\ValidationException;
use Carbon\Carbon;

class PasswordChangeController extends Controller
{
    /**
     * コントローラーのコンストラクタ
     * 
     * ログイン状態のユーザーのみアクセス可能
     */
    public function __construct()
    {
        // Laravel 12: ミドルウェアは routes/web.php で処理
    }

    /**
     * パスワード変更フォーム表示
     * 
     * GET /password/change
     *
     * @return \Illuminate\View\View
     */
    public function showChangeForm()
    {
        // 現在のユーザー情報を取得
        $ope = Auth::user();
        
        // ビューにパスワード変更が必須かどうかを判定するデータを渡す
        $isRequired = $this->isPasswordChangeRequired($ope);

        return view('auth.password-change', [
            'isRequired' => $isRequired,
        ]);
    }

    /**
     * パスワード変更成功画面を表示
     * 
     * GET /password/change/success
     *
     * @return \Illuminate\View\View
     */
    public function showSuccessPage()
    {
        return view('auth.password-change-success');
    }

    /**
     * パスワード変更処理
     * 
     * POST /password/change
     * 
     * バリデーション：
     * - 当前パスワード：必填、8-64文字、ハッシュ値一致確認
     * - 新パスワード：必填、8-64文字、英数字+記号のみ、当前と異なる
     * - 新パスワード確認：必填、新パスワードと一致
     *
     * @param  \App\Http\Requests\ChangePasswordRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function updatePassword(ChangePasswordRequest $request)
    {
        // 現在のユーザーを取得
        $ope = Auth::user();

        // ステップ1：当前パスワードの認証（ハッシュ値の確認）
        if (!Hash::check($request->current_password, $ope->ope_pass)) {
            // バリデーションエラーとして当前パスワード が正しくないことを返す
            throw ValidationException::withMessages([
                'current_password' => '当前パスワードが正しくありません。',
            ]);
        }

        // ステップ2：新パスワードが当前パスワードと同一でないか確認
        // FormRequest側でも not_in ルールで確認しているが、ハッシュ値での二重チェック
        if (Hash::check($request->password, $ope->ope_pass)) {
            throw ValidationException::withMessages([
                'password' => '新パスワードは当前パスワードと異なる必要があります。',
            ]);
        }

        // ステップ3：データベース更新
        // パスワードをハッシュ化して更新
        $ope->ope_pass = Hash::make($request->password);
        
        // パスワード変更時刻を現在時刻に更新
        $ope->ope_pass_changed_at = Carbon::now();
        
        // updated_at も自動更新される
        $ope->save();

        // イベント発火：パスワード変更イベント
        event(new PasswordReset($ope));

        // 成功画面へリダイレクト
        return redirect()->route('password.change.success');
    }

    /**
     * パスワード変更が必須かどうかを判定
     * 
     * 初回ログイン時（ope_pass_changed_at が NULL）または
     * 最後変更から3ヶ月以上経過している場合、TRUE を返す
     *
     * @param  \App\Models\Ope  $ope
     * @return bool
     */
    private function isPasswordChangeRequired($ope): bool
    {
        // パスワード変更日時が未設定（初回ログイン等）
        if (is_null($ope->ope_pass_changed_at)) {
            return true;
        }

        // パスワード変更から経過日数を計算
        $changedAt = Carbon::parse($ope->ope_pass_changed_at);
        $now = Carbon::now();
        
        // 3ヶ月以上経過している場合
        if ($now->diffInMonths($changedAt) >= 3) {
            return true;
        }

        return false;
    }
}
