<?php

namespace App\Services;

use App\Models\MailTemplate;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

/**
 * SHJ メール送信処理サービス
 * 
 * メールテンプレートを使用したメール送信処理を実行するビジネスロジック
 * バッチ処理「SHJメール送信」の核となる処理を担当
 */
class ShjMailSendService
{
    /**
     * MailTemplate モデル
     *
     * @var MailTemplate
     */
    protected $mailTemplateModel;

    /**
     * コンストラクタ
     *
     * @param MailTemplate $mailTemplateModel
     */
    public function __construct(
        MailTemplate $mailTemplateModel
    ) {
        $this->mailTemplateModel = $mailTemplateModel;
    }

    /**
     * SHJ-7 メール送信処理メイン実行
     *
     * 処理フロー:
     * 【処理1】入力パラメーターをチェックする
     * 【判断1】チェック結果
     * 【処理2】メール送信テンプレート情報を取得する
     * 【判断2】取得結果判定
     * 【処理3】メールを送信する
     * 【処理4】処理結果を返却する
     *
     * @param string $mailAddress メールアドレス
     * @param string $backupMailAddress 予備メールアドレス
     * @param int $mailTemplateId メールテンプレートID（使用プログラムID）
     * @return array 処理結果 ['result' => 0|1, 'error_info' => string]
     */
    public function executeMailSend(string $mailAddress, string $backupMailAddress, int $mailTemplateId): array
    {
        try {
            Log::info('SHJ-7 メール送信処理開始', [
                'mail_address' => $mailAddress,
                'backup_mail_address' => $backupMailAddress,
                'mail_template_id' => $mailTemplateId
            ]);

            // 【処理1】入力パラメーターをチェックする
            $paramCheckResult = $this->checkInputParameters($mailAddress, $backupMailAddress, $mailTemplateId);

            // 【判断1】チェック結果
            if (!$paramCheckResult['valid']) {
                $errorInfo = $paramCheckResult['error_info'];

                Log::warning('SHJ-7 パラメーターチェックNG', [
                    'error_info' => $errorInfo
                ]);

                // 【処理4】処理結果を返却する（異常終了）
                return [
                    'result' => 1,
                    'error_info' => $errorInfo
                ];
            }

            // 【処理2】メール送信テンプレート情報を取得する
            $templateInfo = $this->getMailTemplateInfo($mailTemplateId);

            // 【判断2】取得結果判定
            if (empty($templateInfo)) {
                // 0件の場合：取得NGの結果を設定する
                $errorInfo = "メール送信NG：メール送信テンプレートが存在しません。/{$mailTemplateId}";

                Log::warning('SHJ-7 メールテンプレート取得NG', [
                    'mail_template_id' => $mailTemplateId,
                    'error_info' => $errorInfo
                ]);

                // 【処理4】処理結果を返却する（異常終了）
                return [
                    'result' => 1,
                    'error_info' => $errorInfo
                ];
            }

            // 【処理3】メールを送信する
            $mailSendResult = $this->sendMail($mailAddress, $backupMailAddress, $templateInfo);

            if (!$mailSendResult['success']) {
                $errorInfo = $mailSendResult['error_info'];

                Log::error('SHJ-7 メール送信失敗', [
                    'error_info' => $errorInfo
                ]);

                // 【処理4】処理結果を返却する（異常終了）
                return [
                    'result' => 1,
                    'error_info' => $errorInfo
                ];
            }

            Log::info('SHJ-7 メール送信処理完了', [
                'to_address' => $mailSendResult['to_address']
            ]);

            // 【処理4】処理結果を返却する（正常終了）
            return [
                'result' => 0,
                'error_info' => ''
            ];

        } catch (\Exception $e) {
            $errorInfo = 'メール送信NG：' . $e->getMessage();

            Log::error('SHJ-7 メール送信処理例外エラー', [
                'exception' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            // 【処理4】処理結果を返却する（異常終了）
            return [
                'result' => 1,
                'error_info' => $errorInfo
            ];
        }
    }

    /**
     * 【処理1】入力パラメーターをチェックする
     *
     * SHJ-7仕様書に基づくチェック内容:
     * 1. メールアドレス: 「メールアドレス」「予備メールアドレス」いずれか必須
     * 2. 予備メールアドレス: 「メールアドレス」「予備メールアドレス」いずれか必須
     * 3. 使用プログラムID: 必須
     *
     * エラーメッセージ形式: "パラメーターNG: 項目名/入力値"
     * 複数エラーの場合は全角カンマ（、）で連結
     *
     * @param string $mailAddress メールアドレス
     * @param string $backupMailAddress 予備メールアドレス
     * @param int $mailTemplateId メールテンプレートID（使用プログラムID）
     * @return array チェック結果 ['valid' => bool, 'error_info' => string]
     */
    private function checkInputParameters(string $mailAddress, string $backupMailAddress, int $mailTemplateId): array
    {
        $errors = [];

        try {
            // 1. メールアドレスと予備メールアドレスのいずれか必須チェック
            // 両方とも空の場合は、それぞれ別エラーとして追加
            if (empty($mailAddress) && empty($backupMailAddress)) {
                $errors[] = "パラメーターNG：メールアドレス/<空>";
                $errors[] = "パラメーターNG：予備メールアドレス/<空>";
            } else {
                // いずれかに値がある場合は、形式チェックを実施
                // 2. メールアドレス形式チェック（値がある場合のみ）
                if (!empty($mailAddress) && !filter_var($mailAddress, FILTER_VALIDATE_EMAIL)) {
                    $errors[] = "パラメーターNG：メールアドレス/{$mailAddress}";
                }

                // 3. 予備メールアドレス形式チェック（値がある場合のみ）
                if (!empty($backupMailAddress) && !filter_var($backupMailAddress, FILTER_VALIDATE_EMAIL)) {
                    $errors[] = "パラメーターNG：予備メールアドレス/{$backupMailAddress}";
                }
            }

            // 4. 使用プログラムID（メールテンプレートID）必須チェック
            if (empty($mailTemplateId) || $mailTemplateId <= 0) {
                $errors[] = "パラメーターNG：使用プログラムID/{$mailTemplateId}";
            }

            // エラーがある場合
            if (!empty($errors)) {
                // 複数のエラーがある場合は全角カンマ（、）で連結
                $errorInfo = implode('、', $errors);

                Log::warning('SHJ-7 入力パラメーターチェックNG', [
                    'mail_address' => $mailAddress,
                    'backup_mail_address' => $backupMailAddress,
                    'mail_template_id' => $mailTemplateId,
                    'error_info' => $errorInfo
                ]);

                return [
                    'valid' => false,
                    'error_info' => $errorInfo
                ];
            }

            // 正常終了
            Log::info('SHJ-7 入力パラメーターチェックOK', [
                'mail_address' => $mailAddress,
                'backup_mail_address' => $backupMailAddress,
                'mail_template_id' => $mailTemplateId
            ]);

            return [
                'valid' => true,
                'error_info' => ''
            ];

        } catch (\Exception $e) {
            $errorInfo = 'パラメーターチェック中にエラーが発生：' . $e->getMessage();

            Log::error('SHJ-7 入力パラメーターチェック例外エラー', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'valid' => false,
                'error_info' => $errorInfo
            ];
        }
    }

    /**
     * 【処理2】メール送信テンプレート情報を取得する
     *
     * SHJ-7仕様書に基づくSQLクエリ:
     * SELECT エリアマネージャー同報, bccアドレス, 件名, 本文
     * FROM メール送信テンプレート
     * WHERE 使用プログラムID = 入力パラメーター.使用プログラムID
     *   AND 使用フラグ = 1
     *
     * @param int $mailTemplateId メールテンプレートID（使用プログラムID）
     * @return MailTemplate|null メールテンプレート情報
     */
    private function getMailTemplateInfo(int $mailTemplateId): ?MailTemplate
    {
        try {
            // SHJ-7仕様: 使用プログラムID（pg_id）で検索、使用フラグ=1
            $templateInfo = $this->mailTemplateModel::where('pg_id', $mailTemplateId)
                ->where('use_flag', 1)
                ->first();

            if ($templateInfo) {
                Log::info('SHJ-7 メールテンプレート情報取得完了', [
                    'mail_template_id' => $mailTemplateId,
                    'template_found' => true,
                    'subject' => $templateInfo->getSubject(),
                    'mgr_cc_flag' => $templateInfo->isManagerCcEnabled(),
                    'has_bcc' => !empty($templateInfo->getBccAddress())
                ]);
            } else {
                Log::warning('SHJ-7 メールテンプレート情報取得結果0件', [
                    'mail_template_id' => $mailTemplateId,
                    'template_found' => false
                ]);
            }

            return $templateInfo;

        } catch (\Exception $e) {
            Log::error('SHJ-7 メールテンプレート情報取得エラー', [
                'mail_template_id' => $mailTemplateId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            throw $e;
        }
    }

    /**
     * 【処理3】メールを送信する
     *
     * SHJ-7仕様書に基づくmb_send_mail関数使用:
     * - 送信先: 入力パラメーター.メールアドレス（空なら予備メールアドレス）
     * - タイトル: 処理2.件名
     * - 本文: 処理2.本文
     * - 追加ヘッダ: 処理2.bccアドレス（※値が設定されている場合のみ）
     *
     * ※待ち時間: 仕様では「一定の待ち時間を設ける」とあるが、現時点では実装しない（0秒）
     *
     * @param string $mailAddress メールアドレス
     * @param string $backupMailAddress 予備メールアドレス
     * @param MailTemplate $templateInfo テンプレート情報
     * @return array 送信結果 ['success' => bool, 'error_info' => string, 'to_address' => string]
     */
    private function sendMail(string $mailAddress, string $backupMailAddress, MailTemplate $templateInfo): array
    {
        try {
            // 送信先アドレス決定（優先: メールアドレス、代替: 予備メールアドレス）
            $toAddress = !empty($mailAddress) ? $mailAddress : $backupMailAddress;

            // 処理2で取得したメール内容を取得
            $subject = $templateInfo->getSubject() ?? '';
            $message = $templateInfo->getText() ?? '';

            // 追加ヘッダ設定（BCC、From等）
            $headers = $this->buildMailHeaders($templateInfo);

            Log::info('SHJ-7 メール送信準備完了', [
                'to_address' => $toAddress,
                'subject' => $subject,
                'has_bcc' => !empty($templateInfo->getBccAddress()),
                'mgr_cc_flag' => $templateInfo->isManagerCcEnabled()
            ]);

            // mb_send_mail関数を使用してメール送信
            $sendResult = mb_send_mail(
                $toAddress,     // 送信先
                $subject,       // 件名（タイトル）
                $message,       // 本文
                $headers        // 追加ヘッダ
            );

            if ($sendResult) {
                Log::info('SHJ-7 メール送信成功', [
                    'to_address' => $toAddress,
                    'subject' => $subject
                ]);

                return [
                    'success' => true,
                    'error_info' => '',
                    'to_address' => $toAddress
                ];
            } else {
                // mb_send_mail がfalseを返した場合
                $errorInfo = 'メール送信NG：mb_send_mail関数がfalseを返しました';
                Log::error('SHJ-7 メール送信失敗', [
                    'to_address' => $toAddress,
                    'subject' => $subject,
                    'error_info' => $errorInfo
                ]);

                return [
                    'success' => false,
                    'error_info' => $errorInfo
                ];
            }

        } catch (\Exception $e) {
            $errorInfo = 'メール送信NG：' . $e->getMessage();
            Log::error('SHJ-7 メール送信例外エラー', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return [
                'success' => false,
                'error_info' => $errorInfo
            ];
        }
    }

    /**
     * メールヘッダを構築
     *
     * SHJ-7仕様書に基づく追加ヘッダ設定:
     * - 追加ヘッダ: 処理2.bccアドレス（※値が設定されている場合のみ）
     * - From: システム設定から取得
     * - エリアマネージャー同報: フラグが有効な場合はログ出力のみ（実装保留）
     *
     * @param MailTemplate $templateInfo テンプレート情報
     * @return string メールヘッダ
     */
    private function buildMailHeaders(MailTemplate $templateInfo): string
    {
        $headers = [];

        // BCCアドレス設定（値が設定されている場合のみ追加）
        $bccAddress = $templateInfo->getBccAddress();
        if (!empty($bccAddress)) {
            $headers[] = "Bcc: {$bccAddress}";
        }

        // エリアマネージャー同報フラグが有効な場合
        // ※SHJ-7では実装しない（仕様詳細不明）。ログ出力のみ。
        if ($templateInfo->isManagerCcEnabled()) {
            Log::info('SHJ-7 エリアマネージャー同報フラグが有効', [
                'mail_template_id' => $templateInfo->mail_template_id
            ]);
            // 実際のエリアマネージャーアドレス取得・設定処理は将来実装
        }

        // From設定（システム設定から取得）
        $fromAddress = config('mail.from.address', 'noreply@so-manager.com');
        $headers[] = "From: {$fromAddress}";

        // Content-Type設定（日本語対応）
        $headers[] = "Content-Type: text/plain; charset=UTF-8";

        return implode("\r\n", $headers);
    }


    /**
     * SHJ-12 未払い者通知メール送信
     * 
     * SHJ-12から呼び出される専用メール送信メソッド
     * 未払い者への通知メールを送信する
     *
     * @param array $mailParams メール送信パラメータ
     * @return array 送信結果
     */
    public function sendUnpaidNotificationMail(array $mailParams): array
    {
        try {
            // パラメータ展開
            $toEmail = $mailParams['to_email'] ?? '';
            $userName = $mailParams['user_name'] ?? '';
            $parkName = $mailParams['park_name'] ?? '';
            $billingAmount = $mailParams['billing_amount'] ?? 0;
            $contractId = $mailParams['contract_id'] ?? '';

            // 未払い者通知専用のメールテンプレートID（仮定: 1）
            // 実際の運用では設定ファイルまたはデータベースから取得
            $mailTemplateId = 1;

            // メールテンプレート情報取得
            $templateInfo = $this->getMailTemplateInfo($mailTemplateId);
            
            if (!$templateInfo) {
                return [
                    'success' => false,
                    'message' => '未払い者通知用メールテンプレートが見つかりません'
                ];
            }

            // メール件名とメッセージのカスタマイズ
            $subject = str_replace(
                ['{park_name}', '{user_name}'],
                [$parkName, $userName],
                $templateInfo->getSubject()
            );

            $message = str_replace(
                ['{user_name}', '{park_name}', '{billing_amount}', '{contract_id}'],
                [$userName, $parkName, number_format($billingAmount), $contractId],
                $templateInfo->getText()
            );

            // 追加ヘッダ設定
            $headers = $this->buildMailHeaders($templateInfo);
            
            Log::info('SHJ-12 未払い者通知メール送信準備完了', [
                'to_email' => $toEmail,
                'user_name' => $userName,
                'billing_amount' => $billingAmount,
                'contract_id' => $contractId
            ]);

            // メール送信実行
            $sendResult = mb_send_mail(
                $toEmail,       // 送信先
                $subject,       // 件名
                $message,       // 本文
                $headers        // 追加ヘッダ
            );

            if ($sendResult) {
                Log::info('SHJ-12 未払い者通知メール送信成功', [
                    'to_email' => $toEmail,
                    'contract_id' => $contractId
                ]);

                return [
                    'success' => true,
                    'message' => '未払い者通知メール送信完了'
                ];
            } else {
                $errorMessage = '未払い者通知メール送信に失敗しました';
                Log::error('SHJ-12 未払い者通知メール送信失敗', [
                    'to_email' => $toEmail,
                    'contract_id' => $contractId,
                    'error' => $errorMessage
                ]);

                return [
                    'success' => false,
                    'message' => $errorMessage
                ];
            }

        } catch (\Exception $e) {
            $errorMessage = 'SHJ-12 未払い者通知メール送信エラー: ' . $e->getMessage();
            Log::error('SHJ-12 未払い者通知メール送信エラー', [
                'error' => $e->getMessage(),
                'mail_params' => $mailParams
            ]);

            return [
                'success' => false,
                'message' => $errorMessage
            ];
        }
    }
}