<?php

namespace Modules\Employees\Controllers;

use core\Controller;
use core\Auth;
use core\Database;

class SalaryController extends Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    public function index(): void
    {
        $this->requirePermission('salaries_view');

        $db = Database::getInstance();
        $employeeId = $this->request->get('employee_id', '');
        $month = $this->request->get('month', date('m'));
        $year = $this->request->get('year', date('Y'));
        $status = $this->request->get('status', '');
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;

        $query = $db->table('employee_salary s')
            ->select('s.*, e.first_name, e.last_name, e.job_title')
            ->leftJoin('employees e', 's.employee_id', '=', 'e.id');

        if (!empty($employeeId)) {
            $query->where('s.employee_id', $employeeId);
        }

        if (!empty($month) || !empty($year)) {
            $m = $month ?: '01';
            $y = $year ?: date('Y');
            $startDate = sprintf('%04d-%02d-01', $y, $m);
            $endDate = date('Y-m-t', strtotime($startDate));
            $query->where('s.salary_date', '>=', $startDate)
                  ->where('s.salary_date', '<=', $endDate);
        }

        if (!empty($status)) {
            $query->where('s.payment_status', $status);
        }

        $salaries = $query->orderBy('s.created_at', 'DESC')
            ->paginate($perPage, $page);

        $months = [
            '01' => 'January', '02' => 'February', '03' => 'March', '04' => 'April',
            '05' => 'May', '06' => 'June', '07' => 'July', '08' => 'August',
            '09' => 'September', '10' => 'October', '11' => 'November', '12' => 'December',
        ];

        $currentYear = (int)date('Y');
        $years = range($currentYear - 5, $currentYear + 1);

        $employees = $db->table('employees')
            ->where('is_active', 1)
            ->where('deleted_at', 'IS', null)
            ->orderBy('first_name', 'ASC')
            ->get();

        $this->view('Employees/salary', [
            'title' => 'Salaries',
            'breadcrumb' => ['Salaries' => url('salary')],
            'salaries' => $salaries,
            'employeeId' => $employeeId,
            'month' => $month,
            'year' => $year,
            'status' => $status,
            'months' => $months,
            'years' => $years,
            'employees' => $employees,
        ]);
    }

    public function create(): void
    {
        $this->requirePermission('salaries_create');

        $db = Database::getInstance();
        $selectedEmployeeId = $this->request->get('employee_id', '');
        $selectedMonth = $this->request->get('month', date('m'));
        $selectedYear = $this->request->get('year', date('Y'));

        $employees = $db->table('employees')
            ->where('is_active', 1)
            ->where('deleted_at', 'IS', null)
            ->orderBy('first_name', 'ASC')
            ->get();

        $months = [
            '01' => 'January', '02' => 'February', '03' => 'March', '04' => 'April',
            '05' => 'May', '06' => 'June', '07' => 'July', '08' => 'August',
            '09' => 'September', '10' => 'October', '11' => 'November', '12' => 'December',
        ];

        $currentYear = (int)date('Y');
        $years = range($currentYear - 5, $currentYear + 1);

        $this->view('Employees/salary_create', [
            'title' => 'Generate Salary',
            'breadcrumb' => [
                'Salaries' => url('salary'),
                'Generate' => url('salary/create'),
            ],
            'employees' => $employees,
            'months' => $months,
            'years' => $years,
            'selectedEmployeeId' => $selectedEmployeeId,
            'selectedMonth' => $selectedMonth,
            'selectedYear' => $selectedYear,
        ]);
    }

    public function store(): void
    {
        $this->requirePermission('salaries_create');

        $validated = $this->validate([
            'employee_id' => 'required|integer',
            'month' => 'required|max_length:2',
            'year' => 'required|integer|min:2020|max:2100',
            'basic_salary' => 'numeric|min:0',
            'commission_total' => 'numeric|min:0',
            'bonus' => 'numeric|min:0',
            'deductions' => 'numeric|min:0',
            'notes' => 'max_length:2000',
        ]);

        $db = Database::getInstance();

        $salaryDate = $validated['year'] . '-' . str_pad($validated['month'], 2, '0', STR_PAD_LEFT) . '-01';

        $existing = $db->table('employee_salary')
            ->where('employee_id', $validated['employee_id'])
            ->where('salary_date', $salaryDate)
            ->first();

        if ($existing) {
            $this->redirectWith(url('salary'), 'warning', 'Salary already generated for this period.');
        }

        $employee = $db->table('employees')->find($validated['employee_id']);
        if (!$employee) {
            $this->redirectWith(url('salary/create'), 'error', 'Employee not found.');
        }

        $netSalary = ($validated['basic_salary'] + $validated['commission_total'] + $validated['bonus']) - $validated['deductions'];

        $salaryId = $db->table('employee_salary')->insert([
            'employee_id' => $validated['employee_id'],
            'salary_date' => $validated['year'] . '-' . str_pad($validated['month'], 2, '0', STR_PAD_LEFT) . '-01',
            'basic_salary' => $validated['basic_salary'] ?? 0,
            'commission_total' => $validated['commission_total'] ?? 0,
            'bonus' => $validated['bonus'] ?? 0,
            'deductions' => $validated['deductions'] ?? 0,
            'net_salary' => max(0, $netSalary),
            'payment_status' => 'pending',
            'notes' => $validated['notes'] ?? null,
            'created_at' => date(DATE_TIME_FORMAT),
            'updated_at' => date(DATE_TIME_FORMAT),
        ]);

        $this->logActivity('generate_salary', "Generated salary #{$salaryId} for employee: {$employee->first_name} {$employee->last_name}");
        $this->logAudit('create', 'salaries', $salaryId, null, $validated);

        $this->redirectWith(url('salary'), 'success', 'Salary generated successfully.');
    }

    public function pay(int $id): void
    {
        $this->requirePermission('salaries_edit');

        $db = Database::getInstance();
        $salary = $db->table('employee_salary')->find($id);

        if (!$salary) {
            $this->redirectWith(url('salary'), 'error', 'Salary record not found.');
        }

        if ($salary->payment_status === 'paid') {
            $this->redirectWith(url('salary'), 'warning', 'Salary already paid.');
        }

        $db->table('employee_salary')
            ->where('id', $id)
            ->update([
                'payment_status' => 'paid',
                'payment_date' => date(DATE_TIME_FORMAT),
                'updated_at' => date(DATE_TIME_FORMAT),
            ]);

        $this->logActivity('pay_salary', 'Paid salary #' . $id);
        $this->logAudit('update', 'employee_salary', $id, (array)$salary, ['payment_status' => 'paid']);

        $this->redirectWith(url('salary'), 'success', 'Salary marked as paid.');
    }

    public function payslip(int $id): void
    {
        $this->requirePermission('salaries_view');

        $db = Database::getInstance();

        $salary = $db->query(
            "SELECT s.*, e.first_name, e.last_name, e.job_title, e.email, e.phone, e.hire_date,
                    e.salary_type, e.salary_amount, e.hourly_rate, e.commission_percent,
                    u.first_name as processed_by_first_name, u.last_name as processed_by_last_name
             FROM employee_salary s
             INNER JOIN employees e ON s.employee_id = e.id
             LEFT JOIN users u ON s.paid_by = u.id
             WHERE s.id = :id",
            [':id' => $id]
        );

        if (empty($salary)) {
            $this->redirectWith(url('salary'), 'error', 'Salary record not found.');
        }

        $salary = $salary[0];

        $salaryMonth = date('m', strtotime($salary->salary_date));
        $salaryYear = date('Y', strtotime($salary->salary_date));

        $commissions = $db->table('employee_commissions c')
            ->select('c.*, services.name as service_name')
            ->leftJoin('services', 'c.service_id', '=', 'services.id')
            ->where('c.employee_id', $salary->employee_id)
            ->where('c.status', 'paid')
            ->whereRaw("MONTH(c.paid_at) = ? AND YEAR(c.paid_at) = ?", [$salaryMonth, $salaryYear])
            ->get();

        $this->view('Employees/payslip', [
            'title' => 'Payslip - ' . $salary->first_name . ' ' . $salary->last_name,
            'breadcrumb' => [
                'Salaries' => url('salary'),
                'Payslip' => url('salary/payslip/' . $id),
            ],
            'salary' => $salary,
            'commissions' => $commissions,
        ]);
    }
}
