<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Contribution;
use App\Models\Project;
use App\Models\User;
use App\Models\ExpectedContribution;
use App\Exports\ContributionsExport;
use Maatwebsite\Excel\Facades\Excel;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;

class ContributionController extends Controller
{
    private function getFilteredQuery(Request $request)
    {
        $status = $request->input('status');

        if ($status === 'en_attente') {
            $query = ExpectedContribution::with(['user', 'project', 'contributions'])
                ->where('status', '!=', 'paye')
                ->whereDate('due_date', '<', now());

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

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

            // Date Filtering
            $startDate = $request->input('start_date');
            $endDate = $request->input('end_date');

            if ($startDate) {
                $query->whereDate('due_date', '>=', $startDate);
            }
            if ($endDate) {
                $query->whereDate('due_date', '<=', $endDate);
            }

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

            return ['query' => $query, 'isLatePayment' => true, 'startDate' => $startDate, 'endDate' => $endDate];
        } else {
            $query = Contribution::with(['user', 'project']);

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

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

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

            // Date Filtering
            $startDate = $request->input('start_date');
            $endDate = $request->input('end_date');

            if ($startDate) {
                $query->whereDate('payment_date', '>=', $startDate);
            }
            if ($endDate) {
                $query->whereDate('payment_date', '<=', $endDate);
            }

            // Frequency Filtering
            if ($request->filled('frequency')) {
                $query->whereHas('project', function ($q) use ($request) {
                    $q->where('frequency', $request->frequency);
                });
            }

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

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

            return ['query' => $query, 'isLatePayment' => false, 'startDate' => $startDate, 'endDate' => $endDate];
        }
    }

    public function index(Request $request)
    {
        // Set default dates if not provided
        if (!$request->has('start_date')) {
            $request->merge(['start_date' => now()->startOfMonth()->format('Y-m-d')]);
        }
        if (!$request->has('end_date')) {
            $request->merge(['end_date' => now()->endOfMonth()->format('Y-m-d')]);
        }

        // Default to active year if not specified
        if (!$request->has('management_year_id')) {
            $activeYear = \App\Models\ManagementYear::where('status', 'actif')->first();
            if ($activeYear) {
                $request->merge(['management_year_id' => $activeYear->id]);
            }
        }

        $filterResult = $this->getFilteredQuery($request);
        $query = $filterResult['query'];
        $isLatePayment = $filterResult['isLatePayment'];

        $totalAmount = $query->sum('amount');
        $currency = \App\Models\Setting::get('currency', 'FCFA');

        if ($isLatePayment) {
            $contributions = $query->latest('due_date')->paginate(10)->through(function ($item) {
                $item->payment_date = $item->due_date;
                return $item;
            });
        } else {
            $contributions = $query->latest('payment_date')->paginate(10);
        }

        $projects = Project::all();
        $contributions->appends($request->all());

        $members = User::where('role', 'membre')->where('status', 'active')->get();
        $years = \App\Models\ManagementYear::orderBy('year', 'desc')->get();
        $accounts = \App\Models\Account::where('is_active', true)->get();

        return view('admin.contributions.index', compact('contributions', 'projects', 'members', 'years', 'accounts', 'totalAmount', 'currency', 'isLatePayment'));
    }

    public function exportExcel(Request $request)
    {
        $filterResult = $this->getFilteredQuery($request);
        $query = $filterResult['query'];
        $isLatePayment = $filterResult['isLatePayment'];

        $filename = $isLatePayment ? 'retards-cotisations.xlsx' : 'liste-cotisations.xlsx';
        return Excel::download(new ContributionsExport($query, $isLatePayment), $filename);
    }

    public function exportPdf(Request $request)
    {
        $filterResult = $this->getFilteredQuery($request);
        $query = $filterResult['query'];
        $isLatePayment = $filterResult['isLatePayment'];
        $startDate = $filterResult['startDate'];
        $endDate = $filterResult['endDate'];

        $data = $query->get();
        $total = $query->sum('amount');

        // Fetching filter display values
        $filters = [
            'project' => $request->project_id ? Project::find($request->project_id)?->name : null,
            'member' => $request->user_id ? User::find($request->user_id) : null, // We might want full name, but let's pass object or string. String is safer if object is null.
            // Let's pass strings for simplicity in view or handle nulls there.
            // Let's pass the model if found, easy to access name.
            'member_name' => $request->user_id ? User::find($request->user_id)?->first_name . ' ' . User::find($request->user_id)?->last_name : null,
            'status' => $request->status,
            'frequency' => $request->frequency,
        ];

        $currency = \App\Models\Setting::get('currency', 'FCFA');

        $pdf = Pdf::loadView('admin.contributions.export-pdf', compact('data', 'total', 'isLatePayment', 'startDate', 'endDate', 'filters', 'currency'));
        $filename = $isLatePayment ? 'retards-cotisations.pdf' : 'liste-cotisations.pdf';

        return $pdf->stream($filename);
    }

