<?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(Request $request): Response
    {
        $this->authorize('accounting.journal.view');

        $page = max(1, (int) ($request->get('page', 1)));
        $filters = [
            'status'         => $request->get('status'),
            'date_from'      => $request->get('date_from'),
            'date_to'        => $request->get('date_to'),
            'source_module'  => $request->get('source_module'),
            'fiscal_year_id' => $request->get('fiscal_year_id'),
            'search'         => $request->get('search'),
        ];

        $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(Request $request): Response
    {
        $this->authorize('accounting.journal.create');

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

        // Parse lines from POST
        $lines = [];
        $lineAccounts = $request->post('line_account_id', []);
        $lineDebits = $request->post('line_debit', []);
        $lineCredits = $request->post('line_credit', []);
        $lineDescriptions = $request->post('line_description', []);

        $lineCostCenterIds = $request->post('line_cost_center_id', []);
        $lineBranchIds = $request->post('line_branch_id', []);

        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($lineCostCenterIds[$i]) ? (int) $lineCostCenterIds[$i] : null,
                'branch_id'      => !empty($lineBranchIds[$i]) ? (int) $lineBranchIds[$i] : null,
            ];
        }

        $result = JournalService::createEntry([
            'entry_date'     => $data['entry_date'],
            'description_ar' => $data['description_ar'],
            'description_en' => $request->post('description_en'),
            'reference_type' => 'manual',
            'reference_number' => $request->post('reference_number'),
            'branch_id'      => $request->post('branch_id') ? (int) $request->post('branch_id') : null,
            'cost_center_id' => $request->post('cost_center_id') ? (int) $request->post('cost_center_id') : null,
            'notes'          => $request->post('notes'),
        ], $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(Request $request): Response
    {
        $this->authorize('accounting.journal.view');

        $term = $request->get('q', '');
        $results = Account::search($term);

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