<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Symfony\Component\HttpFoundation\Response;

/**
 * 定期パスワード変更チェックミドルウェア
 * 
 * ログインしているオペレータのパスワード最後変更時刻をチェック
 * 3ヶ月以上経過している場合、パスワード変更画面へ強制リダイレクト
 */
class CheckPasswordChangeRequired
{
    /**
     * リクエストを処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handle(Request $request, Closure $next): Response
    {
        // ログインしていない場合はスキップ
        if (!Auth::check()) {
            return $next($request);
        }

        // 既にパスワード変更ページにいる場合はスキップ
        if ($request->routeIs('password.change.show', 'password.change.update')) {
            return $next($request);
        }

        // 現在のユーザーを取得
        $ope = Auth::user();

        // パスワード変更が必須か判定
        if ($this->isPasswordChangeRequired($ope)) {
            return redirect()->route('password.change.show');
        }

        return $next($request);
    }

    /**
     * パスワード変更が必須かどうかを判定
     * 
     * 初回ログイン時（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)) {
            \Log::info('Password change required: ope_pass_changed_at is null', [
                'ope_id' => $ope->ope_id,
            ]);
            return true;
        }

        // パスワード変更から経過日数を計算
        // ope_pass_changed_at は複数のフォーマットに対応
        try {
            $changedAt = Carbon::parse($ope->ope_pass_changed_at);
        } catch (\Exception $e) {
            // パース失敗時は強制変更
            \Log::warning('Failed to parse ope_pass_changed_at', [
                'ope_id' => $ope->ope_id,
                'value' => $ope->ope_pass_changed_at,
                'error' => $e->getMessage(),
            ]);
            return true;
        }

        $now = Carbon::now();
        
        // 3ヶ月以上経過しているか判定
        // diffInMonths は絶対値ではなく符号付きなので、abs() で絶対値を取得
        $monthsDiff = abs($now->diffInMonths($changedAt));
        
        \Log::info('Password change check', [
            'ope_id' => $ope->ope_id,
            'changed_at' => $changedAt->format('Y-m-d H:i:s'),
            'now' => $now->format('Y-m-d H:i:s'),
            'months_diff' => $monthsDiff,
            'is_required' => $monthsDiff >= 3,
        ]);

        if ($monthsDiff >= 3) {
            return true;
        }

        return false;
    }
}
