<?php

namespace App\Controllers;

use App\Core\View;
use App\Helpers\SlaCalculator;
use App\Models\StatusTicketModel;
use App\Services\ActivityLogService;
use App\Services\AttachmentService;
use App\Services\CategoryService;
use App\Services\PriorityService;
use App\Services\SlaService;
use App\Services\StatusTicketService;
use App\Services\TeknisiService;
use App\Services\TicketAssignmentService;
use App\Services\TicketCommentService;
use App\Services\TicketService;
use App\Services\UserService;

class TicketController
{
  private TicketService $ticketService;
  private View $view;
  private CategoryService $categoryService;
  private PriorityService $prioritasService;
  private SlaService $slaService;
  private StatusTicketService $statusTicketService;
  private TeknisiService $teknisiService;
  private AttachmentService $attachmentService;
  private ActivityLogService $activityLogService;
  private SlaCalculator $slaCalculator;
  private UserService $userService;
  private TicketAssignmentService $ticketAssignmentService;
  private TicketCommentService $ticketCommentService;

  public function __construct()
  {
    $this->categoryService = new CategoryService();
    $this->prioritasService = new PriorityService();
    $this->slaService = new SlaService();
    $this->statusTicketService = new StatusTicketService();
    $this->teknisiService = new TeknisiService();
    $this->attachmentService = new AttachmentService();
    $this->activityLogService = new ActivityLogService();
    $this->slaCalculator = new SlaCalculator();
    $this->ticketService = new TicketService($this->activityLogService, $this->statusTicketService);
    $this->userService = new UserService();
    $this->ticketAssignmentService = new TicketAssignmentService();
    $this->ticketCommentService = new TicketCommentService();
    $this->view = new View();
  }

  public function index()
  {
    $user = $_SESSION['user'];
    if ($user['role'] !== 'ADMIN') {
      redirect('LOGIN');
    }
    $filter = [
      'keyword'      => $_GET['keyword'] ?? null,
      'id_status'    => $_GET['id_status'] ?? null,
      'id_prioritas' => $_GET['id_prioritas'] ?? null,
      'id_kategori'  => $_GET['id_kategori'] ?? null,
      'id_sla'       => $_GET['id_sla'] ?? null,
    ];

    $hasFilter = !empty(array_filter(
      $filter,
      fn($value) => $value !== null && $value !== ''
    ));

    if (!$hasFilter && !empty($_GET)) {

      redirect('DAFTAR_TIKET');
      exit;
    }

    $tickets = $hasFilter
      ? $this->ticketService->findByFilter($filter)
      : $this->ticketService->findAll();

    $this->view->renderAdminPage(
      'ticket/index',
      [
        'tickets' => $tickets,
        'statusTiket' => $this->statusTicketService->findAll(),
        'daftarPrioritas' => $this->prioritasService->findAll(),
        'categories' => $this->categoryService->findAll(),
        'daftarSla' => $this->slaService->findAll()
      ]
    );
  }

  // create form
  public function createForm()
  {
    $categories = $this->categoryService->findAll();
    $prioritas = $this->prioritasService->findAll();
    $slas = $this->slaService->findAll();
    $statusTickets = $this->statusTicketService->findAll();
    $statusOpen = array_filter(
      $statusTickets,
      fn(StatusTicketModel $status) => $status->getNamaStatus() === 'OPEN'
    );

    $statusOpen = reset($statusOpen);

    $this->view->renderAdminPage(
      'ticket/tambah',
      [
        'categories' => $categories,
        'priorities' => $prioritas,
        'slas' => $slas,
        'statusOpen' => $statusOpen
      ]
    );
  }

  public function detail(int $id)
  {
    $ticket = $this->ticketService->findById($id);
    $currentStatus = $ticket->getNamaStatus();
    $availableStatus = $this->statusTicketService->getAvailableStatus($currentStatus);
    $daftarTeknisi = $this->teknisiService->findAktif();
    $attachments = $this->attachmentService->findByTicket($id);
    $timelines = $this->activityLogService->findByTicketId($id);
    $requester = $this->userService->findById($ticket->getUserId());
    $ticketAssignment = $this->ticketAssignmentService->findByTicketId($id);
    if ($ticketAssignment) {
      $teknisi = $this->teknisiService->findById($ticketAssignment->getTeknisiId());
      $teknisiUser = $this->userService->findById($teknisi->getUserId());
    }
    $comments = $this->ticketCommentService->findByTicketId($id);

    if (empty($ticket)) {
      $_SESSION['error'] = 'Tiket tidak ditemukan.';
      redirect('DAFTAR_TIKET');
      exit;
    }

    $slaResponse = $ticket->getSlaId() ? $this->slaCalculator->getSlaResponse($id) : null;
    $slaResolution = $ticket->getSlaId() ? $this->slaCalculator->getSlaResolution($id) : null;

    $user = $_SESSION['user'];
    if ($user['role'] !== 'ADMIN' && $ticket->getNamaStatus() === 'OPEN') {
      redirect('LOGIN');
    }

    $this->view->renderAdminPage(
      'ticket/detail',
      [
        'ticket' => $ticket,
        'availableStatus' => $availableStatus,
        'daftarTeknisi' => $daftarTeknisi,
        'attachments' => $attachments,
        'timelines' => $timelines,
        'slaResponse' => $slaResponse,
        'slaResolution' => $slaResolution,
        'requester' => $requester,
        'teknisi' => $teknisiUser ?? null,
        'comments' => $comments
      ]
    );
  }

