<?php
declare(strict_types=1);
require __DIR__ . '/app/bootstrap.php';
require_permission('finance.journals.create');
require __DIR__ . '/app/layout.php';

$pdo = db();
$companyId = company_id();
$userId = (int)user()['id'];

function journal_period(string $date): array
{
    $stmt = db()->prepare("SELECT fp.* FROM fiscal_periods fp JOIN fiscal_years fy ON fy.id=fp.fiscal_year_id WHERE fy.company_id=? AND ? BETWEEN fp.starts_on AND fp.ends_on LIMIT 1");
    $stmt->execute([company_id(), $date]);
    $period = $stmt->fetch();
    if (!$period || $period['status'] !== 'open') { throw new RuntimeException('لا توجد فترة مالية مفتوحة لتاريخ القيد.'); }
    return $period;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verify_csrf();
    try {
        $action = (string)($_POST['action'] ?? '');
        if ($action === 'create') {
            $date = (string)($_POST['entry_date'] ?? '');
            $description = trim((string)($_POST['description'] ?? ''));
            $accountIds = $_POST['account_id'] ?? [];
            $debits = $_POST['debit'] ?? [];
            $credits = $_POST['credit'] ?? [];
            $projectId = (int)($_POST['project_id'] ?? 0);
            $costCenterId = (int)($_POST['cost_center_id'] ?? 0);
            if ($projectId && !$costCenterId) { $costCenterId = (int)scalar('SELECT cost_center_id FROM projects WHERE id=? AND company_id=?', [$projectId,$companyId]); }
            if (!$date || !$description || count($accountIds) < 2) { throw new RuntimeException('أدخل وصف القيد وسطرين على الأقل.'); }
            $lines = []; $totalDebit = 0.0; $totalCredit = 0.0;
            foreach ($accountIds as $i => $accountId) {
                $debit = round((float)($debits[$i] ?? 0), 2); $credit = round((float)($credits[$i] ?? 0), 2);
                if (!$accountId || ($debit <= 0 && $credit <= 0) || ($debit > 0 && $credit > 0)) { continue; }
                $check=$pdo->prepare('SELECT requires_project FROM accounts WHERE id=? AND company_id=?'); $check->execute([(int)$accountId,$companyId]); $flags=$check->fetch();
                if(!$flags) throw new RuntimeException('أحد الحسابات المختارة غير تابع للشركة.');
                if((int)$flags['requires_project']===1 && !$projectId) throw new RuntimeException('أحد الحسابات المختارة يتطلب تحديد مشروع.');
                $lines[] = [(int)$accountId, $debit, $credit]; $totalDebit += $debit; $totalCredit += $credit;
            }
            if (count($lines) < 2 || abs($totalDebit - $totalCredit) > 0.009 || $totalDebit <= 0) { throw new RuntimeException('القيد غير متوازن. يجب أن يتساوى إجمالي المدين والدائن.'); }
            $period = journal_period($date);
            $pdo->beginTransaction();
            $bookId = (int)scalar("SELECT id FROM journal_books WHERE company_id=? AND book_type='general' LIMIT 1", [$companyId]);
            if (!$bookId) { $pdo->prepare("INSERT INTO journal_books(company_id,code,name_ar,book_type,is_active) VALUES (?,'GJ','اليومية العامة','general',1)")->execute([$companyId]); $bookId = (int)$pdo->lastInsertId(); }
            $branchId = (int)user()['branch_id'];
            $currencyId = (int)scalar('SELECT base_currency_id FROM companies WHERE id=?', [$companyId]);
            $entryNo = 'GJ-' . date('Ymd', strtotime($date)) . '-' . str_pad((string)((int)scalar('SELECT COUNT(*)+1 FROM journal_entries WHERE company_id=?', [$companyId])), 5, '0', STR_PAD_LEFT);
            $stmt = $pdo->prepare("INSERT INTO journal_entries(company_id,branch_id,fiscal_period_id,journal_book_id,entry_no,entry_date,description,currency_id,status,created_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?, 'draft',?,NOW(),NOW())");
            $stmt->execute([$companyId,$branchId,$period['id'],$bookId,$entryNo,$date,$description,$currencyId,$userId]);
            $entryId = (int)$pdo->lastInsertId();
            $stmt = $pdo->prepare('INSERT INTO journal_lines(journal_entry_id,line_no,account_id,description,debit_amount,credit_amount,project_id,cost_center_id,created_at) VALUES (?,?,?,?,?,?,?,?,NOW())');
            foreach ($lines as $i => $line) { $stmt->execute([$entryId,$i+1,$line[0],$description,$line[1],$line[2],$projectId?:null,$costCenterId?:null]); }
            $pdo->commit(); audit('journal.create','journal_entry',(string)$entryId,['entry_no'=>$entryNo]);
            flash('success','تم حفظ القيد كمسودة: ' . $entryNo);
        } elseif (in_array($action, ['approve','post'], true)) {
            $id = (int)($_POST['id'] ?? 0);
            if ($action === 'approve') { $stmt=$pdo->prepare("UPDATE journal_entries SET status='approved',approved_by=?,approved_at=NOW() WHERE id=? AND company_id=? AND status='draft'"); }
            else { $stmt=$pdo->prepare("UPDATE journal_entries SET status='posted',posted_by=?,posted_at=NOW() WHERE id=? AND company_id=? AND status='approved'"); }
            $stmt->execute([$userId,$id,$companyId]);
            if (!$stmt->rowCount()) { throw new RuntimeException('تعذر تغيير حالة القيد؛ تحقق من حالته الحالية.'); }
            audit('journal.'.$action,'journal_entry',(string)$id); flash('success',$action==='approve'?'تم اعتماد القيد.':'تم ترحيل القيد نهائيًا.');
        }
    } catch (Throwable $e) { if ($pdo->inTransaction()) $pdo->rollBack(); flash('error',$e->getMessage()); }
    redirect('journals.php');
}

