<?php

namespace App\Models;

use App\Constants\Status;
use App\Traits\ApiQuery;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;

class SupportTicket extends Model
{
    use ApiQuery;

    protected $hidden = ['email_message_id'];
    protected $casts  = ['department_data' => 'object'];

    public function department()
    {
        return $this->belongsTo(Department::class);
    }

    public function createdBy()
    {
        return $this->belongsTo(Admin::class, 'admin_id');
    }

    public function admin()
    {
        return $this->belongsTo(Admin::class, 'assign_staff_id');
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function priority()
    {
        return $this->belongsTo(Priority::class);
    }

    public function ticketStatus()
    {
        return $this->belongsTo(TicketStatus::class);
    }

    public function replies()
    {
        return $this->hasMany(SupportTicketReply::class);
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }

    public function ticketLogs()
    {
        return $this->hasMany(TicketLog::class);
    }

    public function scopePending($query)
    {
        return $query->whereHas('ticketStatus', function ($ticketStatus) {
            return $ticketStatus->where('is_awaiting', Status::YES);
        });
    }

    public function scopeOpen($query)
    {
        return $query->whereHas('ticketStatus', function ($ticketStatus) {
            return $ticketStatus->where('slug', 'open');
        });
    }

    public function scopeAnswered($query)
    {
        return $query->whereHas('ticketStatus', function ($ticketStatus) {
            return $ticketStatus->where('slug', 'answered');
        });
    }

    public function scopeCustomerReply($query)
    {
        return $query->whereHas('ticketStatus', function ($ticketStatus) {
            return $ticketStatus->where('slug', 'customer-reply');
        });
    }

    public function scopeClosed($query)
    {
        return $query->whereHas('ticketStatus', function ($ticketStatus) {
            return $ticketStatus->where('slug', 'closed');
        });
    }

    public function scopePrimary($query)
    {
        return $query->where('folder', Status::TICKET_PRIMARY);
    }

    public function scopeDraft($query)
    {
        return $query->where('folder', Status::TICKET_DRAFT);
    }
    public function scopeSpam($query)
    {
        return $query->where('folder', Status::TICKET_SPAM);
    }
    public function scopeTrash($query)
    {
        return $query->where('folder', Status::TICKET_TRASH);
    }

    public function scopeAdminAccess($query)
    {
        return $query->whereHas('department', function ($dept) {
            $dept->whereHas('admins', function ($admin) {
                $admin->where('admin_id', auth('admin')->id());
            });
        });
    }

    public static function filterTickets(Request $request, $count = false)
    {
        $query = self::adminAccess();

        if ($request->search) {
            $query->where(function ($query) use ($request) {
                $query->where('subject', 'like', '%' . $request->search . '%')
                    ->orWhere('ticket_number', 'like', '%' . $request->search . '%')
                    ->orWhereHas('user', function ($user) use ($request) {
                        $user->where('firstname', 'like', '%' . $request->search . '%')
                            ->orWhere('lastname', 'like', '%' . $request->search . '%')
                            ->orWhere('email', 'like', '%' . $request->search . '%');
                    })
                    ->orWhereHas('replies', function ($reply) use ($request) {
                        $reply->where('description', 'like', '%' . $request->search . '%');
                    });
            });
        }

        if ($request->assign == 'assigned') {
            $query->where('assign_staff_id', '>', 0);
        } elseif ($request->assign == 'unassigned') {
            $query->where('assign_staff_id', 0);
        } elseif ($request->assign == 'me') {
            $query->where('assign_staff_id', auth('admin')->id());
        }

        if ($request->admin) {
            $query->where('assign_staff_id', $request->admin);
        }

        if ($request->department) {
            $query->where('department_id', $request->department);
        }

        $creation = $request->created;
        if ($creation) {
            $range = getDateRangeByKey($creation);
            $query->whereBetween('created_at', [$range['start'], $range['end']]);
        }

        $lastActivity = $request->last_activity;
        if ($lastActivity) {
            $range = getDateRangeByKey($lastActivity);
            $query->whereHas('ticketLogs', function ($ticketLog) use ($range) {
                $ticketLog->whereBetween('created_at', [$range['start'], $range['end']]);
            });
        }

        $lastMessage = $request->last_message;
        if ($lastMessage) {
            $range = getDateRangeByKey($lastMessage);
            if ($range) {
                $query->whereHas('replies', function ($reply) use ($range) {
                    $reply->whereBetween('created_at', [$range['start'], $range['end']]);
                });
            }
        }

        if ($request->rating) {
            $query->where('customer_happiness', $request->rating);
        }

        if ($request->status) {
            $query->where('ticket_status_id', $request->status);
        }

        if ($request->priority) {
            $query->where('priority_id', $request->priority);
        }

        if ($request->has_attachment) {
            $query->whereHas('replies', function ($reply) {
                $reply->whereHas('attachments');
            });
        }

        if ($request->is_pinned) {
            $pinTickets = auth('admin')->user()->pin_ticket;
            $query->whereIn('id', $pinTickets);
        }

        if ($request->folder) {
            $folders     = ['primary', 'draft', 'spam', 'trash'];
            $folderIndex = array_search($request->folder, $folders);
            $folderIndex = $folderIndex === false ? 0 : $folderIndex;

            $query->where('folder', $folderIndex);
        } else {
            $query->primary();
        }

        if ($count) {
            return $query->count();
        }

        return $query
            ->with([
                'tags',
                'replies.admin',
                'replies.attachments',
                'department',
                'admin',
                'createdBy',
                'user',
                'priority',
                'ticketStatus',
            ])
            ->orderByRaw('CASE
                    WHEN (SELECT is_awaiting FROM ticket_statuses WHERE ticket_statuses.id = support_tickets.ticket_status_id) = 1 THEN 2
                    WHEN assign_staff_id > 0 THEN 1
                    ELSE 0
                END DESC
            ')
            ->orderByRaw('assign_staff_id > 0 DESC')
            ->orderBy('id', 'desc')
            ->paginate(getPaginate());
    }

    public function sendAutoResponse()
    {
        $supportTicketReply                    = new SupportTicketReply();
        $supportTicketReply->support_ticket_id = $this->id;
        $supportTicketReply->admin_id          = 1;
        $supportTicketReply->description       = gs('auto_response');
        $supportTicketReply->auto_response     = Status::YES;
        $supportTicketReply->save();

        $email = $this->department->pipe_only ? $this->department->email_user : ($this->department->email ?? company('email'));

        $sendFromData = [
            'email_address' => $email,
            'name'          => $this->department->name,
        ];

        notify($this->user, 'TICKET_REPLY', [
            'ticket_subject'  => $this->subject,
            'ticket_number'   => $this->ticket_number,
            'ticket_message'  => $supportTicketReply->description,
            'department_name' => $this->department->name,
        ], sendFromData: $sendFromData);
    }
}