  public function create()
  {
    try {
      $user = $_SESSION['user'];
      $this->ticketService->create(
        userId: (int) $_POST['userId'],
        kategoriId: (int) $_POST['kategoriId'],
        prioritasId: (int) $_POST['prioritasId'],
        slaId: (int) $_POST['slaId'],
        statusId: (int) $_POST['statusId'],
        judul: $_POST['judul'],
        deskripsi: $_POST['deskripsi'],
        attachments: $_FILES['attachments'] ?? null
      );

      $_SESSION['success'] = 'Tiket berhasil dibuat.';
    } catch (\Exception $e) {

      $_SESSION['error'] = $e->getMessage();
    }

    if ($user["role"] == "ADMIN") {
      redirect('DAFTAR_TIKET');
    } else {
      redirect('MY_ACTIVITY');
    }
    exit;
  }

  public function update()
  {
    try {

      $this->ticketService->update(
        id: (int) $_POST['id'],
        kategoriId: (int) $_POST['kategoriId'],
        prioritasId: (int) $_POST['prioritasId'],
        slaId: (int) $_POST['slaId'],
        statusId: (int) $_POST['statusId'],
        judul: $_POST['judul'],
        deskripsi: $_POST['deskripsi'],
        deadline: $_POST['deadline'] ?: null,
        isClosed: isset($_POST['isClosed'])
      );

      $_SESSION['success'] = 'Tiket berhasil diubah.';
    } catch (\Exception $e) {

      $_SESSION['error'] = 'Tiket gagal diubah: ' . $e->getMessage();
    }

    redirect('DAFTAR_TIKET');
    exit;
  }

  public function delete()
  {
    try {

      $this->ticketService->delete(
        (int) $_POST['id']
      );

      $_SESSION['success'] = 'Tiket berhasil dihapus.';
    } catch (\Exception $e) {

      $_SESSION['error'] = 'Tiket gagal dihapus: ' . $e->getMessage();
    }

    redirect('DAFTAR_TIKET');
    exit;
  }

  // update stastus

  public function updateStatus(int $id)
  {
    try {

      $statusId = filter_input(INPUT_POST, 'statusId', FILTER_VALIDATE_INT);
      $userId = $_SESSION['user']['id'] ?? 1;

      if (!$statusId) {
        throw new \Exception('Status tidak valid.');
      }

      $this->ticketService->updateStatus($id, $statusId, $userId);

      $_SESSION['success'] = 'Status tiket berhasil diubah.';
    } catch (\Exception $e) {

      $_SESSION['error'] = 'Status tiket gagal diubah: ' . $e->getMessage();
    }

    redirect('DETAIL_TIKET', ['id' => $id]);
    exit;
  }

  public function updateSla()
  {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
      redirect("DAFTAR_TIKET");
      exit;
    }

    try {

      $idTicket = $_POST['id_ticket'] ?? null;
      $idSla = $_POST['id_sla'] ?? null;
      $idPrioritas = $_POST['id_prioritas'] ?? null;


      // Validasi input
      if (!$idTicket || !$idSla || !$idPrioritas) {
        $_SESSION['error'] = "Data SLA dan prioritas wajib dipilih.";
        redirect("DAFTAR_TIKET");
        exit;
      }


      $this->ticketService->updateSlaTicket(
        (int) $idTicket,
        (int) $idSla,
        (int) $idPrioritas
      );


      $_SESSION['success'] = "SLA tiket berhasil diperbarui.";
    } catch (\Exception $e) {

      $_SESSION['error'] = "Gagal mengatur SLA tiket: " . $e->getMessage();
    }


    redirect("DAFTAR_TIKET");
  }
}
