<?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\HistoricalBalance;

class OpeningEntryController extends Controller
{
    public function index(Request $request): Response
    {
        $this->authorize('accounting.opening_entry.view');

        $db = App::getInstance()->db();
        $fiscalYears = $db->select("SELECT id, name_ar, start_date, end_date, status FROM fiscal_years WHERE is_archived = 0 ORDER BY start_date DESC");
        $selectedYearId = (int)($request->get('fiscal_year_id') ?? 0);

        $historicalBalances = [];
        if ($selectedYearId) {
            $historicalBalances = $db->select("
                SELECT hb.*, coa.account_code, coa.name_ar AS account_name
                FROM historical_balances hb
                JOIN chart_of_accounts coa ON coa.id = hb.account_id
                WHERE hb.fiscal_year_id = ?
                ORDER BY coa.account_code
            ", [$selectedYearId]);
        }

        return $this->view('Accounting/Views/opening_entries/index', [
            'fiscalYears'        => $fiscalYears,
            'selectedYearId'     => $selectedYearId,
            'historicalBalances'  => $historicalBalances,
        ]);
    }

    public function create(Request $request): Response
    {
        $this->authorize('accounting.opening_entry.manage');

        $db = App::getInstance()->db();
        $fiscalYears = $db->select("SELECT id, name_ar, start_date, end_date, status FROM fiscal_years WHERE is_archived = 0 AND status = 'open' ORDER BY start_date DESC");
        $accounts = $db->select("SELECT id, account_code, name_ar, account_type FROM chart_of_accounts WHERE is_archived = 0 AND is_header = 0 ORDER BY account_code");

        return $this->view('Accounting/Views/opening_entries/create', [
            'fiscalYears' => $fiscalYears,
            'accounts'    => $accounts,
        ]);
    }

    public function store(Request $request): Response
    {
        $this->authorize('accounting.opening_entry.manage');

        $fiscalYearId = (int)$request->post('fiscal_year_id');
        $entries = $request->post('entries', []);

        if (!$fiscalYearId || empty($entries)) {
            return $this->redirect('/accounting/opening-entries/create')
                ->withError('بيانات غير مكتملة');
        }

        $db = App::getInstance()->db();
        $session = App::getInstance()->session();
        $fy = $db->selectOne("SELECT * FROM fiscal_years WHERE id = ? AND status = 'open'", [$fiscalYearId]);

        if (!$fy) {
            return $this->redirect('/accounting/opening-entries/create')
                ->withError('السنة المالية غير مفتوحة');
        }

        $totalDebit = 0;
        $totalCredit = 0;
        $lines = [];

        foreach ($entries as $entry) {
            $accountId = (int)($entry['account_id'] ?? 0);
            $debit = (float)($entry['debit'] ?? 0);
            $credit = (float)($entry['credit'] ?? 0);

            if (!$accountId || ($debit == 0 && $credit == 0)) {
                continue;
            }

            $totalDebit += $debit;
            $totalCredit += $credit;
            $lines[] = [
                'account_id' => $accountId,
                'debit'      => $debit,
                'credit'     => $credit,
                'description' => $entry['description'] ?? 'قيد افتتاحي',
            ];
        }

        if (abs($totalDebit - $totalCredit) > 0.01) {
            return $this->redirect('/accounting/opening-entries/create')
                ->withError('القيد غير متوازن — المدين: ' . number_format($totalDebit, 2) . ' الدائن: ' . number_format($totalCredit, 2));
        }

        $now = date('Y-m-d H:i:s');
        $entryNumber = 'OPN-' . substr($fy['start_date'], 0, 4) . '-001';

        $db->insert('journal_entries', [
            'entry_number'    => $entryNumber,
            'entry_date'      => $fy['start_date'],
            'fiscal_year_id'  => $fiscalYearId,
            'reference_type'  => 'opening',
            'description'     => 'قيد افتتاحي — ' . ($fy['name_ar'] ?? ''),
            'total_debit'     => $totalDebit,
            'total_credit'    => $totalCredit,
            'status'          => 'posted',
            'posted_at'       => $now,
            'created_by'      => (int)($session->get('employee_id') ?? 0) ?: null,
            'created_at'      => $now,
            'updated_at'      => $now,
        ]);

        $journalEntryId = (int)$db->lastInsertId();

        foreach ($lines as $line) {
            $db->insert('journal_entry_lines', [
                'journal_entry_id' => $journalEntryId,
                'account_id'       => $line['account_id'],
                'debit'            => $line['debit'],
                'credit'           => $line['credit'],
                'description_ar'   => $line['description'],
                'created_at'       => $now,
            ]);
        }

        return $this->redirect('/accounting/opening-entries?fiscal_year_id=' . $fiscalYearId)
            ->withSuccess('تم إنشاء القيد الافتتاحي بنجاح');
    }

    public function snapshot(Request $request): Response
    {
        $this->authorize('accounting.opening_entry.manage');

        $fiscalYearId = (int)$request->post('fiscal_year_id');
        if (!$fiscalYearId) {
            return $this->redirect('/accounting/opening-entries')
                ->withError('اختر سنة مالية');
        }

        $count = HistoricalBalance::snapshotYear($fiscalYearId);

        return $this->redirect('/accounting/opening-entries?fiscal_year_id=' . $fiscalYearId)
            ->withSuccess("تم حفظ أرصدة {$count} حساب كأرصدة تاريخية");
    }
}
