<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Mail;
use App\Models\UserMail;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class MailController extends Controller
{

    public function index(Request $request)
    {
        $domain_list  = config('mail.domain_list');
        $block_prefix = config('mail.block_prefix');
        $rand_prefix  = strtolower(Str::random(8));
        $key          = Crypt::encryptString(json_encode(['time' => time()]));
        return view('welcome', [
            'domain_list'  => $domain_list,
            'block_prefix' => $block_prefix,
            'rand_prefix'  => $rand_prefix,
            'key'          => $key,
        ]);
    }

    public function get(Request $request)
    {
        $email = $request->input('email');
        $email = strtolower($email);
        $key   = $request->input('key', '');

        $validator = Validator::make($request->all(), [
            'key'   => [
                'required',
                'string',
            ],
            'email' => [
                'required',
                'email',
                function ($attribute, $value, $fail) {
                    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                        return $fail('The ' . $attribute . ' must be a valid email address.');
                    }

                    list($prefix, $domain) = explode('@', $value);
                    $length                = mb_strlen($prefix);

                    if ($length < 5 || $length > 32) {
                        return $fail('The email prefix must be between 5 and 32 characters.');
                    }

                    if (in_array($prefix, config('mail.block_prefix'))) {
                        return $fail('The email prefix is blocked.');
                    }
                },
            ],
        ]);

        if ($validator->fails()) {
            return abort(400);
        }

        $mail_hash = hash('sha256', $email);

        if (UserMail::where('mail_hash', $mail_hash)->count() != 0) {
            $key = ['time' => time()];

            return response()->json([
                'code' => 1,
                'msg'  => '',
                'data' => [
                    'list'      => [],
                    'new_key'   => Crypt::encryptString(json_encode($key)),
                    'duplicate' => true,
                ],
            ]);
        }

        $where = [
            'to_hash' => $mail_hash,
            'is_read' => 0,
            'user_id' => 0,
        ];
        // $to_hash = hash('sha256', $email);
        // $where[] = ['to_hash', '=', $to_hash];

        try {
            $key = Crypt::decryptString($key);
            $key = json_decode($key, true);
            if (time() - $key['time'] > 300) {
                throw new Exception("The token has expired.", 400);
            }
            // if (!empty($key['id'])) {
            //     $where[] = ['id', '>', $key['id']];
            // } elseif (time() - $key['time'] < 300) {
            //     $where[] = ['received_at', '>', Carbon::parse($key['time'])];
            // } else {
            //     $where[] = ['received_at', '>', Carbon::now()->subSeconds(60)];
            // }
        } catch (\Throwable $th) {
            return abort(400, $th->getMessage());
        }

        $email_list = Mail::where($where)
            ->select([
                'id as key',
                'from',
                'to',
                'title',
                'received_at',
                'created_at',
            ])
            ->orderBy('received_at', 'asc')
            ->get();

        // $mail_ids = array_column($email_list->toArray(), 'key');

        foreach ($email_list as $value) {
            $value->hash = hash('sha256', $value->key . $value->to . $value->received_at . $value->created_at);
            $value->key  = Crypt::encryptString($value->key);
        }

        // Mail::whereIn('id', $mail_ids)->update([
        //     'is_read' => 1,
        // ]);

        $key = ['time' => time()];

        return response()->json([
            'code' => 1,
            'msg'  => '',
            'data' => [
                'list'      => $email_list,
                'new_key'   => Crypt::encryptString(json_encode($key)),
                'duplicate' => false,
            ],
        ]);
    }

    public function put(Request $request)
    {
        $key           = $request->input('key');
        $from          = $request->input('from', '');
        $to            = $request->input('to', '');
        $title         = $request->input('title', '');
        $body          = $request->input('body', '');
        $from_addr     = $request->input('from_addr', '');
        $from_protocol = $request->input('from_protocol', '');
        $received_at   = $request->input('received_at');
        if ($key != config('app.api_key')) {
            return abort(401);
        }

        $to   = strtolower($to);
        $from = strtolower($from);

        $mail = new Mail;

        $mail->from      = $from;
        $mail->from_hash = hash('sha256', $from);
        $mail->to        = $to;
        $mail->to_hash   = hash('sha256', $to);

        $mail->title         = $title;
        $mail->body          = $body;
        $mail->from_addr     = $from_addr;
        $mail->from_protocol = $from_protocol;
        $mail->received_at   = Carbon::parse($received_at);
        $mail->is_read       = 0;

        $mail->user_id = UserMail::where(['mail_hash' => $mail->to_hash, 'is_disable' => 0])->value('user_id') ?? 0;

        $mail->save();

        return response()->json([
            'code' => 1,
            'msg'  => 'success',
            'data' => new \stdClass,
        ]);
    }

    public function info(Request $request, $key)
    {
        try {
            $id = Crypt::decryptString($key);
        } catch (\Throwable $th) {
            return abort(400);
        }

        if (empty(intval($id))) {
            return abort(400);
        }

        $mail_info = Mail::find($id);
        if (empty($mail_info) || $mail_info->user_id != 0) {
            return abort(404);
        }

        $mail_info->is_read = 1;
        $mail_info->save();

        $title = str_replace(["\n", "\r", "\t"], '', strip_tags($mail_info->title));
        $body  = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $mail_info->body);

        return response()->json([
            'code' => 1,
            'msg'  => '',
            'data' => [
                'from'        => $mail_info->from,
                'title'       => base64_encode($title),
                'body'        => base64_encode($body),
                'created_at'  => $mail_info->created_at,
                'received_at' => $mail_info->received_at,
            ],
        ]);

    }
}
