<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Helpers\Auth;
use App\Helpers\Csrf;
use App\Helpers\Mailer;
use App\Helpers\SessionHelper;
use App\Models\AdvanceSalary;
use App\Models\Claim;
use App\Models\LeaveRequest;
use App\Models\Log;
use App\Models\User;
use PDO;

class ApproverController extends Controller
{
    private string $adminLoginId = '999999999999';

    private PDO $pdo;  // Declare property manually

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo; // Assign manually (PHP 7.4 style)
    }

    public function pending(): void
    {
        Auth::requireRole(['approver']);
        $advance = (new AdvanceSalary($this->pdo))->pending();
        $leave = (new LeaveRequest($this->pdo))->pending();
        $claims = (new Claim($this->pdo))->pending();

        $this->view('approver/pending', [
            'advance' => $advance,
            'leave' => $leave,
            'claims' => $claims,
            'csrf' => Csrf::field(),
            'message' => SessionHelper::flash('message'),
            'error' => SessionHelper::flash('error'),
        ]);
    }

    public function update(): void
    {
        Auth::requireRole(['approver']);

        if (!Csrf::validate($_POST['_token'] ?? null)) {
            SessionHelper::flash('error', 'Invalid CSRF token');
            header('Location: index.php?route=approver/pending');
            exit;
        }

        $type = $_POST['type'] ?? '';
        $id = (int) ($_POST['id'] ?? 0);
        $action = $_POST['action'] ?? '';
        $remarks = trim($_POST['remarks'] ?? '');

        if (!in_array($action, ['approved', 'rejected'], true)) {
            SessionHelper::flash('error', 'Invalid action.');
            header('Location: index.php?route=approver/pending');
            exit;
        }
        if ($remarks === '') {
            SessionHelper::flash('error', 'Remarks required.');
            header('Location: index.php?route=approver/pending');
            exit;
        }

        $approver = SessionHelper::user();
        $admin = (new User($this->pdo))->findByLoginId($this->adminLoginId);

        $method = $action === 'approved' ? 'handleApproval' : 'handleRejection';
        $result = $this->$method($type, $id, $approver['id'], $remarks, $admin);

        if ($result) {
            SessionHelper::flash('message', "Request {$action}.");
        } else {
            SessionHelper::flash('error', 'Unable to update request.');
        }

        header('Location: index.php?route=approver/pending');
    }

    private function handleApproval(string $type, int $id, int $approverId, ?string $remarks, ?array $admin): bool
    {
        $log = new Log($this->pdo);
        switch ($type) {
            case 'advance':
                $model = new AdvanceSalary($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'approved', $approverId, $remarks);
                $log->record('advance_approved', $approverId, json_encode(['id' => $id]));
                if ($admin && !empty($admin['email'])) {
                    Mailer::send(
                        $admin['email'],
                        'Advance Salary Approved',
                        $this->renderEmail('emails/approved.php', [
                            'subject' => 'Advance Salary Approved',
                            'message' => "Advance salary request #{$id} approved and ready for payroll.",
                        ])
                    );
                }
                return true;
            case 'leave':
                $model = new LeaveRequest($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'approved', $approverId, $remarks);
                $log->record('leave_approved', $approverId, json_encode(['id' => $id]));
                if ($admin && !empty($admin['email'])) {
                    Mailer::send(
                        $admin['email'],
                        'Leave Approved',
                        $this->renderEmail('emails/approved.php', [
                            'subject' => 'Leave Approved',
                            'message' => "Leave request #{$id} approved and added to payroll summary.",
                        ])
                    );
                }
                return true;
            case 'claim':
                $model = new Claim($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'approved', $approverId, $remarks);
                $log->record('claim_approved', $approverId, json_encode(['id' => $id]));
                if ($admin && !empty($admin['email'])) {
                    Mailer::send(
                        $admin['email'],
                        'Claim Approved',
                        $this->renderEmail('emails/approved.php', [
                            'subject' => 'Claim Approved',
                            'message' => "Claim #{$id} approved. Please process payment.",
                        ])
                    );
                }
                return true;
        }
        return false;
    }

    private function handleRejection(string $type, int $id, int $approverId, ?string $remarks, ?array $admin): bool
    {
        $log = new Log($this->pdo);
        switch ($type) {
            case 'advance':
                $model = new AdvanceSalary($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'rejected', $approverId, $remarks);
                $log->record('advance_rejected', $approverId, json_encode(['id' => $id]));
                if (!empty($record['email'])) {
                    Mailer::send(
                        $record['email'],
                        'Advance Salary Rejected',
                        $this->renderEmail('emails/rejected.php', [
                            'subject' => 'Advance Salary Rejected',
                            'message' => "Advance salary request #{$id} rejected. Remarks: {$remarks}",
                        ])
                    );
                }
                return true;
            case 'leave':
                $model = new LeaveRequest($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'rejected', $approverId, $remarks);
                $log->record('leave_rejected', $approverId, json_encode(['id' => $id]));
                if (!empty($record['email'])) {
                    Mailer::send(
                        $record['email'],
                        'Leave Rejected',
                        $this->renderEmail('emails/rejected.php', [
                            'subject' => 'Leave Rejected',
                            'message' => "Leave request #{$id} rejected. Remarks: {$remarks}",
                        ])
                    );
                }
                return true;
            case 'claim':
                $model = new Claim($this->pdo);
                $record = $model->find($id);
                if (!$record) {
                    return false;
                }
                $model->updateStatus($id, 'rejected', $approverId, $remarks);
                $log->record('claim_rejected', $approverId, json_encode(['id' => $id]));
                if (!empty($record['email'])) {
                    Mailer::send(
                        $record['email'],
                        'Claim Rejected',
                        $this->renderEmail('emails/rejected.php', [
                            'subject' => 'Claim Rejected',
                            'message' => "Claim #{$id} rejected. Remarks: {$remarks}",
                        ])
                    );
                }
                return true;
        }
        return false;
    }

    private function renderEmail(string $template, array $data): string
    {
        ob_start();
        extract($data);
        include __DIR__ . '/../views/' . $template;
        return (string) ob_get_clean();
    }
}

