<?php

namespace App\Models;

use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\View;
use Illuminate\Mail\Mailables\Address;
use App\Mail\EmailForQueuing;
use Exception;

class EmailLib
{
    public string $host;
    public int $port;
    public string $user;
    public string $pw;
    public string $from; // 발송자
    public string $name;
    public array $data;
    public array $error;
    public array $history; // 이메일 전송 내역 정보
    public array $result; // 이메일 전송 결과 정보
    public int $total; // 전송 횟수
    public int $success; // 성공 횟수
    public int $failed; // 실패 횟수
    public array $message; // 처리 결과
    public array $mails; // 대상 이메일

    public function __construct()
    {
        $this->host = env('MAIL_HOST');
        $this->port = env('MAIL_PORT');
        $this->user = env('MAIL_USERNAME');
        $this->pw = env('MAIL_PASSWORD');
        $this->from = env('MAIL_FROM_ADDRESS');
        $this->name = env('MAIL_FROM_NAME');

        $this->_init();
    }

    /**
     * 초기화
     */
    private function _init(): void
    {
        $this->data = [];
        $this->error = [];
        $this->history = [];
        $this->result = [];
        $this->total = 0;
        $this->success = 0;
        $this->failed = 0;
        $this->message = [];
        $this->mails = [];
    }

    /**
     * 테스트 전송
     */
    public function test(array $params): void
    {
        $subject = 'This is Test Email';

        Mail::send('admin.config.test.form', $params, function ($message) use ($params, $subject) {
            $message->from($this->from, $this->name);
            $message->to($params['email'], $params['name'])->subject($subject);
        });
    }

    /**
     * 오류 조회
     */
    public function errors(): array
    {
        return array_filter($this->error);
    }

    /**
     * 전송 데이터 설정
     */
    private function _add($users): bool
    {
        $set = function ($user) {
            $this->mails[] = $user;
        };

        if (is_array($users)) {
            foreach ($users as $user) {
                if (!filter_var($user->email, FILTER_VALIDATE_EMAIL)) {
                    $this->error[] = "{$user->email} 는 잘못된 이메일 형식입니다.";
                    return false;
                }

                $set($user);
            }
        } else {
            $set(current($users));
        }

        return true;
    }

    /**
     * 이메일 발송
     */
    private function _push(string $sendMailFormType): bool
    {
        try {

            if (count($this->mails) > 0) {
                $configs = $this->replaceValues();

                foreach ($this->mails as $user) {
                    // 발송 양식
                    $title = config($sendMailFormType . '_title');
                    $content = config($sendMailFormType . '_content');

                    $mapping = array_merge($configs, [
                        '{회원아이디}' => $user->id,
                        '{회원실명}' => $user->name,
                        '{회원이름}' => $user->name,
                        '{회원닉네임}' => $user->nickname,
                        '{회원이메일}' => $user->email,
                        '{메일수신여부}' => ($user->receive_email ? '동의' : '거부'),
                        '{문자수신여부}' => ($user->receive_sms ? '동의' : '거부'),
                        '{쪽지수신여부}' => ($user->receive_note ? '동의' : '거부'),
                        '{최종로그인시간}' => $user->last_login_at?->format('Y년 m월 d일 H시i분'),
                        '{휴면전환예정일}' => $user->last_login_at?->addYear(1)->format('Y년 m월 d일')
                    ]);

                    $html = View::make('component.form.email', ['content' => $content])->render();

                    // 치환 변수 처리
                    foreach ($mapping as $k => $v) {
                        $title = str_replace($k, $v, $title);
                        $html = str_replace($k, $v, $html);
                    }

                    Mail::send(new EmailForQueuing(
                        new Address($this->from, $this->name),
                        new Address($user->email, $user->name),
                        $title,
                        $html
                    ));

                    $this->total++;
                }
            }

            $this->success++;
            return true;

        } catch (Exception $e) {
            $this->error[] = $e->getMessage();
            $this->failed++;
            return false;
        }
    }

    /**
     * 치환 대상 변수
     */
    public function replaceValues($config = new Config()): array
    {
        return [
            '{홈페이지명}' => $config->item('site_title'),
            '{홈페이지주소}' => $config->item('company_site_url'),
            '{회원아이디}' => null,
            '{회원실명}' => null,
            '{회원닉네임}' => null,
            '{회원이메일}' => null,
            '{메일인증주소}' => null,
            '{메일수신여부}' => null,
            '{문자수신여부}' => null,
            '{쪽지수신여부}' => null,
            '{최종로그인시간}' => null,
            '{회원아이피}' => $config->item('site_title'),
            '{회사명}' => $config->item('company_name'),
            '{사업자등록번호}' => $config->item('company_reg_no'),
            '{대표자명}' => $config->item('company_owner'),
            '{대표전화번호}' => $config->item('company_phone'),
            '{FAX번호}' => $config->item('company_fax'),
            '{통신판매업신고번호}' => $config->item('company_retail_sale_no'),
            '{부가통신사업자번호}' => $config->item('company_added_sale_no'),
            '{사업장우편번호}' => $config->item('company_zip_code'),
            '{사업장주소}' => $config->item('company_address'),
            '{호스팅서비스}' => $config->item('company_hosting'),
            '{정보관리책임자명}' => $config->item('company_admin_name'),
            '{정보관리책임자이메일}' => $config->item('company_admin_email'),
            '{입금은행}' => $config->item('company_bank_name'),
            '{입금계좌}' => $config->item('company_bank_number'),
            '{휴면전환예정일}' => null
        ];
    }

    /**
     * 이메일 전송
     */
    public function send(string $sendMailFormType, User|UserDormant ...$user): bool
    {
        try{

            if(!$this->_add($user)) {
                throw new Exception();
            }

            if(!$this->_push($sendMailFormType)) {
                throw new Exception();
            }

            return true;
        }catch(Exception) {
            return false;
        }
    }
}
