<?php

namespace Tests\Feature\Api;

use App\Models\CashRegister;
use App\Models\Expense;
use App\Models\ExpenseCategory;

class ExpenseManagementTest extends ApiTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        $this->createAuthenticatedUser();
    }

    // ==================== EXPENSE CATEGORY TESTS ====================

    public function test_can_list_expense_categories(): void
    {
        ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        ExpenseCategory::create(['name' => 'Supplies', 'is_active' => true]);

        $response = $this->getJson('/api/v1/expense-categories');

        $this->assertSuccessResponse($response);
        $this->assertCount(2, $response->json('data'));
    }

    public function test_can_create_expense_category(): void
    {
        $response = $this->postJson('/api/v1/expense-categories', [
            'name' => 'Rent',
            'description' => 'Monthly rent payments',
            'is_active' => true,
        ]);

        $this->assertSuccessResponse($response, 201);
        $this->assertDatabaseHas('expense_categories', ['name' => 'Rent']);
    }

    public function test_can_show_expense_category(): void
    {
        $category = ExpenseCategory::create(['name' => 'Show Category', 'is_active' => true]);

        $response = $this->getJson("/api/v1/expense-categories/{$category->id}");

        $this->assertSuccessResponse($response);
        $response->assertJson(['data' => ['name' => 'Show Category']]);
    }

    public function test_can_update_expense_category(): void
    {
        $category = ExpenseCategory::create(['name' => 'Old Name', 'is_active' => true]);

        $response = $this->putJson("/api/v1/expense-categories/{$category->id}", [
            'name' => 'Updated Name',
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('expense_categories', ['id' => $category->id, 'name' => 'Updated Name']);
    }

    public function test_can_delete_expense_category(): void
    {
        $category = ExpenseCategory::create(['name' => 'Delete Me', 'is_active' => true]);

        $response = $this->deleteJson("/api/v1/expense-categories/{$category->id}");

        $this->assertSuccessResponse($response, 200, false);
    }

    // ==================== EXPENSE TESTS ====================

    public function test_can_list_expenses(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Electricity Bill',
            'amount' => 500.00,
            'payment_method' => 'bank',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->getJson('/api/v1/expenses');

        $this->assertSuccessResponse($response);
        $this->assertCount(1, $response->json('data'));
    }

    public function test_can_create_expense(): void
    {
        $category = ExpenseCategory::create(['name' => 'Supplies', 'is_active' => true]);

        $response = $this->postJson('/api/v1/expenses', [
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'title' => 'Office Supplies',
            'description' => 'Pens and paper',
            'amount' => 150.00,
            'payment_method' => 'cash',
            'expense_date' => now()->toDateString(),
        ]);

        $this->assertSuccessResponse($response, 201);
        $this->assertDatabaseHas('expenses', ['title' => 'Office Supplies', 'amount' => 150.00]);
    }

    public function test_can_show_expense(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        $expense = Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Show Expense',
            'amount' => 200.00,
            'payment_method' => 'cash',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->getJson("/api/v1/expenses/{$expense->id}");

        $this->assertSuccessResponse($response);
        $response->assertJson(['data' => ['title' => 'Show Expense']]);
    }

    public function test_can_update_expense(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        $expense = Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Old Title',
            'amount' => 200.00,
            'payment_method' => 'cash',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->putJson("/api/v1/expenses/{$expense->id}", [
            'title' => 'Updated Title',
            'amount' => 250.00,
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('expenses', ['id' => $expense->id, 'title' => 'Updated Title', 'amount' => 250.00]);
    }

    public function test_can_approve_expense(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        $expense = Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Approve Me',
            'amount' => 300.00,
            'payment_method' => 'cash',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->postJson("/api/v1/expenses/{$expense->id}/approve");

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('expenses', ['id' => $expense->id, 'status' => 'approved']);
    }

    public function test_can_reject_expense(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        $expense = Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Reject Me',
            'amount' => 300.00,
            'payment_method' => 'cash',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->postJson("/api/v1/expenses/{$expense->id}/reject", [
            'reason' => 'Insufficient documentation',
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('expenses', ['id' => $expense->id, 'status' => 'rejected']);
    }

    public function test_can_list_expenses_by_branch(): void
    {
        $category = ExpenseCategory::create(['name' => 'Utilities', 'is_active' => true]);
        Expense::create([
            'branch_id' => $this->branch->id,
            'expense_category_id' => $category->id,
            'user_id' => $this->user->id,
            'title' => 'Branch Expense',
            'amount' => 500.00,
            'payment_method' => 'bank',
            'expense_date' => now(),
            'status' => 'pending',
        ]);

        $response = $this->getJson("/api/v1/expenses/branch/{$this->branch->id}");

        $this->assertSuccessResponse($response);
        $this->assertCount(1, $response->json('data'));
    }

    // ==================== CASH REGISTER TESTS ====================

    public function test_can_list_cash_registers(): void
    {
        CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->getJson('/api/v1/cash-registers');

        $this->assertSuccessResponse($response);
        $this->assertCount(1, $response->json('data'));
    }

    public function test_can_open_cash_register(): void
    {
        $response = $this->postJson("/api/v1/branches/{$this->branch->id}/cash-register/open", [
            'opening_balance' => 500.00,
        ]);

        $this->assertSuccessResponse($response, 201);
        $this->assertDatabaseHas('cash_registers', [
            'branch_id' => $this->branch->id,
            'opening_balance' => 500.00,
            'status' => 'open',
        ]);
    }

    public function test_cannot_open_cash_register_if_one_is_already_open(): void
    {
        CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->postJson("/api/v1/branches/{$this->branch->id}/cash-register/open", [
            'opening_balance' => 500.00,
        ]);

        $this->assertErrorResponse($response, 400);
    }

    public function test_can_close_cash_register(): void
    {
        $register = CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->postJson("/api/v1/cash-registers/{$register->id}/close", [
            'actual_balance' => 1500.00,
            'notes' => 'Good day',
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('cash_registers', [
            'id' => $register->id,
            'status' => 'closed',
            'actual_balance' => 1500.00,
        ]);
    }

    public function test_can_add_cash_to_register(): void
    {
        $register = CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->postJson("/api/v1/cash-registers/{$register->id}/add-cash", [
            'amount' => 200.00,
            'notes' => 'Float addition',
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('cash_register_transactions', [
            'cash_register_id' => $register->id,
            'type' => 'cash_in',
            'amount' => 200.00,
        ]);
    }

    public function test_can_remove_cash_from_register(): void
    {
        $register = CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->postJson("/api/v1/cash-registers/{$register->id}/remove-cash", [
            'amount' => 100.00,
            'notes' => 'Bank deposit',
        ]);

        $this->assertSuccessResponse($response);
        $this->assertDatabaseHas('cash_register_transactions', [
            'cash_register_id' => $register->id,
            'type' => 'cash_out',
            'amount' => 100.00,
        ]);
    }

    public function test_can_get_cash_register_transactions(): void
    {
        $register = CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);
        $register->transactions()->create([
            'user_id' => $this->user->id,
            'type' => 'cash_in',
            'amount' => 500.00,
            'notes' => 'Sale',
        ]);

        $response = $this->getJson("/api/v1/cash-registers/{$register->id}/transactions");

        $this->assertSuccessResponse($response);
        $this->assertCount(1, $response->json('data'));
    }

    public function test_can_get_cash_register_summary(): void
    {
        $register = CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->getJson("/api/v1/cash-registers/{$register->id}/summary");

        $this->assertSuccessResponse($response);
    }

    public function test_can_get_current_open_register_for_branch(): void
    {
        CashRegister::create([
            'branch_id' => $this->branch->id,
            'user_id' => $this->user->id,
            'opening_balance' => 1000.00,
            'status' => 'open',
            'register_date' => now()->toDateString(),
        ]);

        $response = $this->getJson("/api/v1/branches/{$this->branch->id}/cash-register/current");

        $this->assertSuccessResponse($response);
    }
}
