<?php

namespace Modules\Payroll\Controllers;

use App\Controllers\BaseController;
use App\Models\PayrollItemModel;
use App\Models\PayrollRunModel;
use Modules\Payroll\Services\PayrollCalculationService;
use Modules\Payroll\Services\WpsExportService;

class PayrollRunController extends BaseController
{
    protected PayrollRunModel $runs;
    protected PayrollItemModel $items;
    protected PayrollCalculationService $calculator;
    protected WpsExportService $wps;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->runs       = new PayrollRunModel();
        $this->items      = new PayrollItemModel();
        $this->calculator = new PayrollCalculationService();
        $this->wps        = new WpsExportService();
    }

    public function index()
    {
        $year   = (int) ($this->request->getGet('year') ?: date('Y'));
        $status = $this->request->getGet('status') ?: null;

        $runs = $this->runs->scopeForList($year, $status)
            ->orderBy('period_year', 'DESC')
            ->orderBy('period_month', 'DESC')
            ->findAll();

        return view('Modules\Payroll\Views\runs\index', array_merge($this->baseViewData(), [
            'title'   => 'Payroll Runs',
            'runs'    => $runs,
            'filters' => compact('year', 'status'),
        ]));
    }

    public function createForm()
    {
        return view('Modules\Payroll\Views\runs\create', array_merge($this->baseViewData(), [
            'title' => 'New Payroll Run',
            'year'  => (int) date('Y'),
            'month' => (int) date('n'),
        ]));
    }

    public function store()
    {
        $year  = (int) $this->request->getPost('period_year');
        $month = (int) $this->request->getPost('period_month');

        $result = $this->calculator->createRun($year, $month, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/payroll/runs/' . $result['id'])->with('success', 'Payroll run created. Click Calculate to process employees.');
    }

    public function show(int $id)
    {
        $run = $this->runs->find($id);
        if (! $run) {
            return redirect()->to('/payroll/runs')->with('error', 'Payroll run not found.');
        }

        $search = trim((string) $this->request->getGet('q'));

        return view('Modules\Payroll\Views\runs\show', array_merge($this->baseViewData(), [
            'title'  => $this->runs->periodLabel($run),
            'run'    => $run,
            'items'  => $this->items->getForRun($id, $search ?: null),
            'totals' => $this->items->getRunTotals($id),
            'filters'=> compact('search'),
        ]));
    }

    public function calculate(int $id)
    {
        $result = $this->calculator->calculateRun($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', implode(' ', $result['errors'] ?? ['Calculation failed.']));
        }

        $msg = 'Payroll calculated for ' . $result['processed'] . ' employee(s).';
        if (! empty($result['skipped'])) {
            $msg .= ' Skipped: ' . implode(', ', array_slice($result['skipped'], 0, 5));
        }

        return redirect()->to('/payroll/runs/' . $id)->with('success', $msg);
    }

    public function approve(int $id)
    {
        $result = $this->calculator->approveRun($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', implode(' ', $result['errors'] ?? ['Approval failed.']));
        }

        return redirect()->to('/payroll/runs/' . $id)->with('success', 'Payroll run approved.');
    }

    public function markPaid(int $id)
    {
        $result = $this->calculator->markPaid($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->back()->with('error', implode(' ', $result['errors'] ?? ['Update failed.']));
        }

        return redirect()->to('/payroll/runs/' . $id)->with('success', 'Payroll run marked as paid.');
    }

    public function destroy(int $id)
    {
        $result = $this->calculator->deleteRun($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/payroll/runs')->with('error', $result['error']);
        }

        return redirect()->to('/payroll/runs')->with('success', 'Payroll run deleted.');
    }

    public function exportWps(int $id)
    {
        $result = $this->wps->generateCsv($id);
        if (! $result['success']) {
            return redirect()->back()->with('error', $result['error']);
        }

        return $this->response
            ->setHeader('Content-Type', 'text/csv')
            ->setHeader('Content-Disposition', 'attachment; filename="' . $result['filename'] . '"')
            ->setBody($result['content']);
    }
}
