<?php

namespace App\Http\Controllers;

use App\Models\CashMutation;
use App\Models\Deposit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class DepositController extends Controller
{
    private const AUTO_DEPOSIT_TAG = '[AUTO-DEPOSIT]';

    public function __construct()
    {
        $this->middleware(\App\Http\Middleware\PermissionMiddleware::class . ':manage deposits')
            ->only(['create', 'store', 'destroy']);
    }

    public function index(Request $request)
    {
        $query = Deposit::with(['creator', 'paymentAccount']);

        if ($request->filled('start_date')) {
            $query->where('deposit_date', '>=', $request->start_date);
        }

        if ($request->filled('end_date')) {
            $query->where('deposit_date', '<=', $request->end_date);
        }

        $deposits = $query->latest('deposit_date')->paginate(15)->withQueryString();

        $summary = [
            'total_amount' => Deposit::when($request->filled('start_date'), fn ($q) => $q->where('deposit_date', '>=', $request->start_date))
                ->when($request->filled('end_date'), fn ($q) => $q->where('deposit_date', '<=', $request->end_date))
                ->sum('amount'),
            'total_count' => $deposits->total(),
        ];

        return view('pages.finance.deposits.index', [
            'title' => 'Data Setoran',
            'deposits' => $deposits,
            'summary' => $summary,
        ]);
    }

    public function create()
    {
        return view('pages.finance.deposits.create', [
            'title' => 'Tambah Setoran',
        ]);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'amount' => ['required', 'numeric', 'min:1'],
            'deposit_date' => ['required', 'date'],
            'reference_number' => ['nullable', 'string', 'max:100'],
            'notes' => ['nullable', 'string', 'max:500'],
        ]);

        DB::transaction(function () use ($validated) {
            $deposit = Deposit::create([
                'amount' => $validated['amount'],
                'deposit_date' => $validated['deposit_date'],
                'reference_number' => $validated['reference_number'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'created_by' => Auth::id(),
                'payment_account_id' => null,
            ]);

            CashMutation::create([
                'amount' => $deposit->amount,
                'mutation_date' => $deposit->deposit_date,
                'from_account' => 'cash',
                'to_account' => 'bank',
                'notes' => $this->buildDepositMutationNote($deposit),
                'user_id' => Auth::id(),
            ]);
        });

        return redirect()->route('finance.deposits.index')
            ->with('success', 'Setoran berhasil ditambahkan.');
    }

    public function destroy(Deposit $deposit)
    {
        DB::transaction(function () use ($deposit) {
            CashMutation::query()
                ->where('from_account', 'cash')
                ->where('to_account', 'bank')
                ->where('notes', 'like', '%' . $this->depositMutationToken($deposit) . '%')
                ->delete();

            $deposit->delete();
        });

        return redirect()->route('finance.deposits.index')
            ->with('success', 'Setoran berhasil dihapus.');
    }

    private function depositMutationToken(Deposit $deposit): string
    {
        return '[DEPOSIT_ID:' . $deposit->id . ']';
    }

    private function buildDepositMutationNote(Deposit $deposit): string
    {
        $parts = [
            self::AUTO_DEPOSIT_TAG,
            $this->depositMutationToken($deposit),
            'Setoran CASH ke BANK',
        ];

        if (!empty($deposit->reference_number)) {
            $parts[] = 'Ref: ' . $deposit->reference_number;
        }

        if (!empty($deposit->notes)) {
            $parts[] = 'Catatan: ' . $deposit->notes;
        }

        return Str::limit(implode(' | ', $parts), 500, '');
    }
}