<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Models\Category;
use App\Models\Currency;
use App\Models\Tag;
use App\Models\Transaction;
use App\Http\Requests\StoreTransactionRequest;
use App\Http\Requests\UpdateTransactionRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

class TransactionController extends Controller
{
    /**
     * Display a listing of transactions.
     */
    public function index(Request $request)
    {
        $user = $request->user();

        $query = Transaction::where('user_id', $user->id)
            ->with(['account', 'category', 'currency', 'tags']);

        // Apply filters
        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        if ($request->filled('account_id')) {
            $query->where('account_id', $request->account_id);
        }

        if ($request->filled('category_id')) {
            $query->where('category_id', $request->category_id);
        }

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

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

        if ($request->filled('search')) {
            $query->search($request->search);
        }

        if ($request->filled('tag_id')) {
            $query->whereHas('tags', function ($q) use ($request) {
                $q->where('tags.id', $request->tag_id);
            });
        }

        // Sorting
        $sortBy = $request->get('sort', 'date');
        $sortDir = $request->get('dir', 'desc');
        $query->orderBy($sortBy, $sortDir);

        if ($sortBy !== 'created_at') {
            $query->orderBy('created_at', 'desc');
        }

        $transactions = $query->paginate(25)->withQueryString();

        // Get filter options
        $accounts = $user->activeAccounts()->get();
        $categories = Category::forUser($user->id)->active()->parents()->with('children')->get();
        $tags = $user->tags()->get();

        // Calculate totals for filtered results
        $totals = [
            'income' => (clone $query)->where('type', 'income')->sum('amount'),
            'expense' => (clone $query)->where('type', 'expense')->sum('amount'),
        ];

        return view('transactions.index', compact(
            'transactions',
            'accounts',
            'categories',
            'tags',
            'totals'
        ));
    }

    /**
     * Show the form for creating a new transaction.
     */
    public function create(Request $request)
    {
        $user = $request->user();

        $accounts = $user->activeAccounts()->with('currency')->get();
        $categories = Category::forUser($user->id)->active()->parents()->with('children')->get();
        $tags = $user->tags()->get();

        $type = $request->get('type', 'expense');
        $accountId = $request->get('account_id');

        return view('transactions.create', compact(
            'accounts',
            'categories',
            'tags',
            'type',
            'accountId'
        ));
    }

    /**
     * Store a newly created transaction.
     */
    public function store(StoreTransactionRequest $request)
    {
        $data = $request->validated();
        $data['user_id'] = $request->user()->id;

        // Get currency from account
        $account = Account::findOrFail($data['account_id']);
        $data['currency_id'] = $account->currency_id;

        // Set default time if not provided
        if (empty($data['time'])) {
            $data['time'] = now()->format('H:i:s');
        } elseif (strlen($data['time']) === 5) {
            // If time is in H:i format, add seconds
            $data['time'] = $data['time'] . ':00';
        }

        // Handle attachment upload
        if ($request->hasFile('attachment')) {
            $file = $request->file('attachment');
            $filename = time() . '_' . $file->getClientOriginalName();
            $path = $file->storeAs('transactions', $filename, 'public');
            $data['attachment'] = $path;
            $data['attachment_name'] = $file->getClientOriginalName();
        }

        $transaction = Transaction::create($data);

        // Attach tags
        if ($request->filled('tags')) {
            $transaction->tags()->sync($request->tags);
        }

        if ($request->expectsJson()) {
            return response()->json([
                'success' => true,
                'message' => 'Transaksi berhasil dibuat.',
                'transaction' => $transaction->load(['account', 'category', 'currency', 'tags']),
            ]);
        }

        return redirect()->route('transactions.index')
            ->with('success', 'Transaksi berhasil disimpan.');
    }

    /**
     * Display the specified transaction.
     */
    public function show(Transaction $transaction)
    {
        // Authorization handled by route model binding in AppServiceProvider
        $transaction->load(['account', 'category', 'currency', 'tags', 'recurringTransaction']);

        return view('transactions.show', compact('transaction'));
    }

