<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\App;
use App\Core\Response;
use App\Modules\Accounting\Models\JournalEntry;
use App\Modules\Accounting\Models\JournalEntryLine;
use App\Modules\Accounting\Models\Account;
use App\Modules\Accounting\Models\FiscalYear;
use App\Modules\Accounting\Models\CostCenter;
use App\Modules\Accounting\Services\JournalService;

class JournalEntryController extends Controller
{
    public function index(): Response
    {
        $this->authorize('accounting.journal.view');

        $page = max(1, (int) ($_GET['page'] ?? 1));
        $filters = [
            'status'         => $_GET['status'] ?? null,
            'date_from'      => $_GET['date_from'] ?? null,
            'date_to'        => $_GET['date_to'] ?? null,
            'source_module'  => $_GET['source_module'] ?? null,
            'fiscal_year_id' => $_GET['fiscal_year_id'] ?? null,
            'search'         => $_GET['search'] ?? null,
        ];

        $result = JournalEntry::search($filters, $page);

        $fiscalYears = FiscalYear::query()
            ->where('is_archived', '=', 0)
            ->orderBy('start_date', 'DESC')
            ->get();

        return $this->view('Accounting/Views/journal_entries/index', [
            'entries'      => $result['data'],
            'total'        => $result['total'],
            'page'         => $result['page'],
            'pages'        => $result['pages'],
            'filters'      => $filters,
            'fiscal_years' => $fiscalYears,
        ]);
    }

    public function create(): Response
    {
        $this->authorize('accounting.journal.create');

        $accounts = Account::getPostableAccounts();
        $costCenters = CostCenter::getActive();
        $currentFY = FiscalYear::current();

        $db = App::getInstance()->db();
        $branches = $db->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");

        return $this->view('Accounting/Views/journal_entries/create', [
            'accounts'     => $accounts,
            'cost_centers' => $costCenters,
            'fiscal_year'  => $currentFY ? $currentFY->toArray() : null,
            'branches'     => $branches,
        ]);
    }

    public function store(): Response
    {
        $this->authorize('accounting.journal.create');

        $data = $this->validate($_POST, [
            'entry_date'     => 'required',
            'description_ar' => 'required',
        ]);

        // Parse lines from POST
        $lines = [];
        $lineAccounts = $_POST['line_account_id'] ?? [];
        $lineDebits = $_POST['line_debit'] ?? [];
        $lineCredits = $_POST['line_credit'] ?? [];
        $lineDescriptions = $_POST['line_description'] ?? [];

        for ($i = 0; $i < count($lineAccounts); $i++) {
            if (empty($lineAccounts[$i])) {
                continue;
            }
            $lines[] = [
                'account_id'     => (int) $lineAccounts[$i],
                'debit'          => $lineDebits[$i] ?? '0.00',
                'credit'         => $lineCredits[$i] ?? '0.00',
                'description_ar' => $lineDescriptions[$i] ?? null,
                'cost_center_id' => !empty($_POST['line_cost_center_id'][$i]) ? (int) $_POST['line_cost_center_id'][$i] : null,
                'branch_id'      => !empty($_POST['line_branch_id'][$i]) ? (int) $_POST['line_branch_id'][$i] : null,
            ];
        }

        $result = JournalService::createEntry([
            'entry_date'     => $data['entry_date'],
            'description_ar' => $data['description_ar'],
            'description_en' => $_POST['description_en'] ?? null,
            'reference_type' => 'manual',
            'reference_number' => $_POST['reference_number'] ?? null,
            'branch_id'      => !empty($_POST['branch_id']) ? (int) $_POST['branch_id'] : null,
            'cost_center_id' => !empty($_POST['cost_center_id']) ? (int) $_POST['cost_center_id'] : null,
            'notes'          => $_POST['notes'] ?? null,
        ], $lines, false);

        $session = App::getInstance()->session();
        if ($result['success']) {
            $session->flash('_alerts', [['type' => 'success', 'message' => 'تم إنشاء القيد ' . $result['entry_number'] . ' بنجاح']]);
            return $this->redirect('/accounting/journal-entries/' . $result['journal_entry_id']);
        }

        $session->flash('_alerts', [['type' => 'error', 'message' => $result['error']]]);
        return $this->redirect('/accounting/journal-entries/create');
    }

    public function show(Request $request, string $id): Response
    {
        $this->authorize('accounting.journal.view');

        $entry = JournalEntry::findOrFail((int) $id);
        $lines = JournalEntryLine::getByJournalEntry((int) $id);

        // Get employee names
        $db = App::getInstance()->db();
        $createdBy = null;
        if ($entry->created_by) {
            $createdBy = $db->selectOne("SELECT full_name_ar FROM employees WHERE id = ?", [(int) $entry->created_by]);
        }
        $postedBy = null;
        if ($entry->posted_by) {
            $postedBy = $db->selectOne("SELECT full_name_ar FROM employees WHERE id = ?", [(int) $entry->posted_by]);
        }

        return $this->view('Accounting/Views/journal_entries/show', [
            'entry'      => $entry->toArray(),
            'lines'      => $lines,
            'created_by' => $createdBy['full_name_ar'] ?? '—',
            'posted_by'  => $postedBy['full_name_ar'] ?? '—',
        ]);
    }

    public function post(Request $request, string $id): Response
    {
        $this->authorize('accounting.journal.post');

        $result = JournalService::postEntry((int) $id);

        $session = App::getInstance()->session();
        if ($result['success']) {
            $session->flash('_alerts', [['type' => 'success', 'message' => 'تم ترحيل القيد بنجاح']]);
        } else {
            $session->flash('_alerts', [['type' => 'error', 'message' => $result['error']]]);
        }

        return $this->redirect('/accounting/journal-entries/' . (int) $id);
    }

    public function reverse(Request $request, string $id): Response
    {
        $this->authorize('accounting.journal.reverse');

        $reason = $request->post('reason', 'عكس قيد');

        $result = JournalService::reverseEntry((int) $id, $reason);

        $session = App::getInstance()->session();
        if ($result['success']) {
            $session->flash('_alerts', [['type' => 'success', 'message' => 'تم عكس القيد — القيد العكسي: ' . $result['reversal_number']]]);
        } else {
            $session->flash('_alerts', [['type' => 'error', 'message' => $result['error']]]);
        }

        return $this->redirect('/accounting/journal-entries/' . (int) $id);
    }

    public function searchAccounts(): Response
    {
        $this->authorize('accounting.journal.view');

        $term = $_GET['q'] ?? '';
        $results = Account::search($term);

        return $this->json($results);
    }
}