    public function create(Request $request)
    {
        // Charger les projets actifs avec leurs membres et les cotisations attendues NON payées de ces membres
        $projects = Project::where('status', 'actif')->with([
            'members' => function ($q) {
                $q->with([
                    'expectedContributions' => function ($query) {
                        // On charge toutes les cotisations attendues impayées de l'utilisateur
                        // On filtrera par project_id dans la vue pour ne pas mélanger
                        $query->where('status', '!=', 'paye')->orderBy('due_date');
                    }
                ]);
            }
        ])->get();
        // $members is no longer strictly needed for the initial load if we rely on project->members, 
        // but we'll keep it or better yet, make it an empty collection initially if we want to force project selection first.
        // However, to satisfy the requirement "only see members linked to this project", 
        // we can just pass the projects with their members.
        // Let's keep $members as all members just in case, or remove it if strictly enforced.
        // Given the request, it's better to NOT pass all members to avoid confusion, or pass them as a fallback.
        // But for the dynamic filtering, we will use the data from $projects.

        $members = User::where('role', 'membre')->where('status', 'active')->get();
        $accounts = \App\Models\Account::where('is_active', true)->get();
        $years = \App\Models\ManagementYear::where('status', 'actif')->orderBy('year', 'desc')->get();

        $selectedProject = $request->project_id ? Project::find($request->project_id) : null;
        $selectedMember = $request->user_id ? User::find($request->user_id) : null;
        $selectedExpectedContributionId = $request->expected_contribution_id;
        $selectedAmount = $request->amount;

        return view('admin.contributions.create', compact('projects', 'members', 'accounts', 'years', 'selectedProject', 'selectedMember', 'selectedExpectedContributionId', 'selectedAmount'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'project_id' => 'required|exists:projects,id',
            'management_year_id' => 'required|exists:management_years,id',
            'account_id' => 'required|exists:accounts,id',
            'user_id' => 'required|exists:users,id',
            'amount' => 'required|numeric|min:0',
            'payment_date' => 'required|date',
            'status' => 'required|in:paye,non_paye',
            'notes' => 'nullable|string',
            'expected_contribution_id' => 'nullable|exists:expected_contributions,id',
        ]);

        $validated['recorded_by'] = auth()->id();

        $contribution = Contribution::create($validated);

        // Mettre à jour le solde du compte
        if ($validated['status'] === 'paye') {
            \App\Models\Account::find($validated['account_id'])->increment('balance', $validated['amount']);
        }

        // Mettre à jour le statut de la cotisation attendue si fournie et si payée
        if ($request->filled('expected_contribution_id') && $validated['status'] === 'paye') {
            ExpectedContribution::where('id', $request->expected_contribution_id)
                ->update(['status' => 'paye']);
        }

        return redirect()->route('admin.contributions.index')
            ->with('success', 'Cotisation enregistrée avec succès.');
    }

    public function show(Contribution $contribution)
    {
        $contribution->load(['user', 'project', 'recorder']);
        return view('admin.contributions.show', compact('contribution'));
    }

    public function edit(Contribution $contribution)
    {
        $projects = Project::where('status', 'actif')->with([
            'members' => function ($q) {
                $q->with([
                    'expectedContributions' => function ($query) {
                        $query->where('status', '!=', 'paye')->orderBy('due_date');
                    }
                ]);
            }
        ])->get();

        $members = User::where('role', 'membre')->where('status', 'active')->get();
        $accounts = \App\Models\Account::where('is_active', true)->get();
        $years = \App\Models\ManagementYear::where('status', 'actif')->orderBy('year', 'desc')->get();
        
        return view('admin.contributions.edit', compact('contribution', 'projects', 'members', 'accounts', 'years'));
    }

    public function update(Request $request, Contribution $contribution)
    {
        $validated = $request->validate([
            'project_id' => 'required|exists:projects,id',
            'management_year_id' => 'required|exists:management_years,id',
            'account_id' => 'required|exists:accounts,id',
            'user_id' => 'required|exists:users,id',
            'amount' => 'required|numeric|min:0',
            'payment_date' => 'required|date',
            'status' => 'required|in:paye,non_paye',
            'notes' => 'nullable|string',
            'expected_contribution_id' => 'nullable|exists:expected_contributions,id',
        ]);

        $oldAmount = $contribution->amount;
        $oldAccountId = $contribution->account_id;
        $oldStatus = $contribution->status;
        $oldExpectedId = $contribution->expected_contribution_id;
        $newExpectedId = $request->expected_contribution_id;

        $contribution->update($validated);

        // Ajuster les soldes des comptes
        if ($oldStatus === 'paye') {
            \App\Models\Account::find($oldAccountId)->decrement('balance', $oldAmount);
        }
        
        if ($validated['status'] === 'paye') {
            \App\Models\Account::find($validated['account_id'])->increment('balance', $validated['amount']);
        }

        // Si la cotisation attendue a changé
        if ($oldExpectedId != $newExpectedId) {
            // Remettre l'ancienne en 'attendu' s'il y en avait une
            if ($oldExpectedId) {
                ExpectedContribution::where('id', $oldExpectedId)->update(['status' => 'attendu']);
            }
            // Marquer la nouvelle comme 'paye'
            if ($newExpectedId) {
                ExpectedContribution::where('id', $newExpectedId)->update(['status' => 'paye']);
            }
        }

        return redirect()->route('admin.contributions.index')
            ->with('success', 'Cotisation mise à jour avec succès.');
    }

    public function destroy(Contribution $contribution)
    {
        // Ajuster le solde du compte avant suppression
        if ($contribution->status === 'paye' && $contribution->account_id) {
            \App\Models\Account::find($contribution->account_id)->decrement('balance', $contribution->amount);
        }

        // Remettre la cotisation attendue en 'attendu'
        if ($contribution->expected_contribution_id) {
            ExpectedContribution::where('id', $contribution->expected_contribution_id)->update(['status' => 'attendu']);
        }

        $contribution->delete();

        return redirect()->route('admin.contributions.index')
            ->with('success', 'Cotisation supprimée avec succès.');
    }
}