    /**
     * Show the form for editing the transaction.
     */
    public function edit(Request $request, Transaction $transaction)
    {
        // Authorization handled by route model binding in AppServiceProvider
        $user = $request->user();

        $accounts = $user->activeAccounts()->with('currency')->get();
        $categories = Category::forUser($user->id)->active()->parents()->with('children')->get();
        $tags = $user->tags()->get();

        $transaction->load('tags');

        return view('transactions.edit', compact(
            'transaction',
            'accounts',
            'categories',
            'tags'
        ));
    }

    /**
     * Update the specified transaction.
     */
    public function update(UpdateTransactionRequest $request, Transaction $transaction)
    {
        // Authorization handled by route model binding in AppServiceProvider
        $data = $request->validated();

        // Update currency if account changed
        if (isset($data['account_id']) && $data['account_id'] != $transaction->account_id) {
            $account = Account::findOrFail($data['account_id']);
            $data['currency_id'] = $account->currency_id;
        }

        // Handle time format (add seconds if only H:i)
        if (!empty($data['time']) && strlen($data['time']) === 5) {
            $data['time'] = $data['time'] . ':00';
        }

        // Handle remove attachment
        if ($request->boolean('remove_attachment') && $transaction->attachment) {
            Storage::disk('public')->delete($transaction->attachment);
            $data['attachment'] = null;
            $data['attachment_name'] = null;
        }

        // Handle attachment upload
        if ($request->hasFile('attachment')) {
            // Delete old attachment
            if ($transaction->attachment) {
                Storage::disk('public')->delete($transaction->attachment);
            }
            $file = $request->file('attachment');
            $filename = time() . '_' . $file->getClientOriginalName();
            $path = $file->storeAs('transactions', $filename, 'public');
            $data['attachment'] = $path;
            $data['attachment_name'] = $file->getClientOriginalName();
        }

        $transaction->update($data);

        // Sync tags
        if ($request->has('tags')) {
            $transaction->tags()->sync($request->tags ?? []);
        }

        return redirect()->route('transactions.index')
            ->with('success', 'Transaksi berhasil diperbarui.');
    }

    /**
     * Remove the specified transaction.
     */
    public function destroy(Transaction $transaction)
    {
        // Authorization handled by route model binding in AppServiceProvider
        // Delete attachment if exists
        if ($transaction->attachment) {
            Storage::disk('public')->delete($transaction->attachment);
        }

        $transaction->delete();

        return redirect()->route('transactions.index')
            ->with('success', 'Transaksi berhasil dihapus.');
    }

    /**
     * Bulk delete transactions.
     */
    public function bulkDestroy(Request $request)
    {
        $validated = $request->validate([
            'transactions' => 'required|array',
            'transactions.*' => 'integer|exists:transactions,id',
        ]);

        $count = Transaction::where('user_id', $request->user()->id)
            ->whereIn('id', $validated['transactions'])
            ->delete();

        return redirect()->route('transactions.index')
            ->with('success', "{$count} transactions deleted successfully.");
    }

    /**
     * Duplicate a transaction.
     */
    public function duplicate(Transaction $transaction)
    {
        // Authorization handled by route model binding in AppServiceProvider
        $newTransaction = $transaction->duplicate();

        return redirect()->route('transactions.edit', $newTransaction)
            ->with('success', 'Transaction duplicated. You can edit it now.');
    }

    /**
     * Quick add transaction (AJAX).
     */
    public function quickStore(Request $request)
    {
        $validated = $request->validate([
            'account_id' => 'required|exists:accounts,id',
            'category_id' => 'required|exists:categories,id',
            'type' => 'required|in:income,expense',
            'amount' => 'required|numeric|min:0.01',
            'description' => 'required|string|max:255',
            'date' => 'nullable|date',
        ]);

        $account = Account::findOrFail($validated['account_id']);

        // Verify account belongs to user
        if ($account->user_id !== $request->user()->id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $transaction = Transaction::create([
            'user_id' => $request->user()->id,
            'account_id' => $validated['account_id'],
            'category_id' => $validated['category_id'],
            'currency_id' => $account->currency_id,
            'type' => $validated['type'],
            'amount' => $validated['amount'],
            'description' => $validated['description'],
            'date' => $validated['date'] ?? now()->toDateString(),
        ]);

        return response()->json([
            'success' => true,
            'transaction' => $transaction->load(['account', 'category', 'currency']),
        ]);
    }
}
