<?php

namespace App\Http\Controllers\Membership\Admin;

use App\Http\Controllers\Controller;
use App\Models\Contribution;
use App\Models\MembershipCategory;
use App\Models\Member;
use App\Services\ContributionService;
use Illuminate\Http\Request;

class ContributionController extends Controller
{
    protected ContributionService $contributionService;

    public function __construct(ContributionService $contributionService)
    {
        $this->contributionService = $contributionService;
    }

    /**
     * Display contribution management dashboard.
     */
    public function index(Request $request)
    {
        abort_unless(auth()->user()->can('view contributions'), 403);

        $statistics = $this->contributionService->getStatistics($request->only(['category_id', 'from_date', 'to_date']));

        $query = Contribution::with(['member.user', 'membershipCategory', 'contributionFee']);

        // Search
        if ($request->search) {
            $query->where(function ($q) use ($request) {
                $q->where('reference_number', 'like', "%{$request->search}%")
                    ->orWhereHas('member.user', function ($q) use ($request) {
                        $q->where('name', 'like', "%{$request->search}%")
                            ->orWhere('email', 'like', "%{$request->search}%");
                    });
            });
        }

        // Filters
        if ($request->status) {
            $query->where('status', $request->status);
        }

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

        if ($request->from_date) {
            $query->where('due_date', '>=', $request->from_date);
        }

        if ($request->to_date) {
            $query->where('due_date', '<=', $request->to_date);
        }

        if ($request->cycle) {
            $query->whereHas('contributionFee', function ($q) use ($request) {
                $q->where('cycle', $request->cycle);
            });
        }

        $contributions = $query->latest()->paginate(15);
        $categories = MembershipCategory::all();

        return view('contributions.admin.index', compact('contributions', 'categories', 'statistics'));
    }

    /**
     * Display contribution details.
     */
    public function show(Contribution $contribution)
    {
        abort_unless(auth()->user()->can('view contributions'), 403);

        $contribution->load(['member.user', 'membershipCategory', 'contributionFee']);

        return view('contributions.admin.show', compact('contribution'));
    }

    /**
     * Show form to create a new contribution.
     */
    public function create(Request $request)
    {
        abort_unless(auth()->user()->can('create contributions'), 403);

        $categories = MembershipCategory::active()->get();
        $members = Member::active()->with('user')->get();

        return view('contributions.admin.create', compact('categories', 'members'));
    }

    /**
     * Store a new contribution.
     */
    public function store(Request $request)
    {
        abort_unless(auth()->user()->can('create contributions'), 403);

        $request->validate([
            'member_id' => 'required|exists:members,id',
            'membership_category_id' => 'required|exists:membership_categories,id',
            'amount' => 'required|numeric|min:0.01',
            'currency' => 'required|in:USD,SSP,KES,UGX',
            'due_date' => 'required|date',
            'period' => 'nullable|string|max:20',
            'notes' => 'nullable|string|max:500',
        ], [
            'member_id.required' => 'Please select a member.',
            'amount.required' => 'Amount is required.',
            'amount.min' => 'Amount must be greater than zero.',
            'due_date.required' => 'Due date is required.',
        ]);

        $member = Member::findOrFail($request->member_id);

        $contribution = $this->contributionService->createContribution($member, [
            'membership_category_id' => $request->membership_category_id,
            'contribution_fee_id' => $request->contribution_fee_id,
            'amount' => $request->amount,
            'currency' => $request->currency,
            'due_date' => $request->due_date,
            'period' => $request->period,
            'notes' => strip_tags($request->notes ?? ''),
        ], auth()->id());

        return redirect()->route('admin.contributions.show', $contribution)
            ->with('success', 'Contribution created successfully.');
    }

    /**
     * Generate bulk contributions for a category.
     */
    public function generateBulk(Request $request)
    {
        abort_unless(auth()->user()->can('create contributions'), 403);

        $request->validate([
            'membership_category_id' => 'required|exists:membership_categories,id',
            'contribution_fee_id' => 'nullable|exists:contribution_fees,id',
        ]);

        $category = MembershipCategory::findOrFail($request->membership_category_id);
        $fee = $request->contribution_fee_id 
            ? \App\Models\ContributionFee::findOrFail($request->contribution_fee_id)
            : null;

        $count = $this->contributionService->generateBulkContributions($category, $fee);

        return redirect()->route('admin.contributions.index')
            ->with('success', "Generated {$count} contributions.");
    }

    /**
     * Apply penalty to overdue contributions.
     */
    public function applyPenalties()
    {
        abort_unless(auth()->user()->can('edit contributions'), 403);

        $overdueContributions = Contribution::overdue()
            ->where('is_penalty_applied', false)
            ->get();

        $count = 0;
        foreach ($overdueContributions as $contribution) {
            $penaltyAmount = $this->contributionService->applyPenalty($contribution);
            if ($penaltyAmount > 0) {
                $count++;
            }
        }

        return redirect()->route('admin.contributions.index')
            ->with('success', "Applied penalties to {$count} contributions.");
    }

    /**
     * Export contributions.
     */
    public function export(Request $request)
    {
        abort_unless(auth()->user()->can('export contributions'), 403);

        $query = Contribution::with(['member.user', 'membershipCategory', 'contributionFee']);

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

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

        if ($request->from_date) {
            $query->where('due_date', '>=', $request->from_date);
        }

        if ($request->to_date) {
            $query->where('due_date', '<=', $request->to_date);
        }

        $contributions = $query->latest()->get();

        // Generate CSV
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="contributions-' . date('Y-m-d') . '.csv"',
        ];

        $callback = function () use ($contributions) {
            $file = fopen('php://output', 'w');
            fputcsv($file, ['Reference', 'Member', 'Category', 'Amount', 'Currency', 'Due Date', 'Status', 'Penalty', 'Paid Date']);

            foreach ($contributions as $contribution) {
                fputcsv($file, [
                    $contribution->reference_number,
                    $contribution->member?->full_name,
                    $contribution->membershipCategory?->name,
                    $contribution->amount,
                    $contribution->currency,
                    $contribution->due_date?->format('Y-m-d'),
                    $contribution->status,
                    $contribution->penalty_amount,
                    $contribution->paid_date?->format('Y-m-d'),
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }
}
