<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Models\DTO\SearchData;
use App\Models\DTO\ResponseData;
use Exception;

class BoardGroup extends Model
{
    protected $table = 'tb_board_group';
    protected $primaryKey = 'id';

    public $keyType = 'int';
    public $incrementing = true;
    public $timestamps = true;

    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';
    const DELETED_AT = null;

    protected $guarded = [];

    public function board()
    {
        return $this->hasMany(Board::class);
    }

    public function boardGroupAdmin()
    {
        return $this->hasMany(BoardGroupAdmin::class);
    }

    public function boardGroupMeta()
    {
        return $this->hasMany(BoardGroupMeta::class);
    }

    /**
     * 게시판 그룹 조회
     */
    public function data(SearchData $params): object
    {
        $query = $this->query();
        $query->select(
            'tb_board_group.*',
            DB::raw('(SELECT COUNT(*) FROM tb_board WHERE board_group_id = tb_board_group.id) AS boardRows'),
            DB::raw('(SELECT SUM(post_rows) FROM tb_board WHERE board_group_id = tb_board.id) AS postRows'),
            DB::raw('(SELECT SUM(comment_rows) FROM tb_board WHERE board_group_id = tb_board.id) AS commentRows')
        );

        if($params->keyword) {
            switch ($params->field) {
                case 'tb_board_group.code' :
                case 'tb_board_group.name' :
                case 'users.name' :
                case 'users.email' :
                    $query->where($params->field, 'LIKE', "%{$params->keyword}%");
                    break;
                case 'tb_board_group.id' :
                case 'users.id' :
                case 'users.sid' :
                    $query->where($params->field, '=', $params->keyword);
                    break;
            }
        }

        $query->orderBy('sort');

        $list = $query->paginate($params->perPage, ['*'], 'page', $params->page);
        $total = $this->count();
        $rows = $list->count();

        return (object)[
            'total' => $total,
            'rows' => $rows,
            'list' => $list
        ];
    }

    /**
     * 게시판 그룹 등록
     */
    public function register(Request $request, ResponseData $response): ResponseData
    {
        DB::beginTransaction();

        try {

            $posts = $request->all();
            $id = (intval($this->all()->last()?->getKey()) + 1);

            $this->insert([
                'id' => $id,
                'code' => $posts['code'],
                'name' => $posts['name'],
                'sort' => $posts['sort']
            ]);

            (new BoardGroupMeta)->save($id, [
                'pc_header_content' => $posts['pc_header_content'],
                'pc_footer_content' => $posts['pc_footer_content'],
                'mobile_header_content' => $posts['mobile_header_content'],
                'mobile_footer_content' => $posts['mobile_footer_content']
            ]);

            DB::commit();
        } catch (Exception $e) {
            $response = $response::fromException($e);
            DB::rollBack();
        }

        return $response;
    }

    /**
     * 게시판 그룹 수정
     */
    public function updater(int $boardGroupID, Request $request, ResponseData $response): ResponseData
    {
        DB::beginTransaction();

        try {

            $posts = $request->all();

            $this->find($boardGroupID)->update([
                'code' => $posts['code'],
                'name' => $posts['name'],
                'sort' => $posts['sort'],
                'updated_at' => now()
            ]);

            (new BoardGroupMeta)->save($boardGroupID, [
                'pc_header_content' => $posts['pc_header_content'],
                'pc_footer_content' => $posts['pc_footer_content'],
                'mobile_header_content' => $posts['mobile_header_content'],
                'mobile_footer_content' => $posts['mobile_footer_content']
            ]);

            DB::commit();
        } catch (Exception $e) {
            $response = $response::fromException($e);
            DB::rollBack();
        }

        return $response;
    }

    /**
     * 삭제
     */
    public function remove(int $boardGroupID): mixed
    {
        return DB::transaction(function() use($boardGroupID) {
            $boardGroup = $this->findOrNew($boardGroupID);

            if($boardGroup->exists) {
                self::deleting(function($boardGroup)
                {
                    // 게시판 그룹 관리자 삭제
                    $boardGroup->boardGroupAdmin()->each(function($admin) {
                        $admin->delete();
                    });

                    // 게시판 그룹 메타 삭제
                    $boardGroup->boardGroupMeta()->each(function($meta) {
                        $meta->delete();
                    });

                    // 게시판 삭제
                    $boardGroup->board()->each(function($board) {
                        $board->remove($board->id);
                    });
                });

                $boardGroup->delete();
            }

            return true;
        });
    }
}