$accounts = $pdo->prepare("SELECT id,code,name_ar FROM accounts WHERE company_id=? AND is_postable=1 AND status='active' ORDER BY code"); $accounts->execute([$companyId]); $accounts=$accounts->fetchAll();
$projectStmt=$pdo->prepare("SELECT id,project_no,name_ar,cost_center_id FROM projects WHERE company_id=? AND status='active' AND deleted_at IS NULL ORDER BY project_no");$projectStmt->execute([$companyId]);$projects=$projectStmt->fetchAll();
$centerStmt=$pdo->prepare("SELECT id,code,name_ar FROM cost_centers WHERE company_id=? AND is_active=1 ORDER BY code");$centerStmt->execute([$companyId]);$centers=$centerStmt->fetchAll();
$entries = $pdo->prepare("SELECT je.*,SUM(jl.debit_amount) total FROM journal_entries je JOIN journal_lines jl ON jl.journal_entry_id=je.id WHERE je.company_id=? GROUP BY je.id ORDER BY je.id DESC LIMIT 100"); $entries->execute([$companyId]); $entries=$entries->fetchAll();
render_header('journals','القيود اليومية','إنشاء القيود واعتمادها وترحيلها مع منع عدم التوازن.');
?>
<section class="panel form-card"><div class="form-grid"><label>المشروع<select name="project_id" form="journalForm"><option value="0">بدون مشروع</option><?php foreach($projects as $p):?><option value="<?= (int)$p['id'] ?>"><?= e($p['project_no'].' — '.$p['name_ar']) ?></option><?php endforeach;?></select></label><label>مركز التكلفة<select name="cost_center_id" form="journalForm"><option value="0">تلقائي من المشروع</option><?php foreach($centers as $c):?><option value="<?= (int)$c['id'] ?>"><?= e($c['code'].' — '.$c['name_ar']) ?></option><?php endforeach;?></select></label></div></section>
<details class="panel quick-add" open><summary>＋ إنشاء قيد يومية</summary><form method="post" id="journalForm"><?= csrf_field() ?><input type="hidden" name="action" value="create"><div class="form-grid"><label>تاريخ القيد<input type="date" name="entry_date" value="<?= date('Y-m-d') ?>" required></label><label class="wide">البيان<input name="description" required></label></div><div class="responsive-table"><table id="journalLines"><thead><tr><th>الحساب</th><th>مدين</th><th>دائن</th><th></th></tr></thead><tbody><?php for($i=0;$i<2;$i++): ?><tr><td><select name="account_id[]" required><option value="">اختر الحساب</option><?php foreach($accounts as $a): ?><option value="<?= (int)$a['id'] ?>"><?= e($a['code'].' — '.$a['name_ar']) ?></option><?php endforeach; ?></select></td><td><input type="number" step="0.01" min="0" name="debit[]" value="0"></td><td><input type="number" step="0.01" min="0" name="credit[]" value="0"></td><td><button type="button" onclick="this.closest('tr').remove()">×</button></td></tr><?php endfor; ?></tbody><tfoot><tr><th>الإجمالي</th><th id="debitTotal">0.00</th><th id="creditTotal">0.00</th><th></th></tr></tfoot></table></div><button type="button" class="secondary-btn" id="addLine">إضافة سطر</button> <button class="primary-btn">حفظ كمسودة</button></form></details>
<section class="panel data-card"><div class="responsive-table"><table><thead><tr><th>رقم القيد</th><th>التاريخ</th><th>البيان</th><th>المبلغ</th><th>الحالة</th><th>الإجراء</th></tr></thead><tbody><?php foreach($entries as $e): ?><tr><td><?= e($e['entry_no']) ?></td><td><?= e($e['entry_date']) ?></td><td><?= e($e['description']) ?></td><td><?= number_format((float)$e['total'],2) ?></td><td><span class="chip"><?= e($e['status']) ?></span></td><td><?php if($e['status']==='draft'): ?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="approve"><input type="hidden" name="id" value="<?= (int)$e['id'] ?>"><button>اعتماد</button></form><?php elseif($e['status']==='approved'): ?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="post"><input type="hidden" name="id" value="<?= (int)$e['id'] ?>"><button>ترحيل</button></form><?php endif; ?></td></tr><?php endforeach; ?></tbody></table></div></section>
<template id="lineTemplate"><tr><td><select name="account_id[]" required><option value="">اختر الحساب</option><?php foreach($accounts as $a): ?><option value="<?= (int)$a['id'] ?>"><?= e($a['code'].' — '.$a['name_ar']) ?></option><?php endforeach; ?></select></td><td><input type="number" step="0.01" min="0" name="debit[]" value="0"></td><td><input type="number" step="0.01" min="0" name="credit[]" value="0"></td><td><button type="button" onclick="this.closest('tr').remove()">×</button></td></tr></template>
<script>const body=document.querySelector('#journalLines tbody'),tpl=document.querySelector('#lineTemplate');document.querySelector('#addLine').onclick=()=>body.append(tpl.content.cloneNode(true));document.querySelector('#journalForm').addEventListener('input',()=>{let d=0,c=0;document.querySelectorAll('[name="debit[]"]').forEach(x=>d+=Number(x.value||0));document.querySelectorAll('[name="credit[]"]').forEach(x=>c+=Number(x.value||0));debitTotal.textContent=d.toFixed(2);creditTotal.textContent=c.toFixed(2)});</script>
<?php render_footer();
