<?php

namespace App\Core\Services\Accounting;

use App\Core\Repositories\IncomeRepository;
use App\Models\Income;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * Income Service
 * Handles income business logic
 */
class IncomeService
{
    public function __construct(
        private IncomeRepository $repository,
        private JournalEntryService $journalService
    ) {}

    /**
     * Create a new income record
     */
    public function create(array $data): Income
    {
        DB::beginTransaction();

        try {
            // Generate income number
            $data['income_number'] = $this->repository->generateIncomeNumber();

            // Calculate total
            $data['total'] = ($data['amount'] ?? 0) + ($data['tax_amount'] ?? 0);

            // Create income
            $income = $this->repository->create([
                'income_number' => $data['income_number'],
                'income_date' => $data['income_date'],
                'account_id' => $data['account_id'],
                'customer_id' => $data['customer_id'] ?? null,
                'category' => $data['category'] ?? null,
                'payment_method' => $data['payment_method'] ?? 'cash',
                'bank_account_id' => $data['bank_account_id'] ?? null,
                'amount' => $data['amount'],
                'tax_amount' => $data['tax_amount'] ?? 0,
                'total' => $data['total'],
                'currency' => $data['currency'] ?? \App\Models\Currency::getDefaultCode(),
                'description' => $data['description'] ?? null,
                'notes' => $data['notes'] ?? null,
                'reference_type' => $data['reference_type'] ?? null,
                'reference_id' => $data['reference_id'] ?? null,
                'status' => $data['status'] ?? 'draft',
                'created_by' => auth()->id(),
            ]);

            // If status is recorded, create journal entry
            if ($income->status === 'recorded') {
                $this->recordIncome($income);
            }

            DB::commit();

            return $income->load(['account', 'customer']);
        } catch (Exception $e) {
            DB::rollBack();
            Log::error('Income creation failed: '.$e->getMessage());
            throw $e;
        }
    }

    /**
     * Record income in accounting (create journal entry)
     */
    public function recordIncome(Income $income): void
    {
        $account = $income->account;
        $cashAccount = $this->getCashAccount($income->payment_method);

        $this->journalService->create([
            'entry_date' => $income->income_date,
            'description' => 'Income: '.$income->income_number,
            'status' => 'posted',
            'reference_type' => 'income',
            'reference_id' => $income->id,
            'lines' => [
                [
                    'account_id' => $cashAccount->id,
                    'type' => 'debit',
                    'amount' => $income->total,
                    'description' => 'Payment for income '.$income->income_number,
                ],
                [
                    'account_id' => $account->id,
                    'type' => 'credit',
                    'amount' => $income->total,
                    'description' => $income->description,
                ],
            ],
        ]);
    }

    /**
     * Get cash account based on payment method
     */
    private function getCashAccount(string $paymentMethod): \App\Models\ChartOfAccount
    {
        $accountCode = match ($paymentMethod) {
            'cash' => '1010',
            'bank_transfer' => '1020',
            default => '1010',
        };

        $repo = app(\App\Core\Repositories\ChartOfAccountRepository::class);
        $cashAccount = $repo->getByCode($accountCode);

        if (! $cashAccount) {
            throw new Exception('Cash account not found. Please configure chart of accounts.');
        }

        return $cashAccount;
    }
}
